URDFRobot.cpp
Go to the documentation of this file.
00001 /* 
00002  * Copyright (c) 2013 University of Jaume-I.
00003  * All rights reserved. This program and the accompanying materials
00004  * are made available under the terms of the GNU Public License v3.0
00005  * which accompanies this distribution, and is available at
00006  * http://www.gnu.org/licenses/gpl.html
00007  * 
00008  * Contributors:
00009  *     Mario Prats
00010  *     Javier Perez
00011  */
00012 
00013 #include <uwsim/URDFRobot.h>
00014 #include <uwsim/UWSimUtils.h>
00015 #include <osg/ShapeDrawable>
00016 #include <osg/Material>
00017 #include <math.h>
00018 
00019 //ContactTest structure: http://www.bulletphysics.org/mediawiki-1.5.8/index.php/Collision_Callbacks_and_Triggers
00020 struct ContactSensorCallback : public btCollisionWorld::ContactResultCallback
00021 {
00022 
00024 
00026   ContactSensorCallback(btRigidBody& tgtBody) :
00027       btCollisionWorld::ContactResultCallback(), body(tgtBody)
00028   {
00029     collided = 0;
00030   }
00031 
00032   btRigidBody& body; 
00033   int collided;
00034 
00036 
00038   virtual bool needsCollision(btBroadphaseProxy* proxy) const
00039   {
00040     if (proxy->m_collisionFilterGroup == 0x00000010)
00041     { //Check if it's a vehicle!
00042       return false;
00043     }
00044     return body.checkCollideWithOverride(static_cast<btCollisionObject*>(proxy->m_clientObject));
00045   }
00046 
00047   #if BT_BULLET_VERSION <= 279
00048 
00049   virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObject * colObj0, int partId0, int index0,
00050                                    const btCollisionObject * colObj1, int partId1, int index1)
00051   #else
00052   virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper * colObj0, int partId0, int index0,
00053                                    const btCollisionObjectWrapper * colObj1, int partId1, int index1)
00054   #endif
00055   {
00056     //Check if object colliding is Static or Kinematic (in that case no object reaction will be produced by bullet, so we stop the arm movement!)
00057   #if BT_BULLET_VERSION <= 279
00058     if (((colObj0->getCollisionFlags() & btCollisionObject::CF_STATIC_OBJECT) > 0
00059         || (colObj0->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT) > 0)
00060         && ((colObj1->getCollisionFlags() & btCollisionObject::CF_STATIC_OBJECT) > 0
00061             || (colObj1->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT) > 0))
00062   #else
00063     if (((colObj0->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_STATIC_OBJECT) > 0
00064         || (colObj0->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT) > 0)
00065         && ((colObj1->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_STATIC_OBJECT) > 0
00066             || (colObj1->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT) > 0))
00067   #endif
00068     {
00069       collided = 1;
00070 
00071     }
00072     return 0; // not actually sure if return value is used for anything...?
00073   }
00074 };
00075 
00076 URDFRobot::URDFRobot(osgOcean::OceanScene *oscene, Vehicle vehicle) :
00077     KinematicChain(vehicle.nlinks, vehicle.njoints)
00078 {
00079   ScopedTimer buildSceneTimer("Loading URDF robot... \n", osg::notify(osg::ALWAYS));
00080   const std::string SIMULATOR_DATA_PATH = std::string(getenv("HOME")) + "/.uwsim/data";
00081 
00082   osgDB::Registry::instance()->getDataFilePathList().push_back(
00083       std::string(SIMULATOR_DATA_PATH) + std::string("/robot"));
00084   osgDB::Registry::instance()->getDataFilePathList().push_back(
00085       std::string(UWSIM_ROOT_PATH) + std::string("/data/shaders"));
00086   osgDB::Registry::instance()->getDataFilePathList().push_back(
00087       std::string(SIMULATOR_DATA_PATH) + std::string("/textures"));
00088 
00089   URDFFile=vehicle.URDFFile;
00090 
00091   link.resize(vehicle.nlinks);
00092 
00093   //Create links from geometry nodes
00094   for (int i = 0; i < vehicle.nlinks; i++)
00095   {
00096     ScopedTimer buildSceneTimer("  · " + vehicle.links[i].geom->file + ": ", osg::notify(osg::ALWAYS));
00097 
00098     link[i] = UWSimGeometry::loadGeometry(vehicle.links[i].geom);
00099     if (!link[i])
00100       exit(0);
00101     link[i]->setName(vehicle.links[i].name);
00102 
00103     if (!vehicle.links[i].material.empty())
00104     { //Add material if exists
00105       osg::ref_ptr < osg::StateSet > stateset = new osg::StateSet();
00106       osg::ref_ptr < osg::Material > material = new osg::Material();
00107       material->setDiffuse(
00108           osg::Material::FRONT_AND_BACK,
00109           osg::Vec4(vehicle.materials[vehicle.links[i].material].r, vehicle.materials[vehicle.links[i].material].g,
00110                     vehicle.materials[vehicle.links[i].material].b, vehicle.materials[vehicle.links[i].material].a));
00111       stateset->setAttribute(material);
00112       if (vehicle.materials[vehicle.links[i].material].a < 1)
00113       {
00114         stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
00115         stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
00116       }
00117       link[i]->setStateSet(stateset);
00118     }
00119   }
00120 
00121   bool success = true;
00122   for (int i = 0; i < vehicle.nlinks; i++)
00123   {
00124     if (!link[i].valid())
00125     {
00126       osg::notify(osg::WARN) << "Could not find " << vehicle.name << " link" << i << ".osg "
00127           << vehicle.links[i + 1].geom->file << std::endl;
00128       baseTransform = NULL;
00129       success = false;
00130     }
00131   }
00132 
00133   //Create tree hierarchy linkBT->link->linkPT and link links
00134   if (success)
00135   {
00136     ScopedTimer buildSceneTimer("  · Linking links...", osg::notify(osg::ALWAYS));
00137     osgDB::Registry::instance()->getDataFilePathList().push_back(
00138         std::string(UWSIM_ROOT_PATH) + std::string("/data/shaders"));
00139     static const char model_vertex[] = "default_scene.vert";
00140     static const char model_fragment[] = "default_scene.frag";
00141     std::vector < osg::ref_ptr<osg::MatrixTransform> > linkBaseTransforms(vehicle.nlinks);
00142     std::vector < osg::ref_ptr<osg::MatrixTransform> > linkPostTransforms(vehicle.nlinks);
00143 
00144     osg::Matrix linkBase;
00145     osg::Matrix linkPost;
00146     for (int i = 0; i < vehicle.nlinks; i++)
00147     {
00148       link[i]->setNodeMask(
00149           oscene->getNormalSceneMask() | oscene->getReflectedSceneMask() | oscene->getRefractedSceneMask());
00150       linkBase.makeIdentity();
00151       //linkBase.preMultRotate(osg::Quat(vehicle.links[i].rpy[0],osg::Vec3d(1,0,0)));
00152       //linkBase.preMultRotate(osg::Quat(vehicle.links[i].rpy[1],osg::Vec3d(0,1,0)));
00153       //linkBase.preMultRotate(osg::Quat(vehicle.links[i].rpy[2],osg::Vec3d(0,0,1)));
00154       //linkBase.preMultTranslate(osg::Vec3d(-vehicle.links[i].position[0],-vehicle.links[i].position[1],-vehicle.links[i].position[2]));
00155       linkBase.makeTranslate(
00156           osg::Vec3d(vehicle.links[i].position[0], vehicle.links[i].position[1], vehicle.links[i].position[2]));
00157       linkBase.preMultRotate(
00158           osg::Quat(vehicle.links[i].quat[0], vehicle.links[i].quat[1], vehicle.links[i].quat[2],
00159                     vehicle.links[i].quat[3]));
00160       linkBase.preMultScale(osg::Vec3d(vehicle.links[i].geom->scale[0],vehicle.links[i].geom->scale[1],vehicle.links[i].geom->scale[2]));
00161 
00162       linkBaseTransforms[i] = new osg::MatrixTransform;
00163       linkBaseTransforms[i]->setMatrix(linkBase);
00164       linkBaseTransforms[i]->addChild(link[i]);
00165 
00166       //linkBase.invert(linkPost);
00167       linkPost.makeIdentity();
00168       linkPost.preMultScale(osg::Vec3d(1.0/vehicle.links[i].geom->scale[0],1.0/vehicle.links[i].geom->scale[1],1.0/vehicle.links[i].geom->scale[2]));
00169       linkPost.preMultRotate(
00170           osg::Quat(vehicle.links[i].quat[0], vehicle.links[i].quat[1], vehicle.links[i].quat[2],
00171                     vehicle.links[i].quat[3]).inverse());
00172       linkPost.preMultTranslate(
00173           -osg::Vec3d(vehicle.links[i].position[0], vehicle.links[i].position[1], vehicle.links[i].position[2]));
00174       linkPostTransforms[i] = new osg::MatrixTransform;
00175       linkPostTransforms[i]->setMatrix(linkPost);
00176       link[i]->asGroup()->addChild(linkPostTransforms[i]);
00177     }
00178 
00179     joints.resize(vehicle.njoints);
00180     zerojoints.resize(vehicle.njoints);
00181 
00182     for (int i = 0; i < vehicle.njoints; i++)
00183     {
00184       joints[i] = new osg::MatrixTransform;
00185       zerojoints[i] = new osg::MatrixTransform;
00186     }
00187 
00188     osg::Matrix m;
00189     for (int i = 0; i < vehicle.njoints; i++)
00190     {
00191       m.makeTranslate(0, 0, 0);
00192       m.preMultTranslate(
00193           osg::Vec3d(vehicle.joints[i].position[0], vehicle.joints[i].position[1], vehicle.joints[i].position[2]));
00194       m.preMultRotate(
00195           osg::Quat(vehicle.joints[i].quat[0], vehicle.joints[i].quat[1], vehicle.joints[i].quat[2],
00196                     vehicle.joints[i].quat[3]));
00197 
00198       joints[i]->setMatrix(m);
00199       zerojoints[i]->setMatrix(m);
00200     }
00201 
00202     baseTransform = new osg::MatrixTransform();
00203     baseTransform->addChild(linkBaseTransforms[0]);
00204 
00205     //Create a frame that can be switched on and off
00206     osg::ref_ptr < osg::Node > btaxis = UWSimGeometry::createSwitchableFrame();
00207     //Add label to switchable frame
00208     btaxis->asGroup()->addChild(UWSimGeometry::createLabel(vehicle.name));
00209     baseTransform->addChild(btaxis);
00210 
00211     for (int i = 0; i < vehicle.njoints; i++)
00212     {
00213       linkPostTransforms[vehicle.joints[i].parent]->asGroup()->addChild(joints[i]);
00214       joints[i]->addChild(linkBaseTransforms[vehicle.joints[i].child]);
00215 
00216       //Create a frame that can be switched on and off
00217       osg::ref_ptr < osg::Node > axis = UWSimGeometry::createSwitchableFrame();
00218       //Add label to switchable frame
00219       axis->asGroup()->addChild(UWSimGeometry::createLabel(vehicle.joints[i].name));
00220 
00221       joints[i]->addChild(axis);
00222     }
00223     //Save rotations for joints update, limits, and type of joints
00224     joint_axis.resize(vehicle.njoints);
00225     for (int i = 0; i < vehicle.njoints; i++)
00226     {
00227       joint_axis[i] = osg::Vec3d(vehicle.joints[i].axis[0], vehicle.joints[i].axis[1], vehicle.joints[i].axis[2]);
00228       jointType[i] = vehicle.joints[i].type;
00229       limits[i] = std::pair<double, double>(vehicle.joints[i].lowLimit, vehicle.joints[i].upLimit);
00230       names[i] = vehicle.joints[i].name;
00231     }
00232 
00233     //Save mimic info
00234     for (int i = 0; i < vehicle.njoints; i++)
00235     {
00236       if (vehicle.joints[i].mimicp == -1)
00237       {
00238         mimic[i].joint = i;
00239         mimic[i].offset = 0;
00240         mimic[i].multiplier = 1;
00241         mimic[i].sliderCrank = 0;
00242       }
00243       else
00244       {
00245         mimic[i].joint = vehicle.joints[i].mimicp;
00246         mimic[i].offset = vehicle.joints[i].mimic->offset;
00247         mimic[i].multiplier = vehicle.joints[i].mimic->multiplier;
00248         if (vehicle.joints[i].name.find("slidercrank") != string::npos)
00249           mimic[i].sliderCrank = 1;
00250         else
00251           mimic[i].sliderCrank = 0;
00252       }
00253     }
00254 
00255     osg::notify(osg::ALWAYS) << "Robot successfully loaded. Total time: ";
00256   }
00257 }
00258 
00259 void URDFRobot::addToKinematicChain(osg::Node * newLink, btRigidBody* body)
00260 {
00261   link.push_back(newLink);
00262 
00263   //Reset vehicle properties as vehicle
00264   if (body)
00265   {
00266     physics->dynamicsWorld->btCollisionWorld::removeCollisionObject(body);
00267     physics->dynamicsWorld->addCollisionObject(body, short(COL_VEHICLE), short(COL_OBJECTS));
00268   }
00269 
00270 }
00271 
00272 void URDFRobot::moveJoints(std::vector<double> &q)
00273 {
00274   osg::Matrix m;
00275 
00276   for (int i = 0; i < getNumberOfJoints(); i++)
00277   {
00278     if (jointType[i] == 1)
00279     {
00280       if (mimic[i].sliderCrank == 0)
00281         m.makeRotate(q[mimic[i].joint] * mimic[i].multiplier + mimic[i].offset, joint_axis[i]);
00282       else
00283         m.makeRotate((q[mimic[i].joint] + asin(mimic[i].offset * sin(q[mimic[i].joint]))) * -1, joint_axis[i]);
00284     }
00285     else if (jointType[i] == 2)
00286     {
00287       m.makeTranslate(joint_axis[i] * (q[mimic[i].joint] * mimic[i].multiplier + mimic[i].offset));
00288     }
00289     else
00290       m.makeIdentity();
00291     osg::Matrix nm = zerojoints[i]->getMatrix();
00292     nm.preMult(m);
00293     joints[i]->setMatrix(nm);
00294   }
00295 
00296 }
00297 
00298 void URDFRobot::updateJoints(std::vector<double> &q)
00299 {
00300 
00301   moveJoints(q);
00302 
00303   //Check if vehicle is colliding in new position;
00304   int collision = 0;
00305   for (int i = 1; i < link.size() && !collision; i++)
00306   { //Do not check base_link as it's position does not depend on Kinematic chain (should be checked on vehicle moves)
00307     osg::ref_ptr < NodeDataType > data = dynamic_cast<NodeDataType*>(link[i]->getUserData());
00308     btRigidBody* tgtBody = data->rigidBody;
00309     if (tgtBody)
00310     {
00311       boost::shared_ptr<osg::Matrix> mat = getWorldCoords(link[i]);
00312       //BTTransforms do not use scale, so we turn it back to 1.
00313       mat->preMultScale(osg::Vec3d(1.0/mat->getScale().x(),1.0/mat->getScale().y(),1.0/mat->getScale().z())); 
00314       tgtBody->setWorldTransform(osgbCollision::asBtTransform(*mat));
00315       ContactSensorCallback callback(*tgtBody);
00316       physics->dynamicsWorld->contactTest(tgtBody, callback);
00317       collision = callback.collided;
00318     }
00319   }
00320 
00321   //If not colliding save position as safe
00322   if (!collision)
00323   {
00324     //std::cout<<"No collision, saving position as 'safe'"<<std::endl;
00325     for (int i = 0; i < getNumberOfJoints(); i++)
00326       qLastSafe[i] = q[i];
00327   }
00328 
00329   //If collision move back to lastSafe position
00330   //TODO Check if it is posible to move only some joints instead of stopping the whole movement
00331   else
00332   {
00333     //std::cout<<"Collision detected, turning back to last safe position"<<std::endl;
00334     for (int i = 0; i < getNumberOfJoints(); i++)
00335     {
00336       this->q[i] = qLastSafe[i];
00337     }
00338     moveJoints (qLastSafe);
00339   }
00340 
00341 }
00342 
00343 void URDFRobot::updateJoints(std::vector<double> &q, int startJoint, int numJoints)
00344 {
00345   osg::Matrix m;
00346 
00347   for (int i = startJoint; i < startJoint + numJoints; i++)
00348   {
00349     m.makeRotate(q[mimic[i].joint] * mimic[i].multiplier + mimic[i].offset, joint_axis[i]);
00350     osg::Matrix nm = zerojoints[i]->getMatrix();
00351     nm.preMult(m);
00352     joints[i]->setMatrix(nm);
00353   }
00354 }
00355 
00356 URDFRobot::~URDFRobot()
00357 {
00358 }


uwsim
Author(s): Mario Prats , Javier Perez
autogenerated on Fri Aug 28 2015 13:28:58