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
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
00046 simGetShapeMassAndInertia(_associatedObjectID,&_quadrotorMass,intertia,compos,NULL);
00047
00048
00049 _associatedObjectName = simGetObjectName(_associatedObjectID);
00050 std::string objectName(_associatedObjectName);
00051 std::replace( objectName.begin(), objectName.end(), '#', '_');
00052
00053
00054
00055
00056
00057 _pubPose = _nh.advertise<geometry_msgs::PoseStamped>(objectName+"/pose", 1);
00058
00059 _pubTwist = _nh.advertise<geometry_msgs::TwistStamped>(objectName+"/twist", 1);
00060
00061
00062
00063
00064
00065 }
00066
00067
00068
00069 void QuadrotorHandler::handleSimulation(){
00070
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;
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
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;
00100 orientation = nwuToNed*orientation;
00101
00102 if (orientation.w()<0){
00103 orientation.coeffs() *=-1;
00104 }
00105
00106
00107 const simFloat currentSimulationTime = simGetSimulationTime();
00108
00109
00110
00111
00112
00113
00114
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
00148 if ((now-_lastReceivedCmdTime).toSec() > 0.1){
00149
00150 simResetDynamicObject(_associatedObjectID);
00151 simSetObjectIntParameter( _associatedObjectID,3003, 1);
00152 simSetObjectIntParameter( _associatedObjectID,3004, 0);
00153
00154 if ((now-_lastPrintedMsg).toSec() >= 1){
00155
00156 std::stringstream ss;
00157
00158 ss <<"- [" << _associatedObjectName << "] No commands: Static mode activated." << std::endl;
00159 simAddStatusbarMessage(ss.str().c_str());
00160
00161 _lastPrintedMsg = now;
00162
00163 }
00164 return;
00165 } else
00166
00167 {
00168 std::stringstream ss;
00169
00170 simSetObjectIntParameter( _associatedObjectID,3003, 0);
00171 ss << " Receiving and applying commands from ROS." << std::endl;
00172 ConsoleHandler::printInConsole(ss);
00173
00174 }
00175
00176
00177
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
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 const Eigen::Matrix< simFloat, 3, 1> worldTorqueCommand = nwuToNed*orientation*TorqueCommand;
00194 const Eigen::Matrix< simFloat, 3, 1> worldForce = nwuToNed*orientation*ForceCommand;
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 if(simAddForceAndTorque(_associatedObjectID,worldForce.data() ,worldTorqueCommand.data() )==-1){
00208 simSetLastError( _associatedObjectName.c_str(), "Error applying force.");
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248 }
00249
00250
00251
00252 void QuadrotorHandler::_initialize(){
00253 if (_initialized)
00254 return;
00255
00256
00257 std::vector<unsigned char> developerCustomData;
00258 getDeveloperCustomData(developerCustomData);
00259
00260
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
00269
00270 ss << "- [Quadrotor] in '" << _associatedObjectName << "'. Frequency publisher: " << _ObjStatusFrequency << "." << std::endl;
00271 ConsoleHandler::printInConsole(ss);
00272 } else {
00273
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
00288 for(uint motorIdx = 0; motorIdx < 4; ++motorIdx){
00289 _handleOfJoint[motorIdx] = -1;
00290 }
00291 std::vector<int> toExplore;
00292 toExplore.push_back(_associatedObjectID);
00293 while (toExplore.size()!=0)
00294 {
00295 int objHandle=toExplore[toExplore.size()-1];
00296 toExplore.pop_back();
00297
00298 int index=0;
00299 int childHandle=simGetObjectChild(objHandle,index++);
00300 while (childHandle!=-1) {
00301 toExplore.push_back(childHandle);
00302
00303 childHandle=simGetObjectChild(objHandle,index++);
00304 }
00305
00306
00307 int buffSize=simGetObjectCustomDataLength(objHandle,CustomDataHeaders::DEVELOPER_DATA_HEADER);
00308 if (buffSize!=0) {
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
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;
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;
00327 ss << "- [" << _associatedObjectName << "] Found CENTER OF MASS in '"<< simGetObjectName(objHandle) <<"'." << std::endl;
00328 }
00329 }
00330 }
00331
00332
00333
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