Revision: 7493
http://playerstage.svn.sourceforge.net/playerstage/?rev=7493&view=rev
Author: hsujohnhsu
Date: 2009-03-17 00:34:59 +0000 (Tue, 17 Mar 2009)
Log Message:
-----------
added callbacks to get body rates.
added XML initialization for custom inertial matrices for bodies.
Modified Paths:
--------------
code/gazebo/branches/ogre-1.4.9/server/physics/Body.cc
code/gazebo/branches/ogre-1.4.9/server/physics/Body.hh
Modified: code/gazebo/branches/ogre-1.4.9/server/physics/Body.cc
===================================================================
--- code/gazebo/branches/ogre-1.4.9/server/physics/Body.cc 2009-03-17
00:23:10 UTC (rev 7492)
+++ code/gazebo/branches/ogre-1.4.9/server/physics/Body.cc 2009-03-17
00:34:59 UTC (rev 7493)
@@ -44,7 +44,15 @@
#include "PlaneGeom.hh"
#include "Geom.hh"
#include "Body.hh"
+#include "Simulator.hh"
+#include "World.hh"
+#include "ODEPhysics.hh"
+#include "PhysicsEngine.hh"
+#ifdef TIMING
+#include "Simulator.hh"// for timing
+#endif
+
using namespace gazebo;
////////////////////////////////////////////////////////////////////////////////
@@ -70,6 +78,22 @@
this->rpyP = new ParamT<Quatern>("rpy", Quatern(), 0);
this->rpyP->Callback( &Body::SetRotation, this );
+ this->turnGravityOffP = new ParamT<bool>("turnGravityOff", false, 0); //
option to turn gravity off for individual body
+ this->selfCollideP = new ParamT<bool>("selfCollide", false, 0); // option
to make body collide with bodies of the same parent
+
+ // User can specify mass/inertia property for the body
+ this->customMassMatrixP = new ParamT<bool>("massMatrix",false,0);
+ this->cxP = new ParamT<double>("cx",0.0,0);
+ this->cyP = new ParamT<double>("cy",0.0,0);
+ this->czP = new ParamT<double>("cz",0.0,0);
+ this->bodyMassP = new ParamT<double>("mass",0.001,0);
+ this->ixxP = new ParamT<double>("ixx",1e-6,0);
+ this->iyyP = new ParamT<double>("iyy",1e-6,0);
+ this->izzP = new ParamT<double>("izz",1e-6,0);
+ this->ixyP = new ParamT<double>("ixy",0.0,0);
+ this->ixzP = new ParamT<double>("ixz",0.0,0);
+ this->iyzP = new ParamT<double>("iyz",0.0,0);
+
Param::End();
}
@@ -95,24 +119,74 @@
delete this->xyzP;
delete this->rpyP;
+ delete this->turnGravityOffP;
+ delete this->selfCollideP;
+ delete this->customMassMatrixP;
+ delete this->cxP ;
+ delete this->cyP ;
+ delete this->czP ;
+ delete this->bodyMassP;
+ delete this->ixxP;
+ delete this->iyyP;
+ delete this->izzP;
+ delete this->ixyP;
+ delete this->ixzP;
+ delete this->iyzP;
}
////////////////////////////////////////////////////////////////////////////////
// Load the body based on an XMLConfig node
void Body::Load(XMLConfigNode *node)
{
+
+ // before loading child geometry, we have to figure out of selfCollide is
true
+ // and modify parent class Entity so this body has its own spaceId
+ this->selfCollideP->Load(node);
+ if (this->selfCollideP->GetValue())
+ {
+ std::cout << "setting self collide: " << this->nameP->GetValue() <<
std::endl;
+ ODEPhysics* pe =
dynamic_cast<ODEPhysics*>(World::Instance()->GetPhysicsEngine());
+ this->spaceId = dSimpleSpaceCreate( pe->spaceId);
+ }
+
+ // option to enter full mass matrix
+ // load custom inertia matrix for the body
+ this->customMassMatrixP->Load(node);
+ this->cxP ->Load(node);
+ this->cyP ->Load(node);
+ this->czP ->Load(node);
+ this->bodyMassP->Load(node);
+ this->ixxP->Load(node);
+ this->iyyP->Load(node);
+ this->izzP->Load(node);
+ this->ixyP->Load(node);
+ this->ixzP->Load(node);
+ this->iyzP->Load(node);
+
+ this->customMassMatrix = this->customMassMatrixP->GetValue();
+ this->cx = this->cxP ->GetValue();
+ this->cy = this->cyP ->GetValue();
+ this->cz = this->czP ->GetValue();
+ this->bodyMass = this->bodyMassP->GetValue();
+ this->ixx = this->ixxP->GetValue();
+ this->iyy = this->iyyP->GetValue();
+ this->izz = this->izzP->GetValue();
+ this->ixy = this->ixyP->GetValue();
+ this->ixz = this->ixzP->GetValue();
+ this->iyz = this->iyzP->GetValue();
+
XMLConfigNode *childNode;
this->nameP->Load(node);
this->xyzP->Load(node);
this->rpyP->Load(node);
+ this->turnGravityOffP->Load(node);
Pose3d initPose;
initPose.pos = **(this->xyzP);
initPose.rot = **(this->rpyP);
-
childNode = node->GetChildByNSPrefix("geom");
// Load the geometries
@@ -123,6 +197,21 @@
childNode = childNode->GetNextByNSPrefix("geom");
}
+ /// Attach mesh for CG visualization
+ /// Add a renderable visual for CG, make visible in Update()
+ if (Simulator::Instance()->GetRenderEngineEnabled())
+ {
+ if (this->mass.mass > 0.0)
+ {
+ this->cg_visual = new OgreVisual(this->GetModel()->GetVisualNode());
+ this->cg_visual->AttachMesh("body_cg");
+ this->cg_visual->SetVisible(false);
+ this->cg_visual->SetMaterial("Gazebo/Red");
+ }
+ }
+
+
+
childNode = node->GetChildByNSPrefix("sensor");
// Load the sensors
@@ -134,8 +223,9 @@
}
// If no geoms are attached, then don't let gravity affect the body.
- if (this->geoms.size()==0)
+ if (this->geoms.size()==0 || this->turnGravityOffP->GetValue())
{
+ std::cout << "setting gravity to zero for: " << this->nameP->GetValue() <<
std::endl;
this->SetGravityMode(false);
}
@@ -197,6 +287,13 @@
}
////////////////////////////////////////////////////////////////////////////////
+// Return Self-Collision Setting
+bool Body::GetSelfCollide()
+{
+ return this->selfCollideP->GetValue();
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Initialize the body
void Body::Init()
{
@@ -218,25 +315,68 @@
std::vector< Sensor* >::iterator sensorIter;
std::map< std::string, Geom* >::iterator geomIter;
+#ifdef TIMING
+ double tmpT1 = Simulator::Instance()->GetWallTime();
+#endif
+
this->UpdatePose();
+#ifdef TIMING
+ double tmpT2 = Simulator::Instance()->GetWallTime();
+ std::cout << " Body Name (" << this->nameP->GetValue() << ")" <<
std::endl;
+ std::cout << " UpdatePose dt (" << tmpT2-tmpT1 << ")" <<
std::endl;
+#endif
+
if (!this->IsStatic())
{
// Set the pose of the scene node
- this->visualNode->SetPose(this->pose);
+ if (Simulator::Instance()->GetRenderEngineEnabled())
+ {
+ this->visualNode->SetPose(this->pose);
+
+ if (this->mass.mass > 0.0)
+ {
+ // Visualization of Body CG
+ if (this->cg_visual)
+ {
+ this->cg_visual->SetVisible(true);
+
+ // set visual pose of CG (CoM)
+ // comPose is only good for initial pose, to represent dynamically
changing CoM, rotate by pose.rot
+ this->cg_visual->SetPose(this->pose +
this->comPose.RotatePositionAboutOrigin(this->pose.rot.GetInverse()));
+ }
+ }
+ }
}
+#ifdef TIMING
+ double tmpT3 = Simulator::Instance()->GetWallTime();
+ std::cout << " Static SetPose dt (" << tmpT3-tmpT2 << ")" <<
std::endl;
+#endif
+
for (geomIter=this->geoms.begin();
geomIter!=this->geoms.end(); geomIter++)
{
geomIter->second->Update();
}
+#ifdef TIMING
+ double tmpT4 = Simulator::Instance()->GetWallTime();
+ std::cout << " Geom Update DT (" << tmpT4-tmpT3 << ")" <<
std::endl;
+#endif
+
for (sensorIter=this->sensors.begin();
sensorIter!=this->sensors.end(); sensorIter++)
{
(*sensorIter)->Update();
}
+
+#ifdef TIMING
+ double tmpT5 = Simulator::Instance()->GetWallTime();
+ std::cout << " ALL Sensors Update DT (" << tmpT5-tmpT4 << ")"
<< std::endl;
+ std::cout << " Body::Update Total DT (" << tmpT5-tmpT1 << ")"
<< std::endl;
+#endif
+
}
////////////////////////////////////////////////////////////////////////////////
@@ -268,7 +408,12 @@
void Body::SetPose(const Pose3d &pose)
{
- this->pose = pose;
+ // check if pose is NaN, if so, constraint solver likely blew up
+ if (std::isnan(pose.pos.x) || std::isnan(pose.pos.y) ||
std::isnan(pose.pos.z) ||
+ std::isnan(pose.rot.u) || std::isnan(pose.rot.x) ||
std::isnan(pose.rot.y) || std::isnan(pose.rot.z))
+ std::cout << "trying to SetPose() for Body(" << this->GetName() << ") with
some NaN's (" << pose << ")" << std::endl;
+ else
+ this->pose = pose;
if (this->IsStatic())
{
@@ -329,7 +474,8 @@
dBodySetPosition(this->bodyId, pos.x, pos.y, pos.z);
// Set the position of the scene node
- this->visualNode->SetPosition(pos);
+ if (Simulator::Instance()->GetRenderEngineEnabled())
+ this->visualNode->SetPosition(pos);
}
////////////////////////////////////////////////////////////////////////////////
@@ -350,7 +496,8 @@
}
// Set the orientation of the scene node
- this->visualNode->SetRotation(rot);
+ if (Simulator::Instance()->GetRenderEngineEnabled())
+ this->visualNode->SetRotation(rot);
}
////////////////////////////////////////////////////////////////////////////////
@@ -368,6 +515,14 @@
pos.x = p[0];
pos.y = p[1];
pos.z = p[2];
+
+ // check for NaN
+ if (std::isnan(pos.x) || std::isnan(pos.y) || std::isnan(pos.z))
+ {
+ std::cout << "Your simulation has exploded, position of body(" <<
this->GetName() << ") has NaN(" << pos << ")" << std::endl;
+ //pos = this->pose.pos;
+ assert(0);
+ }
}
else
{
@@ -394,6 +549,14 @@
rot.x = r[1];
rot.y = r[2];
rot.z = r[3];
+
+ // check for NaN
+ if (std::isnan(rot.u) || std::isnan(rot.x) || std::isnan(rot.y) ||
std::isnan(rot.z))
+ {
+ std::cout << "Your simulation has exploded, rotation of body(" <<
this->GetName() << ") has NaN(" << rot << ")" << std::endl;
+ //rot = this->pose.rot;
+ assert(0);
+ }
}
else
{
@@ -404,6 +567,88 @@
}
////////////////////////////////////////////////////////////////////////////////
+// Return the position of the body. in global CS
+Vector3 Body::GetPositionRate() const
+{
+ Vector3 vel;
+
+ if (this->bodyId)
+ {
+ const dReal *v;
+
+ v = dBodyGetLinearVel(this->bodyId);
+
+ vel.x = v[0];
+ vel.y = v[1];
+ vel.z = v[2];
+ }
+ else
+ {
+ vel.x = 0;
+ vel.y = 0;
+ vel.z = 0;
+ }
+
+ return vel;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Return the rotation
+Quatern Body::GetRotationRate() const
+{
+ Quatern velQ;
+ Vector3 vel;
+
+ if (this->bodyId)
+ {
+ const dReal *v;
+
+ v = dBodyGetAngularVel(this->bodyId);
+ vel.x = v[0];
+ vel.y = v[1];
+ vel.z = v[2];
+
+ velQ.SetFromEuler(vel);
+ }
+ else
+ {
+ vel.x = 0;
+ vel.y = 0;
+ vel.z = 0;
+ velQ.SetFromEuler(vel);
+ }
+
+ return velQ;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Return the rotation
+Vector3 Body::GetEulerRate() const
+{
+ Vector3 vel;
+
+ if (this->bodyId)
+ {
+ const dReal *v;
+
+ v = dBodyGetAngularVel(this->bodyId);
+ vel.x = v[0];
+ vel.y = v[1];
+ vel.z = v[2];
+
+ }
+ else
+ {
+ vel.x = 0;
+ vel.y = 0;
+ vel.z = 0;
+ }
+
+ return vel;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Return the ID of this body
dBodyID Body::GetId() const
{
@@ -447,7 +692,7 @@
}
else if (node->GetName() == "map")
{
- //this->SetStatic(true);
+ this->SetStatic(true);
geom = new MapGeom(this);
}
else
@@ -505,13 +750,103 @@
*/
void Body::UpdateCoM()
{
+ if (!this->bodyId)
+ return;
+
+ // user can specify custom mass matrix or alternatively, UpdateCoM will
calculate CoM for
+ // combined mass of all children geometries.
+ if (this->customMassMatrix)
+ {
+ // Old pose for the CoM
+ Pose3d oldPose, newPose, tmpPose;
+
+ // oldPose is the last comPose
+ // newPose is mass CoM
+ oldPose = this->comPose;
+
+ std::cout << " in UpdateCoM, name: " << this->GetName() << std::endl;
+ std::cout << " in UpdateCoM, comPose or oldPose: " << this->comPose <<
std::endl;
+
+ // New pose for the CoM
+ newPose.pos.x = this->cx;
+ newPose.pos.y = this->cy;
+ newPose.pos.z = this->cz;
+
+ std::map< std::string, Geom* >::iterator giter;
+ // Fixup the poses of the geoms (they are attached to the CoM)
+ for (giter = this->geoms.begin(); giter != this->geoms.end(); giter++)
+ {
+ if (giter->second->IsPlaceable())
+ {
+ // FOR GEOMS:
+ // get pose with comPose set to oldPose
+ this->comPose = oldPose;
+ tmpPose = giter->second->GetPose();
+
+ // get pose with comPose set to newPose
+ this->comPose = newPose;
+ giter->second->SetPose(tmpPose, false);
+ }
+ }
+
+ // FOR BODY: Fixup the pose of the CoM (ODE body)
+ // get pose with comPose set to oldPose
+ this->comPose = oldPose;
+ tmpPose = this->GetPose();
+ // get pose with comPose set to newPose
+ this->comPose = newPose;
+ this->SetPose(tmpPose);
+
+ // Settle on the new CoM pose
+ this->comPose = newPose;
+
+
+
+ // comPose is zero in this case, we'll keep cx, cy, cz
+ this->comPose.Reset();
+
+ this->comPose.pos.x = this->cx;
+ this->comPose.pos.y = this->cy;
+ this->comPose.pos.z = this->cz;
+
+ // setup this->mass as well
+ dMassSetParameters(&this->mass, this->bodyMass,
+ this->cx, this->cy, this->cz,
+ //0,0,0,
+ this->ixx,this->iyy,this->izz,
+ this->ixy,this->ixz,this->iyz);
+
+ dMassTranslate( &this->mass, -this->cx, -this->cy, -this->cz);
+
+ // dMatrix3 rot;
+ // dMassRotate(&this->mass, rot);
+
+ // Set the mass matrix
+ if (this->mass.mass > 0)
+ dBodySetMass( this->bodyId, &this->mass );
+
+ // std::cout << " c[0] " << this->mass.c[0] << std::endl;
+ // std::cout << " c[1] " << this->mass.c[1] << std::endl;
+ // std::cout << " c[2] " << this->mass.c[2] << std::endl;
+ // std::cout << " I[0] " << this->mass.I[0] << std::endl;
+ // std::cout << " I[1] " << this->mass.I[1] << std::endl;
+ // std::cout << " I[2] " << this->mass.I[2] << std::endl;
+ // std::cout << " I[3] " << this->mass.I[3] << std::endl;
+ // std::cout << " I[4] " << this->mass.I[4] << std::endl;
+ // std::cout << " I[5] " << this->mass.I[5] << std::endl;
+ // std::cout << " I[6] " << this->mass.I[6] << std::endl;
+ // std::cout << " I[7] " << this->mass.I[7] << std::endl;
+ // std::cout << " I[8] " << this->mass.I[8] << std::endl;
+
+ }
+ else
+ {
+
+ // original gazebo subroutine that gathers mass from all geoms and sums into
one single mass matrix
+
const dMass *lmass;
- Pose3d oldPose, newPose, pose;
std::map< std::string, Geom* >::iterator giter;
- if (!this->bodyId)
- return;
-
// Construct the mass matrix by combining all the geoms
dMassSetZero( &this->mass );
@@ -525,6 +860,10 @@
}
// Old pose for the CoM
+ Pose3d oldPose, newPose, tmpPose;
+
+ // oldPose is the last comPose
+ // newPose is mass CoM
oldPose = this->comPose;
if (std::isnan(this->mass.c[0]))
@@ -546,19 +885,24 @@
{
if (giter->second->IsPlaceable())
{
+ // FOR GEOMS:
+ // get pose with comPose set to oldPose
this->comPose = oldPose;
- pose = giter->second->GetPose();
+ tmpPose = giter->second->GetPose();
+
+ // get pose with comPose set to newPose
this->comPose = newPose;
- giter->second->SetPose(pose, false);
+ giter->second->SetPose(tmpPose, false);
}
}
-
- // Fixup the pose of the CoM (ODE body)
+ // FOR BODY: Fixup the pose of the CoM (ODE body)
+ // get pose with comPose set to oldPose
this->comPose = oldPose;
- pose = this->GetPose();
+ tmpPose = this->GetPose();
+ // get pose with comPose set to newPose
this->comPose = newPose;
- this->SetPose(pose);
+ this->SetPose(tmpPose);
// Settle on the new CoM pose
@@ -570,6 +914,8 @@
// Set the mass matrix
if (this->mass.mass > 0)
dBodySetMass( this->bodyId, &this->mass );
+ }
+
}
////////////////////////////////////////////////////////////////////////////////
Modified: code/gazebo/branches/ogre-1.4.9/server/physics/Body.hh
===================================================================
--- code/gazebo/branches/ogre-1.4.9/server/physics/Body.hh 2009-03-17
00:23:10 UTC (rev 7492)
+++ code/gazebo/branches/ogre-1.4.9/server/physics/Body.hh 2009-03-17
00:34:59 UTC (rev 7493)
@@ -101,6 +101,18 @@
/// \return Rotation quaternion
public: Quatern GetRotation() const;
+ /// \brief Return the velocity of the body
+ /// \return Velocity vector
+ public: Vector3 GetPositionRate() const;
+
+ /// \brief Return the rotation rates
+ /// \return Rotation Rate quaternion
+ public: Quatern GetRotationRate() const;
+
+ /// \brief Return the rotation rates
+ /// \return Rotation Rate Euler Angles RPY
+ public: Vector3 GetEulerRate() const;
+
/// \brief Return the ID of this body
/// \return ODE body id
public: dBodyID GetId() const;
@@ -117,6 +129,10 @@
/// \brief Set whether gravity affects this body
public: void SetGravityMode(bool mode);
+ /// \brief Get Self-Collision Flag, if this is true, this body will collide
+ // with other bodies even if they share the same parent.
+ public: bool GetSelfCollide();
+
/// \brief Set the linear velocity of the body
public: void SetLinearVel(const Vector3 &vel);
@@ -187,6 +203,26 @@
private: ParamT<Vector3> *xyzP;
private: ParamT<Quatern> *rpyP;
+
+ private: ParamT<bool> *turnGravityOffP;
+ private: ParamT<bool> *selfCollideP;
+
+ private: OgreVisual *cg_visual;
+
+ /// User specified Mass Matrix
+ protected: ParamT<bool> *customMassMatrixP;
+ protected: ParamT<double> *cxP ;
+ protected: ParamT<double> *cyP ;
+ protected: ParamT<double> *czP ;
+ protected: ParamT<double> *bodyMassP;
+ protected: ParamT<double> *ixxP;
+ protected: ParamT<double> *iyyP;
+ protected: ParamT<double> *izzP;
+ protected: ParamT<double> *ixyP;
+ protected: ParamT<double> *ixzP;
+ protected: ParamT<double> *iyzP;
+ protected: bool customMassMatrix;
+ protected: double cx,cy,cz,bodyMass,ixx,iyy,izz,ixy,ixz,iyz;
};
/// \}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit