Quadrotor_tk_Handler.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_tk_handler/Quadrotor_tk_Handler.h>
00005 #include <stdio.h>
00006 #include <v_repLib.h>
00007 
00008 #include <telekyb_msgs/TKState.h>
00009 #include <sensor_msgs/Imu.h>
00010 
00011 #include <eigen3/Eigen/Geometry>
00012 
00013 #include <vrep_ros_plugin/access.h>
00014 #include <vrep_ros_plugin/ConsoleHandler.h>
00015 
00016 Quadrotor_tk_Handler::Quadrotor_tk_Handler() : GenericObjectHandler(),
00017 _torqueToForceRatio(0.01738),
00018 _handleOfCoM(-1),
00019 _ctrlMode(CustomDataHeaders::DIRECT),
00020 _tkMotorCommands(4,0),
00021 //_tkCommands(3,0),
00022 _quadrotorMass(0.8),
00023 // Before changing the following 3 parameters be careful and look closely into the controller which is implemented below
00024 _att_cutoff(2.9),
00025 _att_damping(1.0),
00026 _kp_yaw(1),
00027 _lastReceivedCmdTime(ros::Time::now()),
00028 _previousTime(ros::Time::now()),
00029 _integralTermRoll(0.0),
00030 _integralTermPitch(0.0)
00031 {
00032 }
00033 
00034 Quadrotor_tk_Handler::~Quadrotor_tk_Handler(){
00035 }
00036 
00037 unsigned int Quadrotor_tk_Handler::getObjectType() const {
00038         return CustomDataHeaders::QUADROTOR_TK_DATA_MAIN;
00039 }
00040 
00041 /*void Quadrotor_tk_Handler::setID(int newID){
00042     _id=newID;
00043 }
00044 
00045 int Quadrotor_tk_Handler::getID(){
00046     return(_id);
00047 }*/
00048 
00049 /*
00050 void Quadrotor_tk_Handler::setAssociatedObject(int objID,int objUniqueID){
00051     _associatedObjectID=objID;
00052     _associatedObjectUniqueID=objUniqueID;
00053 }
00054 
00055 int Quadrotor_tk_Handler::getAssociatedObject(){
00056     return(_associatedObjectID);
00057 }
00058 
00059 int Quadrotor_tk_Handler::getAssociatedObjectUniqueId(){
00060     return(_associatedObjectUniqueID);
00061 }
00062 
00063 void Quadrotor_tk_Handler::synchronizeSceneObject(){
00064     // We update Quadrotor_tk_Handler's associated scene object custom data:
00065     putQuadrotorTagToSceneObject(_associatedObjectID,_torqueToForceRatio);
00066 }
00067  */
00068 
00069 void Quadrotor_tk_Handler::synchronize(){
00070         //    // We update Quadrotor_tk_Handler's data from its associated scene object custom data:
00071         //    // 1. Get all the developer data attached to the associated scene object (this is custom data added by the developer):
00072         //    int buffSize=simGetObjectCustomDataLength(_associatedObjectID,CustomDataHeaders::DEVELOPER_DATA_HEADER);
00073         //    char* datBuff=new char[buffSize];
00074         //    simGetObjectCustomData(_associatedObjectID,CustomDataHeaders::DEVELOPER_DATA_HEADER,datBuff);
00075         //    std::vector<unsigned char> developerCustomData(datBuff,datBuff+buffSize);
00076         //    delete[] datBuff;
00077         //    // 2. From that retrieved data, try to extract sub-data with the QUADROTOR_DATA_TF_RATIO tag:
00078         //    std::vector<unsigned char> tempMainData;
00079         //    if (CAccess::extractSerializationData(developerCustomData,CustomDataHeaders::QUADROTOR_DATA_TF_RATIO,tempMainData))
00080         //    { // Yes, the tag is there. For now we only have to synchronize _maxVelocity:
00081         //        _torqueToForceRatio=CAccess::pop_float(tempMainData);
00082         //        std::cout << "torque to force ratio: " << _torqueToForceRatio << std::endl;
00083         //    }
00084 
00085 
00086         simFloat intertia[9];
00087         simFloat compos[3];
00088 
00089         // Get the mass of the quadcopter
00090         simGetShapeMassAndInertia(_associatedObjectID,&_quadrotorMass,intertia,compos,NULL);
00091 
00092         // Remove # chars for compatibility with ROS
00093         _associatedObjectName = simGetObjectName(_associatedObjectID);
00094         std::string objectName(_associatedObjectName);
00095         std::replace( objectName.begin(), objectName.end(), '#', '_');
00096 
00097         // Publisher of the quadropter status
00098         _pub = _nh.advertise<telekyb_msgs::TKState>(objectName+"/status", 1000);
00099 
00100         // Publisher of the IMU
00101         _pubIMU = _nh.advertise<sensor_msgs::Imu>(objectName+"/IMU", 1000);
00102 
00103         // Subscriber of the command from TeleKib
00104         //_sub = _nh.subscribe("/Telekyb/TelekybCore_0/Commands", 1000, &Quadrotor_tk_Handler::tkMotorCommandsCallback, this);
00105 }
00106 
00107 
00108 //void Quadrotor_tk_Handler::setThrustToForceRatio(float thrustToForceRatio){
00109 //    _torqueToForceRatio=thrustToForceRatio;
00110 //    synchronizeSceneObject(); // make sure the associated scene object has the same values stored as this
00111 //}
00112 //
00113 //float Quadrotor_tk_Handler::getThrustToForceRatio(){
00114 //    return(_torqueToForceRatio);
00115 //}
00116 
00117 //void Quadrotor_tk_Handler::putQuadrotorTagToSceneObject(int objectHandle,float torqueToForceRatio){
00118 //    // This creates/updates a QUADROTOR_DATA_MAIN tag
00119 //    // 1. Get all the developer data attached to the associated scene object (this is custom data added by the developer):
00120 //    int buffSize=simGetObjectCustomDataLength(objectHandle,DEVELOPER_DATA_HEADER);
00121 //    char* datBuff=new char[buffSize];
00122 //    simGetObjectCustomData(objectHandle,DEVELOPER_DATA_HEADER,datBuff);
00123 //    std::vector<unsigned char> developerCustomData(datBuff,datBuff+buffSize);
00124 //    delete[] datBuff;
00125 //    // 2. From that retrieved data, extract sub-data with the QUADROTOR_DATA_MAIN tag, update it, and add it back to the retrieved data:
00126 //    std::vector<unsigned char> tempMainData;
00127 //    CAccess::extractSerializationData(developerCustomData,QUADROTOR_DATA_MAIN,tempMainData);
00128 //    tempMainData.clear(); // we discard the old value (if present)
00129 //    CAccess::push_float(tempMainData,torqueToForceRatio); // we replace it with the new value
00130 //    CAccess::insertSerializationData(developerCustomData,QUADROTOR_DATA_MAIN,tempMainData);
00131 //    // 3. We add/update the scene object with the updated custom data:
00132 //    simAddObjectCustomData(objectHandle,DEVELOPER_DATA_HEADER,(simChar*)&developerCustomData[0],int(developerCustomData.size()));
00133 //}
00134 
00135 void Quadrotor_tk_Handler::handleSimulation(){
00136         // called when the main script calls: simHandleModule (it is called time by time)
00137         if(!_initialized){
00138                 _initialize();
00139         }
00140 
00141         // TimeStep Computation
00142         ros::Time now = ros::Time::now();
00143         ros::Duration timeStep = now - _previousTime;
00144         //DEBUG
00145 //      std::cout<< "DEBUG: TimeStep: " << timeStep << std::endl;
00146 
00147         // Position of the quadrotor (x,y,z)
00148         Eigen::Matrix<simFloat, 3, 1> position;
00149         // Orientation of the quadrotor
00150         Eigen::Quaternion< simFloat > orientation; //(x,y,z,w)
00151         Eigen::Matrix<simFloat, 3, 1> linVelocity;
00152         Eigen::Matrix<simFloat, 3, 1> angVelocity;
00153         const static Eigen::Quaternion< simFloat > nwuToNed(0,1,0,0);
00154 
00155         if(simGetObjectPosition(_handleOfCoM, -1, position.data())!=-1 &&
00156                         simGetObjectQuaternion(_handleOfCoM, -1, orientation.coeffs().data())!=-1 &&
00157                         simGetObjectVelocity(_handleOfCoM, linVelocity.data(), angVelocity.data())!=-1){
00158                 //DEBUG
00159                 //std::cout<<"DEBUG: Rotation ";
00160 
00161                 position = nwuToNed*position;
00162                 linVelocity = nwuToNed*linVelocity;
00163                 angVelocity = orientation.conjugate()*angVelocity; // Express angular velocity in body frame
00164                 orientation = nwuToNed*orientation; // change world frame to north-east-down
00165 
00166 
00167                 //angVelocity = nwuToNed*angVelocity;
00168                 // use only positive w (not necessary)
00169                 if (orientation.w()<0){
00170                         orientation.coeffs() *=-1;
00171                 }
00172 
00173                 // Fill the status msg
00174                 telekyb_msgs::TKState msg;
00175                 msg.header.stamp = now;
00176                 msg.pose.position.x = position[0];
00177                 msg.pose.position.y = position[1];
00178                 msg.pose.position.z = position[2];
00179                 msg.pose.orientation.w = orientation.w();
00180                 msg.pose.orientation.x = orientation.x();
00181                 msg.pose.orientation.y = orientation.y();
00182                 msg.pose.orientation.z = orientation.z();
00183                 msg.twist.linear.x = linVelocity[0];
00184                 msg.twist.linear.y = linVelocity[1];
00185                 msg.twist.linear.z = linVelocity[2];
00186                 msg.twist.angular.x = angVelocity[0];
00187                 msg.twist.angular.y = angVelocity[1];
00188                 msg.twist.angular.z = angVelocity[2];
00189                 std::stringstream ss;
00190                 //DEBUG:
00191                 //std::cout << "Filling the TKState msg" << std::endl;
00192                 _pub.publish(msg);
00193         }
00194 
00195         simFloat TotforceZ = 0.0;
00196 
00197         if (_ctrlMode == CustomDataHeaders::DIRECT){
00198                 //DEBUG
00199                 std::cout<<"DEBUG: DIRECT MODE ";
00200 
00201                 for(uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00202                         const simFloat force[3] = {0.0, 0.0, -(simFloat)_tkMotorCommands[motorIdx]};
00203                         const simFloat torque[3] = {0.0, 0.0, _torqueToForceRatio*(1-2*((int)(motorIdx/2)))*(simFloat)_tkMotorCommands[motorIdx]};
00204 
00205                         // Compute the net force
00206                         TotforceZ =+ -(simFloat)_tkMotorCommands[motorIdx];
00207 
00208                         // Try to apply a force to the object
00209                         if(simAddForce(_associatedObjectID, _jointPosition[motorIdx], force)==-1){
00210                                 simSetLastError( _associatedObjectName.c_str(), "Error applying force.");
00211                         } else if(simAddForceAndTorque(_associatedObjectID, NULL, torque)==-1){
00212                                 simSetLastError( _associatedObjectName.c_str(), "Error applying torque.");
00213                         } else if(simSetJointTargetVelocity(_handleOfJoint[motorIdx], 10*_tkMotorCommands[motorIdx])==-1){
00214                                 simSetLastError( simGetObjectName(_handleOfJoint[motorIdx]), "Error applying velocity.");
00215                         }
00216                 }
00217         } else if (_ctrlMode == CustomDataHeaders::INTERNAL){
00218 
00219                 //              timeStep=now-previousTime;
00220                 //DEBUG
00221                 //              std::cout<<"INTERNAL MODE "<< timeStep;
00222                 //DEBUG
00223                 //std::cout<<"INTERNAL MODE ";
00224 
00225                 // Compute the net force
00226                 TotforceZ = (simFloat)_tkCommands.thrust;
00227 
00228 //              Eigen::Matrix< simFloat, 3, 1> rpy = orientation.toRotationMatrix().eulerAngles(2,1,0);
00229                 //              Eigen::Matrix< simFloat, 3, 3> rotMatrix = orientation.toRotationMatrix();
00230                 //              Eigen::Matrix< simFloat, 3, 1> rpy(
00231                 //                              atan2(rotMatrix(3,1),rotMatrix(3,2)),
00232                 //                              acos(rotMatrix(3,3)),
00233                 //                              -atan2(rotMatrix(1,3),rotMatrix(2,3)));
00234                 //
00235                 //                              atan2(rotMatrix(3,2),rotMatrix(3,3)),
00236                 //                              atan2(-rotMatrix(3,1),sqrt(rotMatrix(3,2)*rotMatrix(3,2)+rotMatrix(3,3)*rotMatrix(3,3))),
00237                 //                              atan2(rotMatrix(2,1),rotMatrix(1,1)));
00238 
00239                 Eigen::Matrix< simFloat, 3, 3> R = orientation.toRotationMatrix();
00240                 Eigen::Matrix< simFloat, 3, 1> rpy;
00241                 rpy(0) = atan2((double)R(2,1), (double)R(2,2));
00242                 rpy(1) = atan2(-R(2,0), sqrt( R(2,1)*R(2,1) + R(2,2)*R(2,2) ) );
00243                 rpy(2) = atan2((double)R(1,0),(double)R(0,0));
00244 
00245 //              std::cout << "DEBUG: (_tkCommands.roll): " <<  (_tkCommands.roll) <<std::endl;
00246 //              std::cout << "DEBUG: rpy: " << rpy(0) << "  "<< rpy(1) << "  " << rpy(2) <<std::endl;
00247 //              std::cout << "DEBUG: R: " << R <<std::endl;
00248 //
00249 //              std::cout << "DEBUG: R(3,1): " << R(3,1) <<std::endl;
00250 //              std::cout << "DEBUG: R(3,2): " << R(3,2) <<std::endl;
00251 //              std::cout << "DEBUG: R(3,3): " << R(3,3) <<std::endl;
00252                 // Definition of sin_r,cos_r etc.
00253                 const double cos_r = cos((double)rpy(0));
00254                 //std::cout << "DEBUG: cos_r: " <<  cos_r <<std::endl;
00255                 const double sin_r = sin((double)rpy(0));
00256                 //std::cout << "DEBUG: sin_r: " <<  sin_r <<std::endl;
00257                 const double cos_p = cos((double)rpy(1));
00258                 //std::cout << "DEBUG: cos_p: " <<  cos_p <<std::endl;
00259                 const double sin_p = sin((double)rpy(1));
00260                 //std::cout << "DEBUG: sin_p: " <<  sin_p <<std::endl;
00261                 const double tan_p = tan((double)rpy(1));
00262 
00263                 const Eigen::Matrix<simFloat, 3, 3> angVelToEulerRate = (Eigen::Matrix<simFloat, 3, 3>() <<
00264                                 1.0, sin_r*tan_p, cos_r*tan_p,
00265                                 0.0,       cos_r,      -sin_r,
00266                                 0.0, sin_r/cos_p, cos_r/cos_p).finished();
00267 
00268                 Eigen::Matrix< simFloat, 3, 1> rpyRate = angVelToEulerRate*angVelocity;
00269                 const simFloat kp_att = _att_cutoff;
00270                 const simFloat kd_att = _att_damping;
00271 
00272                 // Errors
00273                 const simFloat errorRoll = (_tkCommands.roll)-(rpy(0));
00274                 const simFloat errorPitch = (_tkCommands.pitch)-(rpy(1));
00275 
00276                 // Computaton of the integral terms
00277                 _integralTermRoll = _integralTermRoll + timeStep.toSec() * errorRoll;
00278                 _integralTermPitch = _integralTermPitch + timeStep.toSec() * errorPitch;
00279                 if(_integralTermRoll<0.0001)_integralTermRoll=0.0;
00280                 if(_integralTermPitch<0.0001)_integralTermPitch=0.0;
00281 
00282                 //DEBUG
00283 //              std::cout<< "DEBUG: _integralTermRoll: " << _integralTermRoll << std::endl;
00284 //              std::cout<< "DEBUG: _integralTermPitch: " << _integralTermPitch << std::endl;
00285 
00286 
00287 
00288 
00289                 Eigen::Matrix< simFloat, 3, 1> rpyTorque(
00290                                 //roll
00291                                 kp_att*(errorRoll) + kd_att*(0-rpyRate(0))+0*0.001*_integralTermRoll,
00292                                 //pitch
00293 //                              0.1*kp_att*(errorPitch) + 0.02*kd_att*(0-rpyRate(1))+0*0.002*_integralTermPitch,
00294                                 kp_att*(errorPitch) + kd_att*(0-rpyRate(1))+0*0.002*_integralTermPitch,
00295                                 //yaw
00296                                 _kp_yaw*(_tkCommands.yaw- rpyRate(2)));  //sign is the opposite of the yaw angular velocity
00297 
00298                 //DEBUG
00299 //              std::cout << "DEBUG: (_tkCommands.roll): " <<  (_tkCommands.roll) <<std::endl;
00300 //              std::cout << "DEBUG: rpy: " << rpy(0) << "  "<< rpy(1) << "  " << rpy(2) <<std::endl;
00301 //              std::cout << "DEBUG: sin(_tkCommands.pitch): " <<  sin(_tkCommands.pitch) <<std::endl;
00302 //              std::cout << "DEBUG: sin(rpy(1)): " << sin(rpy(1)) <<std::endl;
00303 //              std::cout << "DEBUG: errorRoll: " << errorRoll <<std::endl;
00304 //              std::cout << "DEBUG: errorPitch: " << errorPitch <<std::endl;
00305 
00306                 rpyTorque = nwuToNed*orientation*rpyTorque; //rotate torque to world frame
00307                 //const Eigen::Matrix< simFloat, 3, 1> worldForce = nwuToNed*Eigen::Matrix< simFloat, 3, 1>(0.0,0.0,(simFloat)_tkCommands.thrust);
00308 
00309                 Eigen::Matrix< simFloat, 3, 1> worldForce = nwuToNed*orientation*Eigen::Matrix< simFloat, 3, 1>(0.0,0.0,(simFloat)_tkCommands.thrust);
00310 
00311 
00312                 // To Delete Probably
00313 //              if(worldForce(0)<0.001 && worldForce(0)>-0.001)worldForce(0)=0;
00314 //              if(worldForce(1)<0.001 && worldForce(1)>-0.001)worldForce(1)=0;
00315 
00316 
00317                 //DEBUG torques and forces
00318 //              std::cout << "DEBUG: rpyTorque: " << rpyTorque(0) <<"|"<< rpyTorque(1) <<"|"<< rpyTorque(2) <<"|" <<std::endl;
00319 //              std::cout << "DEBUG: forces: " << worldForce(0) <<"|"<< worldForce(1) <<"|"<< worldForce(2) <<"|" <<std::endl;
00320 
00321                 //        std::stringstream ss;
00322                 //        ss << "applying force : [" << worldForce.transpose() << std::endl;
00323                 //        ConsoleHandler::printInConsole(ss);
00324                 if(simAddForceAndTorque(_associatedObjectID, worldForce.data(), rpyTorque.data())==-1){
00325                         //                                                      if(simAddForceAndTorque(_associatedObjectID, worldForce.data(), 0)==-1){
00326                         simSetLastError( _associatedObjectName.c_str(), "Error applying force.");
00327                 } else {
00328                         for (uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00329                                 // the following is needed to rotate the propellers
00330                                 if(simSetJointTargetVelocity(_handleOfJoint[motorIdx], _tkCommands.thrust)==-1){
00331                                         simSetLastError( simGetObjectName(_handleOfJoint[motorIdx]), "Error applying velocity.");
00332                                 }
00333                         }
00334                 }
00335                 _previousTime=now;
00336         }
00337 
00338         Eigen::Matrix<simFloat, 3, 1> TotCommandforces(0.0, 0.0, TotforceZ);
00339         Eigen::Matrix<simFloat, 3, 1> VectorG (0.0, 0.0, 9.8);
00340         VectorG = orientation.conjugate()*VectorG; // Express angular velocity in body frame
00341 
00342         // Fill the IMU msg
00343         sensor_msgs::Imu msg1;
00344         msg1.header.stamp = ros::Time::now();
00345         msg1.angular_velocity.x = angVelocity[0];
00346         msg1.angular_velocity.y = angVelocity[1];
00347         msg1.angular_velocity.z = angVelocity[2];
00348         msg1.linear_acceleration.x = TotCommandforces[0]/_quadrotorMass + VectorG[0];
00349         msg1.linear_acceleration.y = TotCommandforces[1]/_quadrotorMass + VectorG[1];
00350         msg1.linear_acceleration.z = TotCommandforces[2]/_quadrotorMass + VectorG[2];
00351         _pubIMU.publish(msg1); // Publish the Imu message in ROS
00352 
00353         if ((now-_lastReceivedCmdTime).toSec() > 0.1){
00354                 _tkMotorCommands = std::vector<double>(4,0);
00355                 _tkCommands.pitch = 0.0;
00356                 _tkCommands.roll = 0.0;
00357                 _tkCommands.yaw = 0.0;
00358                 _tkCommands.thrust = _quadrotorMass*9.8;
00359                 std::stringstream ss;
00360                 ss << "I am here" << std::endl;
00361                 simAddStatusbarMessage(ss.str().c_str());
00362                 ConsoleHandler::printInConsole(ss);
00363                 if ((now-_lastPrintedMsg).toSec() >= 1){
00364                         std::stringstream ss;
00365                         ss << "- [" << _associatedObjectName << "] No command received since more than " << (now-_lastReceivedCmdTime).toSec() << "s!" << std::endl;
00366                         simAddStatusbarMessage(ss.str().c_str());
00367                         ConsoleHandler::printInConsole(ss);
00368                         _lastPrintedMsg = now;
00369                 }
00370         }
00371 
00372         //    if ((now-_lastPrintedMsg).toSec() >= 1){
00373         //        std::stringstream sstream("I am alive at simulation time = ");
00374         //        sstream << simGetSimulationTime() << std::endl;
00375         //        simAddStatusbarMessage(sstream.str().c_str());
00376         //        _lastPrintedMsg = now;
00377         //    }
00378 }
00379 
00380 
00381 void Quadrotor_tk_Handler::_initialize(){
00382         if (_initialized)
00383                 return;
00384 
00385         // get some data from the main object
00386         std::vector<unsigned char> developerCustomData;
00387         getDeveloperCustomData(developerCustomData);
00388 
00389         // 2. From that retrieved data, try to extract sub-data with the IMU_DATA_MAIN tag:
00390         std::vector<unsigned char> tempMainData;
00391         std::stringstream ss;
00392 
00393         if (CAccess::extractSerializationData(developerCustomData, CustomDataHeaders::IMU_DATA_MASS,tempMainData)){
00394                 //      if (false){
00395                 _quadrotorMass=CAccess::pop_float(tempMainData);
00396                 ss << "- [" << _associatedObjectName << "] Setting mass to: " << _quadrotorMass << "." << std::endl;
00397         } else {
00398                 _quadrotorMass = 24.0;
00399                 ss << "- [" << _associatedObjectName << "] Mass of the quadrotor not specified. using " << _quadrotorMass << " as default."  << std::endl;
00400         }
00401 
00402         if (CAccess::extractSerializationData(developerCustomData, CustomDataHeaders::QUADROTOR_DATA_TF_RATIO,tempMainData)){
00403                 _torqueToForceRatio=CAccess::pop_float(tempMainData);
00404                 ss << "- [" << _associatedObjectName << "] Setting torque to force ratio to: " << _torqueToForceRatio << "." << std::endl;
00405         } else {
00406                 _torqueToForceRatio = 0.01738;
00407                 ss << "- [" << _associatedObjectName << "] Torque to force ratio not specified. using " << _torqueToForceRatio << " as default."  << std::endl;
00408         }
00409 
00410         if (CAccess::extractSerializationData(developerCustomData, CustomDataHeaders::QUADROTOR_DATA_CTRL_MODE,tempMainData)){
00411                 const int ctrlMode = CAccess::pop_int(tempMainData);
00412                 if (ctrlMode == (int)(CustomDataHeaders::DIRECT)){
00413                         _ctrlMode = CustomDataHeaders::DIRECT;
00414                         ss << "- [" << _associatedObjectName << "] Using DIRECT control mode." << std::endl;
00415                 } else if (ctrlMode == (int)(CustomDataHeaders::INTERNAL)){
00416                         _ctrlMode = CustomDataHeaders::INTERNAL;
00417                         ss << "- [" << _associatedObjectName << "] Using INTERNAL control mode." << std::endl;
00418                 } else {
00419                         _ctrlMode = CustomDataHeaders::DIRECT;
00420                         ss << "- [" << _associatedObjectName << "] Invalid control mode specified. using DIRECT as default." << std::endl;
00421                 }
00422 
00423         } else {
00424                 _ctrlMode = CustomDataHeaders::DIRECT;
00425                 ss << "- [" << _associatedObjectName << "] Control mode not specified. using DIRECT as default."  << std::endl;
00426         }
00427 
00428         // We need to find the handle of quadrotor motors, and CoM.
00429         for(uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00430                 _handleOfJoint[motorIdx] = -1;
00431         }
00432         std::vector<int> toExplore;
00433         toExplore.push_back(_associatedObjectID); // We start exploration with the base of the quadrotor-tree
00434         while (toExplore.size()!=0)
00435         {
00436                 int objHandle=toExplore[toExplore.size()-1];
00437                 toExplore.pop_back();
00438                 // 1. Add this object's children to the list to explore:
00439                 int index=0;
00440                 int childHandle=simGetObjectChild(objHandle,index++);
00441                 while (childHandle!=-1) {
00442                         toExplore.push_back(childHandle);
00443                         //            std::cout << "Adding " << simGetObjectName(childHandle) << " to exploration list." << std::endl;
00444                         childHandle=simGetObjectChild(objHandle,index++);
00445                 }
00446                 // 2. Now check if this object has one of the tags we are looking for:
00447                 // a. Get all the developer data attached to this scene object (this is custom data added by the developer):
00448                 int buffSize=simGetObjectCustomDataLength(objHandle,CustomDataHeaders::DEVELOPER_DATA_HEADER);
00449                 if (buffSize!=0) { // Yes there is some custom data written by us (the developer with the DEVELOPER_DATA_HEADER header)
00450                         char* datBuff=new char[buffSize];
00451                         simGetObjectCustomData(objHandle,CustomDataHeaders::DEVELOPER_DATA_HEADER,datBuff);
00452                         std::vector<unsigned char> developerCustomData(datBuff,datBuff+buffSize);
00453                         delete[] datBuff;
00454                         // b. From that retrieved data, try to extract sub-data with the searched tags:
00455                         std::vector<unsigned char> quadrotorTagData;
00456                         for (uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00457                                 if (CAccess::extractSerializationData(developerCustomData,CustomDataHeaders::QUADROTOR_DATA_MOTOR_0+motorIdx,quadrotorTagData)){
00458                                         _handleOfJoint[motorIdx]=objHandle; // We found the QUADROTOR_DATA_MOTOR_i tag. This is the i-th motor!
00459                                         simGetObjectPosition(objHandle,_associatedObjectID,_jointPosition[motorIdx]);
00460                                         ss << "- [" << _associatedObjectName << "] Found motor " << motorIdx << " in position ["
00461                                                         << _jointPosition[motorIdx][0] << ", "
00462                                                         << _jointPosition[motorIdx][1] << ", "
00463                                                         << _jointPosition[motorIdx][2] << "]." <<  std::endl;
00464                                 }
00465                         }
00466                         if (CAccess::extractSerializationData(developerCustomData,CustomDataHeaders::QUADROTOR_DATA_COM,quadrotorTagData)){
00467                                 _handleOfCoM=objHandle; // We found the QUADROTOR_DATA_MOTOR_i tag. This is the i-th motor!
00468                                 ss << "- [" << _associatedObjectName << "] Found CENTER OF MASS in '"<< simGetObjectName(objHandle) <<"'." << std::endl;
00469                         }
00470                 }
00471         }
00472 
00473 
00474         // Subscriber of the command from TeleKib
00475         std::string objectName(_associatedObjectName);
00476         std::replace( objectName.begin(), objectName.end(), '#', '_');
00477 
00478         if (_ctrlMode == CustomDataHeaders::DIRECT){
00479                 try{
00480                         _sub = _nh.subscribe(objectName+"/command", 1000, &Quadrotor_tk_Handler::tkMotorCommandsCallback, this);
00481                 } catch (ros::Exception &e) {
00482                         std::stringstream ss(e.what());
00483                         ss << std::endl;
00484                         ConsoleHandler::printInConsole(ss);
00485                 }
00486 
00487         } else if (_ctrlMode == CustomDataHeaders::INTERNAL){
00488                 try{
00489                         //_sub = _nh.subscribe(objectName+"/command", 1000, &Quadrotor_tk_Handler::tkCommandsCallback, this);
00490                         std::cout<< "Subscribed to Commands";
00491                         //                                      _sub = _nh.subscribe("/TeleKyb/TeleKybCore_0/Commands", 1000, &Quadrotor_tk_Handler::tkCommandsCallback(), this);
00492                         _sub = _nh.subscribe("/TeleKyb/TeleKybCore_0/Commands", 1000, &Quadrotor_tk_Handler::tkCommandsCallback, this);
00493 
00494                 } catch (ros::Exception &e) {
00495                         std::stringstream ss(e.what());
00496                         ss << std::endl;
00497                         ConsoleHandler::printInConsole(ss);
00498                 }
00499         } else {
00500                 simSetLastError( _associatedObjectName.c_str(), "Unknown control mode.");
00501         }
00502 
00503 
00504 
00505         ConsoleHandler::printInConsole(ss);
00506         _initialized=true;
00507 }
00508 
00509 void Quadrotor_tk_Handler::tkMotorCommandsCallback(const telekyb_msgs::TKMotorCommands::ConstPtr& msg){
00510         if (msg->force.size() == 4){
00511                 _tkMotorCommands = msg->force;
00512                 _lastReceivedCmdTime = ros::Time::now();
00513         } else {
00514                 simSetLastError( _associatedObjectName.c_str(), "Received wrong command size.");
00515                 //        std::cout << "Received wrong command containing " <<  msg->force.size() << " elements" << std::endl;
00516         }
00517 }
00518 
00519 void Quadrotor_tk_Handler::tkCommandsCallback(const telekyb_msgs::TKCommands::ConstPtr& msg){
00520         _tkCommands = *msg;
00521         _lastReceivedCmdTime = ros::Time::now();
00522 }
00523 
00524 
00525 PLUGINLIB_EXPORT_CLASS(Quadrotor_tk_Handler, GenericObjectHandler)
00526 
00527 
00528 
00529 


quadrotor_tk_handler
Author(s):
autogenerated on Sat May 9 2015 13:16:55