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


uwsim
Author(s): Mario Prats
autogenerated on Mon Oct 6 2014 08:24:07