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


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