Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

collision.cc

Go to the documentation of this file.
00001 /*
00002   svas_server -- virtual World Server of Svas
00003   Copyright (c) 2001, 2002 David Moreno Montero
00004  
00005  
00006   This program is free software; you can redistribute it and/or modify
00007   it under the terms of the GNU General Public License as published by
00008   the Free Software Foundation; either version 2 of the License, or
00009   (at your option) any later version.
00010  
00011   This program is distributed in the hope that it will be useful, but
00012   WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   General Public License for more details.
00015  
00016   You should have received a copy of the GNU General Public License
00017   along with this program; if not, write to the Free Software
00018   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00019   02111-1307, USA.  
00020 
00021 */
00022 
00023 #include <thread.h>
00024 #include <math.h>
00025 #include "collision.h"
00026 #include "world.h"
00027 #include "log.h"
00028 #include "agent.h"
00029 
00030 
00031 /**
00032  * Default  constructor, but not usefull at all.
00033  */
00034 Collision::Collision(){
00035   type=noCollision;
00036 }
00037 
00038 
00039 /**
00040  * This collision is against another cylinder. Just copy some data.
00041  */
00042 Collision::Collision(Cylinder *_cyl1, const Point3d &_pt1, Cylinder *_cyl2, const Point3d &_pt2, Vector3d &_normal, collisionType _type){
00043   cyl1=_cyl1;
00044   cyl2=_cyl2;
00045   pt1=_pt1;
00046   pt2=_pt2;
00047   normal=_normal;
00048   type=_type;
00049 }
00050 
00051 
00052 /**
00053  * This collision is always against the ground plane, so the normal is always (0,0,1)
00054  */
00055 Collision::Collision(Cylinder *_cyl, const Point3d &_pt, collisionType _type){
00056   cyl1=_cyl;
00057   cyl2=NULL;
00058   pt1=_pt;
00059   type=_type;
00060   normal=Vector3d(0,0,1);
00061 }
00062 
00063 /**
00064  * Two points of one cylinder are touching in some way a plane, the
00065  * only difference is that we should anulate moment
00066  */
00067 Collision::Collision(Cylinder *_cyl, const Point3d &_pt1, const Point3d &_pt2, collisionType _type){
00068   cyl1=_cyl;
00069   cyl2=NULL;
00070   pt1=_pt1;
00071   pt2=_pt2;
00072   type=_type;
00073   normal=Vector3d(0,0,1);
00074 }
00075 
00076 
00077 
00078 Collision::~Collision(){
00079 }
00080 
00081 /**
00082  * Resolves a collision
00083  */
00084 void Collision::resolve(){
00085   if (type==noCollision)
00086     return;
00087 
00088   if (cyl2==NULL)
00089     resolveGroundCollision();
00090   else
00091     resolveCylinderCollision();
00092 }
00093 
00094 void Collision::resolveGroundCollision(){
00095   Quaternion base=cyl1->orientationBase; // Faster access... and cleaner code
00096 
00097   Vector3d relativeVelocity=cyl1->velocity
00098     +(base.toWorld(cyl1->angularVelocity^pt1));
00099   
00100   Vector3d tangent(0,0,0);
00101   if ((relativeVelocity.X()!=0)&&(0!=relativeVelocity.Y())){
00102     tangent=Vector3d(relativeVelocity.X(), relativeVelocity.Y(),0); /// A quick way for this case (ground)
00103     tangent.normalize();
00104   }
00105 
00106   if (type==contact){
00107     Vector3d contactForce=Vector3d(0,0,0);
00108     Vector3d frictionForce=Vector3d(0,0,0);
00109 
00110     Vector3d A=cyl1->inertiaInverse*(cyl1->moment - (cyl1->angularVelocity^(cyl1->inertia*cyl1->angularVelocity)));
00111     Vector3d relativeAcceleration=(cyl1->force/cyl1->mass) +
00112       base.toWorld((cyl1->angularVelocity^(cyl1->angularVelocity^pt1)) +
00113            (A^pt1));
00114     
00115     if (relativeAcceleration.Z()<0) /// If accelerate vs. the ground
00116       contactForce=cyl1->mass*((-relativeAcceleration*normal)*normal);
00117     if (tangent!=Vector3d(0,0,0)){    /// Maybe there is also friction force
00118       frictionForce=(contactForce.module()*World::getGroundFrictionCoefficient())*tangent;
00119     }
00120 
00121 
00122     // Then I apply the forces
00123     cyl1->force+=contactForce+frictionForce;
00124     
00125     /// I convert from world force coordinates, to body
00126     contactForce=base.toBody(contactForce);
00127     frictionForce=base.toBody(frictionForce);
00128     /// and set the moment
00129     cyl1->moment+=pt1^(contactForce+frictionForce);
00130   }
00131 
00132   if (relativeVelocity.Z()<COLLISION_VELOCITY_EPSILUM){
00133 #define  mu World::getGroundFrictionCoefficient()
00134 #define  Cr World::getGroundRestitutionCoefficient()
00135     Point3d pt1w=base.toWorld(pt1);
00136 
00137     /// We calculate the impulse, this case is for the ground
00138     double j=(-(1+Cr)*(relativeVelocity.Z())) /
00139       ( (1/cyl1->mass) + (normal*(((pt1w^normal)*cyl1->inertiaInverse)^pt1w)) );
00140 
00141     j=fabs(j);
00142 
00143     if (j<0){
00144       log <<"J LESS THAN 0!!!"<<j<<endl;
00145       log <<relativeVelocity.toString()<<endl;
00146       log <<cyl1->velocity.toString()<<endl;
00147       cyl1->velocity=Vector3d(0,0,0);
00148       cyl1->angularVelocity=Vector3d(0,0,0);
00149       return;
00150     }
00151     if ((j>1e3)||(j<0))
00152       j=1e3;
00153 
00154     Vector3d impulse;
00155     if (fabs(relativeVelocity*tangent) > 0.0)
00156       impulse=(j*normal) + ((mu*j)*tangent);
00157     else
00158       impulse=j*normal;
00159 
00160     cyl1->velocity+=impulse/cyl1->mass;
00161     cyl1->angularVelocity+=( pt1^base.toBody(impulse) ) * cyl1->inertiaInverse;
00162   }
00163 }
00164 
00165 
00166 /**
00167  * Resolves the forces that have to applied against both cylinders, the
00168  * moments, and all those things, depending if they are in contact, o
00169  * penetrating...
00170  */
00171 void Collision::resolveCylinderCollision(){
00172   //log <<"Cylinder collision!!"<<endl;
00173 }

Generated on Mon Jun 17 19:53:44 2002 for Svas Server by doxygen1.2.16