ForceSensor.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 <pluginlib/class_list_macros.h>
00014 #include <uwsim/ForceSensor.h>
00015 
00016 ForceSensor::ForceSensor(ForceSensor_Config * cfg, osg::ref_ptr<osg::Node> target) :
00017     SimulatedDevice(cfg)
00018 {
00019   this->target = target;
00020   this->offsetp[0]=cfg->offsetp[0];  this->offsetp[1]=cfg->offsetp[1];  this->offsetp[2]=cfg->offsetp[2];
00021   offset.makeRotate(osg::Quat(cfg->offsetr[0], osg::Vec3d(1, 0, 0), cfg->offsetr[1], osg::Vec3d(0, 1, 0), cfg->offsetr[2],osg::Vec3d(0, 0, 1)));
00022   physics=NULL;
00023   physicsApplied=0;
00024 }
00025 
00026 void ForceSensor::applyPhysics(BulletPhysics * bulletPhysics)
00027 {
00028   physics=bulletPhysics;
00029   osg::ref_ptr<NodeDataType> data = dynamic_cast<NodeDataType*>(target->getUserData());
00030   copy=physics->copyObject(data->rigidBody);
00031   copy->setGravity(btVector3(0,0,0));
00032   copy->setCenterOfMassTransform(btTransform(btQuaternion(0,0,0,1),btVector3(offsetp[0],offsetp[1],offsetp[2])));
00033   btTarget = data->rigidBody;
00034   btTarget->setCenterOfMassTransform(btTransform(btQuaternion(0,0,0,1),btVector3(offsetp[0],offsetp[1],offsetp[2])));
00035 
00036   if(btTarget->getInvMass()==0)
00037   {
00038     ROS_FATAL("ForceSensor %s used in a null mass object.", name.c_str());
00039     exit(0);
00040   } 
00041 
00042   CBreference=physics->callbackManager->addForceSensor(copy,btTarget);
00043   physicsApplied=1;
00044 }
00045 
00046 void ForceSensor::getForceTorque(double force[3], double torque[3])
00047 {
00048 
00049   if(!physics)
00050   {
00051     ROS_FATAL("ForceSensor %s can't retrieve physics information. Missing enable physics?", name.c_str());
00052     exit(0);
00053   }
00054   if(physics->physicsStep ==0) //Check if physics is looping (data is not reliable)
00055   {
00056 
00057     osg::Matrix ObjectMat= offset * *getWorldCoords(target); //aply rotation offset to transform from world coords.
00058 
00059     double linSpeed[3],angSpeed[3];
00060     physics->callbackManager->getForceSensorSpeed(CBreference,linSpeed,angSpeed);
00061 
00062     osg::Vec3 res=ObjectMat.getRotate().inverse()*osg::Vec3(linSpeed[0],linSpeed[1],linSpeed[2]);
00063 
00064     force[0]=res.x();
00065     force[1]=res.y();
00066     force[2]=res.z();
00067 
00068     res=ObjectMat.getRotate().inverse()*osg::Vec3(angSpeed[0],angSpeed[1],angSpeed[2]);
00069 
00070     //torque forces are extremely high so they ar reduced.(some physics parameter must be wrong).
00071     torque[0]=res.x()/10;
00072     torque[1]=res.y()/10;
00073     torque[2]=res.z()/10;
00074   }
00075   else  //Maybe last reliable data should be sent
00076   {
00077     force[0]=0;
00078     force[1]=0;
00079     force[2]=0;
00080 
00081     torque[0]=0;
00082     torque[1]=0;
00083     torque[2]=0;
00084 
00085   }
00086 }
00087 
00088 SimulatedDeviceConfig::Ptr ForceSensor_Factory::processConfig(const xmlpp::Node* node, ConfigFile * config)
00089 {
00090   ForceSensor_Config * cfg = new ForceSensor_Config(getType());
00091   xmlpp::Node::NodeList list = node->get_children();
00092   for (xmlpp::Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
00093   {
00094     const xmlpp::Node* child = dynamic_cast<const xmlpp::Node*>(*iter);
00095     if(child->get_name() == "target")
00096       config->extractStringChar(child, cfg->target);
00097     else if(child->get_name() == "offsetp")
00098       config->extractPositionOrColor(child, cfg->offsetp);
00099     else if(child->get_name() == "offsetr")
00100       config->extractPositionOrColor(child, cfg->offsetr);
00101   }
00102   return SimulatedDeviceConfig::Ptr(cfg);
00103 }
00104 
00105 bool ForceSensor_Factory::applyConfig(SimulatedIAUV * auv, Vehicle &vehicleChars, SceneBuilder *sceneBuilder,
00106                                       size_t iteration)
00107 {
00108   if (iteration > 0)
00109     return true;
00110   for (size_t i = 0; i < vehicleChars.simulated_devices.size(); ++i)
00111     if (vehicleChars.simulated_devices[i]->getType() == this->getType())
00112     {
00113       ForceSensor_Config * cfg = dynamic_cast<ForceSensor_Config *>(vehicleChars.simulated_devices[i].get());
00114       osg::ref_ptr<osg::Node> target;
00115       for(int j=0;j<auv->urdf->link.size();j++)
00116       {
00117         if(auv->urdf->link[j]->getName()==cfg->target)
00118         {
00119           target=auv->urdf->link[j];
00120         }
00121       }
00122       auv->devices->all.push_back(ForceSensor::Ptr(new ForceSensor(cfg,target)));
00123     }
00124   return true;
00125 }
00126 
00127 std::vector<boost::shared_ptr<ROSInterface> > ForceSensor_Factory::getInterface(
00128     ROSInterfaceInfo & rosInterface, std::vector<boost::shared_ptr<SimulatedIAUV> > & iauvFile)
00129 {
00130   std::vector < boost::shared_ptr<ROSInterface> > ifaces;
00131   for (size_t i = 0; i < iauvFile.size(); ++i)
00132     for (size_t d = 0; d < iauvFile[i]->devices->all.size(); ++d)
00133       if (iauvFile[i]->devices->all[d]->getType() == this->getType()
00134           && iauvFile[i]->devices->all[d]->name == rosInterface.targetName)
00135       {
00136         ifaces.push_back(
00137             boost::shared_ptr < ROSInterface
00138                 > (new ForceSensor_ROSPublisher(dynamic_cast<ForceSensor*>(iauvFile[i]->devices->all[d].get()),
00139                                                 rosInterface.topic, rosInterface.rate)));
00140         //rosInterface.values are for new and non-standard xml configurations, but it looks like currently existing rosInterface fields are enough...
00141         //below is just an example how to get values, alternatively you can use rosInterface.values["name"]
00142         //for(std::map<std::string,std::string>::iterator it = rosInterface.values.begin() ;it != rosInterface.values.end();++it)
00143         //      ROS_INFO("rosInterface.values[%s]='%s'",  it->first.c_str(), it->second.c_str());
00144       }
00145   if (ifaces.size() == 0)
00146     ROS_WARN("Returning empty ROS interface for device %s...", rosInterface.targetName.c_str());
00147   return ifaces;
00148 }
00149 
00150 void ForceSensor_ROSPublisher::createPublisher(ros::NodeHandle &nh)
00151 {
00152   ROS_INFO("ForceSensor_ROSPublisher on topic %s", topic.c_str());
00153   pub_ = nh.advertise < geometry_msgs::WrenchStamped > (topic, 1);
00154   while (!dev->physicsApplied)
00155   {
00156     ROS_INFO("ForceSensor_ROSPublisher Waiting for physics to be initialized...");
00157     sleep(1.0);
00158   }
00159 }
00160 
00161 void ForceSensor_ROSPublisher::publish()
00162 {
00163 
00164   double force[3], torque[3], elapsed;
00165 
00166   dev->getForceTorque(force,torque);
00167 
00168   elapsed = 1.0/publish_rate;
00169 
00170   geometry_msgs::WrenchStamped msg;
00171   msg.header.stamp = getROSTime();
00172   msg.header.frame_id =dev->target->getName();
00173 
00174   msg.wrench.force.x=force[0]/elapsed*(1/dev->btTarget->getInvMass());
00175   msg.wrench.force.y=force[1]/elapsed*(1/dev->btTarget->getInvMass());
00176   msg.wrench.force.z=force[2]/elapsed*(1/dev->btTarget->getInvMass());
00177 
00178   msg.wrench.torque.x=torque[0]/elapsed*(1/dev->btTarget->getInvMass());
00179   msg.wrench.torque.y=torque[1]/elapsed*(1/dev->btTarget->getInvMass());
00180   msg.wrench.torque.z=torque[2]/elapsed*(1/dev->btTarget->getInvMass());
00181 
00182   pub_.publish(msg);
00183 }
00184 
00185 #if ROS_VERSION_MINIMUM(1, 9, 0)
00186 // new pluginlib API in Groovy and Hydro
00187 PLUGINLIB_EXPORT_CLASS(ForceSensor_Factory, uwsim::SimulatedDeviceFactory)
00188 #else
00189 PLUGINLIB_REGISTER_CLASS(ForceSensor_Factory, ForceSensor_Factory, uwsim::SimulatedDeviceFactory)
00190 #endif
00191 


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