QuadrotorHandler.cpp
Go to the documentation of this file.
00001 
00002 #include <pluginlib/class_list_macros.h>
00003 #include <vrep_ros_plugin/GenericObjectHandler.h>
00004 #include <quadrotor_handler/QuadrotorHandler.h>
00005 
00006 #include <v_repLib.h>
00007 
00008 //#include <telekyb_msgs/TKState.h>
00009 #include <sensor_msgs/Imu.h>
00010 #include <geometry_msgs/PoseStamped.h>
00011 #include <geometry_msgs/TwistStamped.h>
00012 
00013 #include <eigen3/Eigen/Geometry>
00014 
00015 #include <vrep_ros_plugin/access.h>
00016 #include <vrep_ros_plugin/ConsoleHandler.h>
00017 
00018 QuadrotorHandler::QuadrotorHandler() : GenericObjectHandler(),
00019     _torqueToForceRatio(0.0),
00020     _handleOfCoM(-1),
00021     _quadrotorMass(0.8),
00022     _lastReceivedCmdTime(ros::Time::now()),
00023     _ObjStatusFrequency(-1),
00024     _lastPublishedStatusTime(0.0),
00025     _Commands(4,0)
00026 
00027     {
00028 
00029 
00030 }
00031 
00032 QuadrotorHandler::~QuadrotorHandler(){
00033 }
00034 
00035 unsigned int QuadrotorHandler::getObjectType() const {
00036     return CustomDataHeaders::QUADROTOR_DATA_MAIN;
00037 }
00038 
00039 void QuadrotorHandler::synchronize(){
00040 
00041 
00042     simFloat intertia[9];
00043     simFloat compos[3];
00044 
00045     // Get the mass of the quadropter
00046     simGetShapeMassAndInertia(_associatedObjectID,&_quadrotorMass,intertia,compos,NULL);
00047 
00048     // Remove # chars for compatibility with ROS
00049     _associatedObjectName = simGetObjectName(_associatedObjectID);
00050     std::string objectName(_associatedObjectName);
00051     std::replace( objectName.begin(), objectName.end(), '#', '_');
00052 
00053     // Publisher of the quadropter status
00054     //_pub = _nh.advertise<telekyb_msgs::TKState>(objectName+"/status", 1000);
00055 
00056     // Publisher of the quadrotor pose
00057         _pubPose = _nh.advertise<geometry_msgs::PoseStamped>(objectName+"/pose", 1);
00058 
00059         _pubTwist = _nh.advertise<geometry_msgs::TwistStamped>(objectName+"/twist", 1);
00060 
00061     // Publisher of the IMU
00062     //_pubIMU = _nh.advertise<sensor_msgs::Imu>("IMU/"+objectName, 1);
00063 
00064 
00065 }
00066 
00067 
00068 
00069 void QuadrotorHandler::handleSimulation(){
00070     // called when the main script calls: simHandleModule
00071     if(!_initialized){
00072         _initialize();
00073     }
00074 
00075 
00076    ros::Time now = ros::Time::now();
00077 
00078     Eigen::Matrix <simFloat, 3, 1> position;
00079     Eigen::Quaternion < simFloat > orientation; //(x,y,z,w)
00080     Eigen::Matrix <simFloat, 3, 1> linVelocity;
00081     Eigen::Matrix <simFloat, 3, 1> angVelocity;
00082     const static Eigen::Quaternion< simFloat > nwuToNed(0,1,0,0);
00083 
00084 // Turn the propellers
00085     for (int motorIdx = 0; motorIdx < 4; ++motorIdx){
00086          if(simSetJointTargetVelocity(_handleOfJoint[motorIdx], 17.0)==-1){
00087             simSetLastError( simGetObjectName(_handleOfJoint[motorIdx]), "Error applying velocity.");
00088           }
00089        }
00090 
00091 
00092     if(simGetObjectPosition(_handleOfCoM, -1, position.data())!=-1 &&
00093             simGetObjectQuaternion(_handleOfCoM, -1, orientation.coeffs().data())!=-1 &&
00094             simGetObjectVelocity(_handleOfCoM, linVelocity.data(), angVelocity.data())!=-1){
00095 
00096 
00097         position = nwuToNed*position;
00098         linVelocity = nwuToNed*linVelocity;
00099         angVelocity = orientation.conjugate()*angVelocity; // Express angular velocity in body frame
00100         orientation = nwuToNed*orientation; // change world frame to north-east-down
00101         // use only positive w (not necessary)
00102         if (orientation.w()<0){
00103             orientation.coeffs() *=-1;
00104         }
00105 
00106 
00107         const simFloat currentSimulationTime = simGetSimulationTime();
00108 
00109 
00110         //if ((currentSimulationTime-_lastPublishedStatusTime) >= 1.0/_ObjStatusFrequency){
00111 
00112 
00113 
00114                 // Fill the status msg
00115                         geometry_msgs::PoseStamped msgPose;
00116                         msgPose.header.stamp = now;
00117                         msgPose.pose.position.x = position[0];
00118                         msgPose.pose.position.y = position[1];
00119                         msgPose.pose.position.z = position[2];
00120                         msgPose.pose.orientation.w = orientation.w();
00121                         msgPose.pose.orientation.x = orientation.x();
00122                         msgPose.pose.orientation.y = orientation.y();
00123                         msgPose.pose.orientation.z = orientation.z();
00124                    _pubPose.publish(msgPose);
00125 
00126 
00127                         geometry_msgs::TwistStamped msgTwist;
00128                         msgTwist.header.stamp = now;
00129                         msgTwist.twist.linear.x = linVelocity[0];
00130                         msgTwist.twist.linear.y = linVelocity[1];
00131                         msgTwist.twist.linear.z = linVelocity[2];
00132                         msgTwist.twist.angular.x = angVelocity[0];
00133                         msgTwist.twist.angular.y = angVelocity[1];
00134                         msgTwist.twist.angular.z = angVelocity[2];
00135                         _pubTwist.publish(msgTwist);
00136 
00137                         _lastPublishedStatusTime = currentSimulationTime;
00138 
00139         //}
00140 
00141     }
00142 
00143 
00144 
00145 
00146 
00147      //Do the control
00148      if ((now-_lastReceivedCmdTime).toSec() > 0.1){
00149 
00150          simResetDynamicObject(_associatedObjectID);
00151          simSetObjectIntParameter( _associatedObjectID,3003, 1);
00152          simSetObjectIntParameter( _associatedObjectID,3004, 0); // Set the shape relative to the joint as NOT RESPONSABLE
00153 
00154          if ((now-_lastPrintedMsg).toSec() >= 1){
00155 
00156              std::stringstream ss;
00157              //ss << "- [" << _associatedObjectName << "] No command received since more than " << (now-_lastReceivedCmdTime).toSec() << "s!" << std::endl;
00158              ss <<"- [" << _associatedObjectName << "]  No commands: Static mode activated." << std::endl;
00159              simAddStatusbarMessage(ss.str().c_str());
00160              //ConsoleHandler::printInConsole(ss);
00161              _lastPrintedMsg = now;
00162 
00163          }
00164          return;
00165      } else
00166 
00167      {
00168          std::stringstream ss;
00169          //simResetDynamicObject(_associatedObjectID);
00170          simSetObjectIntParameter( _associatedObjectID,3003, 0);
00171          ss << " Receiving and applying commands from ROS." << std::endl;
00172          ConsoleHandler::printInConsole(ss);
00173 
00174      }
00175 
00176 
00177     // Command w.r.t. the quadrotor frame
00178     Eigen::Matrix< simFloat, 3, 1> ForceCommand(0.0 , 0.0 , (simFloat)_Commands[3]);
00179     Eigen::Matrix< simFloat, 3, 1> TorqueCommand ((simFloat)_Commands[0] , (simFloat)_Commands[1] , (simFloat)_Commands[2]);
00180 
00181     // Command w.r.t. the world frame
00182     //Eigen::Matrix< simFloat, 3, 1> worldForce = orientation*ForceCommand;
00183     //Eigen::Matrix< simFloat, 3, 1> worldTorqueCommand = orientation*TorqueCommand;
00184 
00185 
00186     // Print information
00187     //std::cout << "FORCE BOSY:"<< std::endl;
00188    // std::cout <<"x: "<< ForceCommand[0] <<" y: " << ForceCommand[1] <<"z: "<< ForceCommand[2]  << std::endl;
00189 
00190     //std::cout << "TORQUE BODY:"<< std::endl;
00191     //std::cout <<"x: "<< TorqueCommand[0] <<" y: " << TorqueCommand[1] <<"z: "<< TorqueCommand[2]  << std::endl;
00192 
00193     const Eigen::Matrix< simFloat, 3, 1> worldTorqueCommand = nwuToNed*orientation*TorqueCommand; //rotate torque to world frame
00194     const Eigen::Matrix< simFloat, 3, 1> worldForce = nwuToNed*orientation*ForceCommand;
00195 
00196 
00197 
00198 
00199 
00200 //std::cout << "WORLD FORCE APPLIED:"<< std::endl;
00201 //std::cout <<"x: "<< worldTorqueCommand[0] <<" y: " << worldTorqueCommand[1] <<"z: "<< worldTorqueCommand[2]  << std::endl;
00202 
00203 
00204 
00205 
00206     // Apply force and torque to the quadrotor
00207    if(simAddForceAndTorque(_associatedObjectID,worldForce.data() ,worldTorqueCommand.data() )==-1){
00208           simSetLastError( _associatedObjectName.c_str(), "Error applying force.");
00209       }
00210  //  else
00211 //   {
00212 //       for (uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00213 //          if(simSetJointTargetVelocity(_handleOfJoint[motorIdx], 2.5*_Commands[3])==-1){
00214 //             simSetLastError( simGetObjectName(_handleOfJoint[motorIdx]), "Error applying velocity.");
00215 //           }
00216 //        }
00217 //     }
00218 
00219 
00220 
00221 
00222 
00223 
00224 //    if ((now-_lastReceivedCmdTime).toSec() > 0.1){
00225 //        //_tkMotorCommands = std::vector<double>(4,0);
00226 //        // worldTorqueCommand = 0.0;
00227 //       // _tkCommands.roll = 0.0;
00228 //       // _tkCommands.yaw = 0.0;
00229 //        //_tkCommands.thrust = _quadrotorMass*9.8*0.8;
00230 //
00231 //
00232 //      _Commands[0]= 0;
00233 //      _Commands[1]= 0;
00234 //      _Commands[2]= 0;
00235 //      _Commands[3]= _quadrotorMass*9.81;
00236 //
00237 //        if ((now-_lastPrintedMsg).toSec() >= 1){
00238 //            std::stringstream ss;
00239 //            ss << "- [" << _associatedObjectName << "] No command received since more than " << (now-_lastReceivedCmdTime).toSec() << "s!" << std::endl;
00240 //            simAddStatusbarMessage(ss.str().c_str());
00241 //            ConsoleHandler::printInConsole(ss);
00242 //            _lastPrintedMsg = now;
00243 //        }
00244 //    }
00245 
00246 
00247 
00248     }
00249 
00250 
00251 
00252 void QuadrotorHandler::_initialize(){
00253     if (_initialized)
00254         return;
00255 
00256     // get some data from the main object
00257     std::vector<unsigned char> developerCustomData;
00258     getDeveloperCustomData(developerCustomData);
00259 
00260     // 2. From that retrieved data, try to extract sub-data with the IMU_DATA_MAIN tag:
00261     std::vector<unsigned char> tempMainData;
00262     std::stringstream ss;
00263 
00264     if (CAccess::extractSerializationData(developerCustomData, CustomDataHeaders::QUADROTOR_DATA_MAIN,tempMainData)){
00265         int temp_freq = CAccess::pop_int(tempMainData);
00266         if (temp_freq > 0){
00267                 _ObjStatusFrequency = temp_freq;
00268                 //std::cout << "Found Twist target in " << _associatedObjectName << ". Frequency publisher: " << _ObjTwistFrequency << std::endl;
00269 
00270                 ss << "- [Quadrotor] in '" << _associatedObjectName << "'. Frequency publisher: " << _ObjStatusFrequency << "." << std::endl;
00271                 ConsoleHandler::printInConsole(ss);
00272         } else {
00273                 //std::cout << "Found Twist target in " << _associatedObjectName << " at the simulation frequency. " << std::endl;
00274 
00275                 ss << "- [Quadrotor] in '" << _associatedObjectName << "'. Frequency publisher: Simulation frequency. " << std::endl;
00276             ConsoleHandler::printInConsole(ss);
00277         }
00278 
00279 
00280 
00281 
00282 
00283 
00284     }
00285 
00286 
00287     // We need to find the handle of quadrotor motors, and CoM.
00288     for(uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00289         _handleOfJoint[motorIdx] = -1;
00290     }
00291     std::vector<int> toExplore;
00292     toExplore.push_back(_associatedObjectID); // We start exploration with the base of the quadrotor-tree
00293     while (toExplore.size()!=0)
00294     {
00295         int objHandle=toExplore[toExplore.size()-1];
00296         toExplore.pop_back();
00297         // 1. Add this object's children to the list to explore:
00298         int index=0;
00299         int childHandle=simGetObjectChild(objHandle,index++);
00300         while (childHandle!=-1) {
00301             toExplore.push_back(childHandle);
00302 //            std::cout << "Adding " << simGetObjectName(childHandle) << " to exploration list." << std::endl;
00303             childHandle=simGetObjectChild(objHandle,index++);
00304         }
00305         // 2. Now check if this object has one of the tags we are looking for:
00306         // a. Get all the developer data attached to this scene object (this is custom data added by the developer):
00307         int buffSize=simGetObjectCustomDataLength(objHandle,CustomDataHeaders::DEVELOPER_DATA_HEADER);
00308         if (buffSize!=0) { // Yes there is some custom data written by us (the developer with the DEVELOPER_DATA_HEADER header)
00309             char* datBuff=new char[buffSize];
00310             simGetObjectCustomData(objHandle,CustomDataHeaders::DEVELOPER_DATA_HEADER,datBuff);
00311             std::vector<unsigned char> developerCustomData(datBuff,datBuff+buffSize);
00312             delete[] datBuff;
00313             // b. From that retrieved data, try to extract sub-data with the searched tags:
00314             std::vector<unsigned char> quadrotorTagData;
00315             for (uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00316                 if (CAccess::extractSerializationData(developerCustomData,CustomDataHeaders::QUADROTOR_DATA_MOTOR_0+motorIdx,quadrotorTagData)){
00317                     _handleOfJoint[motorIdx]=objHandle; // We found the QUADROTOR_DATA_MOTOR_i tag. This is the i-th motor!
00318                     simGetObjectPosition(objHandle,_associatedObjectID,_jointPosition[motorIdx]);
00319                     ss << "- [" << _associatedObjectName << "] Found motor " << motorIdx << " in position ["
00320                             << _jointPosition[motorIdx][0] << ", "
00321                             << _jointPosition[motorIdx][1] << ", "
00322                             << _jointPosition[motorIdx][2] << "]." <<  std::endl;
00323                 }
00324             }
00325             if (CAccess::extractSerializationData(developerCustomData,CustomDataHeaders::QUADROTOR_DATA_COM,quadrotorTagData)){
00326                     _handleOfCoM=objHandle; // We found the QUADROTOR_DATA_MOTOR_i tag. This is the i-th motor!
00327                     ss << "- [" << _associatedObjectName << "] Found CENTER OF MASS in '"<< simGetObjectName(objHandle) <<"'." << std::endl;
00328             }
00329         }
00330     }
00331 
00332 
00333     // Subscriber of the command
00334     std::string objectName(_associatedObjectName);
00335     std::replace( objectName.begin(), objectName.end(), '#', '_');
00336 
00337     try
00338         {
00339              _sub = _nh.subscribe(objectName+"/command", 1000, &QuadrotorHandler::CommandsCallback, this);
00340         }
00341 
00342     catch (ros::Exception &e)
00343         {
00344             std::stringstream ss(e.what());
00345             ss << std::endl;
00346             ConsoleHandler::printInConsole(ss);
00347         }
00348 
00349 
00350 
00351     ConsoleHandler::printInConsole(ss);
00352     _initialized=true;
00353 }
00354 
00355 void QuadrotorHandler::CommandsCallback(const sensor_msgs::JointStateConstPtr& msg){
00356     if ( msg->effort.size() == 4){
00357 
00358         _Commands = msg->effort;
00359         _lastReceivedCmdTime = ros::Time::now();
00360 
00361     } else {
00362         simSetLastError( _associatedObjectName.c_str(), "Received wrong command size.");
00363 
00364     }
00365 }
00366 
00367 
00368 
00369 PLUGINLIB_EXPORT_CLASS(QuadrotorHandler, GenericObjectHandler)
00370 
00371 
00372 
00373 


quadrotor_handler
Author(s): Giovanni Claudio
autogenerated on Mon Apr 3 2017 04:03:54