Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

physics/ODESolid.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: ODESolid.cpp 1031 2004-02-11 20:46:36Z jungd $
00019   $Revision: 1.6 $
00020   $Date: 2004-02-11 15:46:36 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <physics/ODESolid>
00026 #include <base/ref>
00027 
00028 // need to know about shapes to map them to ODE's equivelent geoms
00029 #include <physics/Box>
00030 #include <physics/Sphere>
00031 
00032 #include <physics/ODECollidableBody>
00033 #include <physics/ODESolidConnectedCollidableBody>
00034 
00035 
00036 using base::Point3;
00037 using base::Quat4;
00038 using base::Orient;
00039 using base::Vector3;
00040 using base::Matrix3;
00041 
00042 using base::copyMemory;
00043 
00044 using physics::Body;
00045 using physics::Shape;
00046 using physics::Material;
00047 using physics::MassProperties;
00048 using physics::ODESolid;
00049 using physics::Collidable;
00050 using physics::CollidableBody;
00051 using physics::ODECollidableBody;
00052 using physics::ODESolidConnectedCollidableBody;
00053 
00054 using physics::Box;
00055 using physics::Sphere;
00056 
00057 
00058   
00059 
00060 ODESolid::ODESolid(ref<const Shape> shape, ref<const Material> material)
00061   : Solid(shape, material), created(false)
00062 {
00063 }
00064 
00065 void ODESolid::create(dWorldID worldID) const
00066 {
00067   if (created)
00068     throw std::runtime_error(Exception("create() called twice"));
00069 
00070   this->worldID = worldID;
00071 
00072   bodyID = dBodyCreate(worldID);
00073   // initialize default state
00074   dBodySetPosition(bodyID, 0,0,0);
00075   dQuaternion q = { 1,0,0,0 };
00076   dBodySetQuaternion(bodyID, q);
00077   dBodySetLinearVel(bodyID, 0,0,0);
00078   dBodySetAngularVel(bodyID, 0,0,0);
00079 
00080   // calculate mass properties 
00081   MassProperties massProps( Solid::massProperties() );
00082 
00083   dMass odemass;
00084   dMassSetZero(&odemass);
00085   const Matrix3& Ibody(massProps.Ibody());
00086   dMassSetParameters(&odemass, massProps.mass,
00087                      0,0,0,
00088                      Ibody(1,1), Ibody(2,2), Ibody(3,3),
00089                      Ibody(1,2), Ibody(1,3), Ibody(2,3));
00090 
00091   dBodySetMass(bodyID, &odemass);
00092 
00093   created = true;
00094 }
00095 
00096 
00097 void ODESolid::destroy() const
00098 {
00099   if (created) {
00100     dBodyDestroy(bodyID);
00101     worldID = 0; 
00102     bodyID = 0;
00103     created = false;
00104   }
00105 }
00106 
00107 
00108 
00109 
00110 ODESolid::ODESolid(const Solid& s)
00111   : Solid(s)
00112 {
00113   // copy state (prev state will be lost)
00114   setPosition(s.getPosition());
00115   setOrientation(s.getOrientation());
00116   setVelocity(s.getVelocity());
00117   setAngVelocity(s.getAngVelocity());
00118   setEnabled(s.isEnabled());
00119 }
00120 
00121 ODESolid::~ODESolid() 
00122 {
00123   if (created) destroy();
00124 }
00125 
00126 
00127 MassProperties ODESolid::massProperties() const
00128 {
00129   if (!created) return Solid::massProperties();
00130 
00131   // get properties from ODE
00132   dMass odemass;
00133   dBodyGetMass(bodyID, &odemass);
00134 
00135   MassProperties massProps;
00136   massProps.mass = odemass.mass;
00137   massProps.centerOfMass = Point3(odemass.c[0], odemass.c[1], odemass.c[2]);
00138   Matrix3 Ibody;
00139   // get from standard ODE matrix format. order or row/col irrelevant as matrix is symmetric
00140   for(int r=1; r<3; r++)
00141     for(int c=1; c<3; c++)
00142       Ibody(r,c) = odemass.I[(r-1)*4+(c-1)];
00143   massProps.setIbody(Ibody);
00144 
00145   return massProps;
00146 }
00147 
00148 
00149 
00150 Body& ODESolid::operator=(const Body& b)
00151 {
00152   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return *this; }
00153 
00154   setPosition(b.getPosition());
00155   setOrientation(b.getOrientation());
00156   setVelocity(b.getVelocity());
00157   setAngVelocity(b.getAngVelocity());
00158   setEnabled(true);
00159   return *this;
00160 }
00161 
00162 
00163 void ODESolid::setEnabled(bool enable)
00164 {
00165   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00166 
00167   if (enable)
00168     dBodyEnable(bodyID);
00169   else
00170     dBodyDisable(bodyID);
00171 }
00172 
00173 bool ODESolid::isEnabled() const
00174 {
00175   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return false; }
00176 
00177   return dBodyIsEnabled(bodyID);
00178 }
00179 
00180 
00181 void ODESolid::setPosition(const Point3& x)
00182 {
00183   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00184 
00185   dBodySetPosition(bodyID, x.x, x.y, x.z);
00186 }
00187 
00188 void ODESolid::ODESolid::setOrientation(const Orient& orient)
00189 {
00190   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00191 
00192   dQuaternion quat;
00193   Quat4 q( orient );
00194   quat[0] = q.w; quat[1] = q.v.x; quat[2] = q.v.y; quat[3] = q.v.z;
00195   dBodySetQuaternion(bodyID, quat);
00196 }
00197 
00198 void ODESolid::setVelocity(const Vector3& v)
00199 {
00200   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00201 
00202   dBodySetLinearVel(bodyID, v.x, v.y, v.z);
00203 }
00204 
00205 void ODESolid::setAngVelocity(const Vector3& w)
00206 {
00207   if (!created) { Logln("Warning: no effect until added to SolidSystem"); return; }
00208 
00209   dBodySetAngularVel(bodyID, w.x, w.y, w.z);
00210 
00211 }
00212 
00213 Point3  ODESolid::getPosition() const
00214 {
00215   if (!created) return Point3(); 
00216 
00217   const dReal* pos = dBodyGetPosition(bodyID);
00218   return Point3(pos[0],pos[1],pos[2]);
00219 }
00220 
00221 Orient  ODESolid::getOrientation() const
00222 {
00223   if (!created) return Orient(); 
00224 
00225   const dReal* orient = dBodyGetQuaternion(bodyID);
00226   return Orient(Quat4(orient[1], orient[2], orient[3], orient[0]));
00227 }
00228 
00229 Vector3 ODESolid::getVelocity() const
00230 {
00231   if (!created) return Vector3(); 
00232 
00233   const dReal* vel = dBodyGetLinearVel(bodyID);
00234   return Vector3(vel[0], vel[1], vel[2]);
00235 }
00236 
00237 
00238 Vector3 ODESolid::getAngVelocity() const
00239 {
00240   if (!created) return Vector3(); 
00241 
00242   const dReal* angVel = dBodyGetAngularVel(bodyID);
00243   return Vector3(angVel[0], angVel[1], angVel[2]);
00244 }
00245 
00246 void ODESolid::saveState()
00247 {
00248   if (!created) return; 
00249 
00250   copyMemory(dBodyGetPosition(bodyID), savedPos, 3);
00251   copyMemory(dBodyGetQuaternion(bodyID), savedOrient, 4);
00252   copyMemory(dBodyGetLinearVel(bodyID), savedVel, 3);
00253   copyMemory(dBodyGetAngularVel(bodyID), savedAngVel, 3);
00254 }
00255 
00256 void ODESolid::restoreState()
00257 {
00258   if (!created) return; 
00259 
00260   dBodySetPosition(bodyID, savedPos[0], savedPos[1], savedPos[2]);
00261   dBodySetQuaternion(bodyID, savedOrient);
00262   dBodySetLinearVel(bodyID, savedVel[0], savedVel[1], savedVel[2]);
00263   dBodySetAngularVel(bodyID, savedAngVel[0], savedAngVel[1], savedAngVel[2]);
00264 }
00265 
00266 Point3  ODESolid::getSavedPosition() const
00267 {
00268   if (!created) return Point3(); 
00269 
00270   return Point3(savedPos[0],savedPos[1],savedPos[2]);
00271 }
00272 
00273 Orient  ODESolid::getSavedOrientation() const
00274 {
00275   if (!created) return Orient(); 
00276 
00277   return Orient(Quat4(savedOrient[1], savedOrient[2], savedOrient[2], savedOrient[0]));
00278 }
00279 
00280 Vector3 ODESolid::getSavedVelocity() const
00281 {
00282   if (!created) return Vector3(); 
00283 
00284   return Vector3(savedVel[0], savedVel[1], savedVel[2]);
00285 }
00286 
00287 Vector3 ODESolid::getSavedAngVelocity() const
00288 {
00289   if (!created) return Vector3(); 
00290 
00291   return Vector3(savedAngVel[0], savedAngVel[1], savedAngVel[2]);
00292 }
00293 
00294 
00295 Point3 ODESolid::getRelPointPos(const Point3& p)
00296 {
00297   if (!created) return p; 
00298 
00299   dVector3 result;
00300   dBodyGetRelPointPos(bodyID, p.x, p.y, p.z, result);
00301   return Point3(result[0], result[1], result[2]);
00302 }
00303 
00304 Vector3 ODESolid::getRelPointVel(const Point3& p)
00305 {
00306   if (!created) return p; 
00307 
00308   dVector3 result;
00309   dBodyGetRelPointVel(bodyID, p.x, p.y, p.z, result);
00310   return Vector3(result[0], result[1], result[2]);
00311 }
00312 
00313 
00314 Point3 ODESolid::getGlobalPointRelPos(const Point3& p)
00315 {
00316   Point3 local(p - getPosition());
00317   getOrientation().invert().rotatePoint(local);
00318   return local;
00319 }
00320 
00321 
00322 
00323 void ODESolid::addForce(const Vector3& f)
00324 {
00325   if (!created) return; 
00326   dBodyAddForce(bodyID, f.x, f.y, f.z);
00327 }
00328 
00329 void ODESolid::addTorque(const Vector3& t)
00330 {
00331   if (!created) return; 
00332   dBodyAddTorque(bodyID, t.x, t.y, t.z);
00333 }
00334 
00335 void ODESolid::addRelForce(const Vector3& f)
00336 {
00337   if (!created) return; 
00338   dBodyAddRelForce(bodyID, f.x, f.y, f.z);
00339 }
00340 
00341 void ODESolid::addRelTorque(const Vector3& t)
00342 {
00343   if (!created) return; 
00344   dBodyAddRelTorque(bodyID, t.x, t.y, t.z);
00345 }
00346 
00347 void ODESolid::addForceAtPos(const Vector3& f, const Point3& p)
00348 {
00349   if (!created) return; 
00350   dBodyAddForceAtPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00351 }
00352 
00353 void ODESolid::addForceAtRelPos(const Vector3& f, const Point3& p)
00354 {
00355   if (!created) return; 
00356   dBodyAddForceAtRelPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00357 }
00358 
00359 void ODESolid::addRelForceAtPos(const Vector3& f, const Point3& p)
00360 {
00361   if (!created) return; 
00362   dBodyAddRelForceAtPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00363 }
00364 
00365 void ODESolid::addRelForceAtRelPos(const Vector3& f, const Point3& p)
00366 {
00367   if (!created) return; 
00368   dBodyAddRelForceAtRelPos(bodyID, f.x, f.y, f.z, p.x, p.y, p.z);
00369 }
00370 
00371 Vector3 ODESolid::getForce() const
00372 {
00373   if (!created) return Vector3(); 
00374 
00375   const dReal* f = dBodyGetForce(bodyID);
00376   return Vector3(f[0], f[1], f[32]);
00377 }
00378 
00379 Vector3 ODESolid::getTorque() const
00380 {
00381   if (!created) return Vector3(); 
00382 
00383   const dReal* t = dBodyGetTorque(bodyID);
00384   return Vector3(t[0], t[1], t[2]);
00385 }
00386 
00387 
00388 ref<Collidable> ODESolid::createCollidable(ref<const Shape> collisionShape, CollidableFlags flags)
00389 {
00390   if (!flags.test(SolidNotConnected)) {
00391     ref<Solid> self( this );
00392     return ref<CollidableBody>(NewObj ODESolidConnectedCollidableBody(self, collisionShape));
00393   }
00394   else
00395     return ref<CollidableBody>(NewObj ODECollidableBody(getShape()));
00396 }
00397 

Generated on Thu Jul 29 15:56:27 2004 for OpenSim by doxygen 1.3.6