00001 #include "r2_gazebo_interface/GazeboInterface.h"
00002
00003 using namespace gazebo;
00004
00005 GazeboInterface::GazeboInterface()
00006 : ModelPlugin()
00007 , advancedMode(false)
00008 {
00009 }
00010
00011 GazeboInterface::~GazeboInterface()
00012 {
00013
00014 rosNodePtr->shutdown();
00015 }
00016
00017 void GazeboInterface::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
00018 {
00019
00020 modelPtr = _model;
00021
00022 prevStatesUpdateTime = _model->GetWorld()->GetSimTime();
00023 prevStatusUpdateTime = _model->GetWorld()->GetSimTime();
00024
00025
00026 robotControllerPtr.reset(new RobotController(modelPtr));
00027
00028
00029 std::string robotNamespace = "";
00030
00031 if (_sdf->HasElement("robotNamespace"))
00032 {
00033 robotNamespace = _sdf->GetElement("robotNamespace")->Get<std::string>() + "/";
00034 }
00035
00036 std::string paramsNamespace = "";
00037
00038 if (_sdf->HasElement("paramsNamespace"))
00039 {
00040 paramsNamespace = _sdf->GetElement("paramsNamespace")->Get<std::string>() + "/";
00041 }
00042
00043 if (!_sdf->HasElement("jointCommandsTopic"))
00044 {
00045 ROS_FATAL("GazeboInterface plugin missing <jointCommandsTopic>, cannot proceed");
00046 return;
00047 }
00048 else
00049 {
00050 jointCommandsTopic = _sdf->GetElement("jointCommandsTopic")->Get<std::string>();
00051 }
00052
00053 if (!_sdf->HasElement("jointStatesTopic"))
00054 {
00055 ROS_FATAL("GazeboInterface plugin missing <jointStatesTopic>, cannot proceed");
00056 return;
00057 }
00058 else
00059 {
00060 jointStatesTopic = _sdf->GetElement("jointStatesTopic")->Get<std::string>();
00061 }
00062
00063 if (!_sdf->HasElement("jointCapabilitiesTopic"))
00064 {
00065 ROS_FATAL("GazeboInterface plugin missing <jointCapabilitiesTopic>, cannot proceed");
00066 return;
00067 }
00068 else
00069 {
00070 jointCapabilitiesTopic = _sdf->GetElement("jointCapabilitiesTopic")->Get<std::string>();
00071 }
00072
00073 if (!_sdf->HasElement("jointStatesRate"))
00074 {
00075 jointStatesStepTime = 0.;
00076 }
00077 else
00078 {
00079 jointStatesStepTime = 1. / _sdf->GetElement("jointStatesRate")->Get<double>();
00080 }
00081
00082 if (!_sdf->HasElement("jointCommandRefsTopic"))
00083 {
00084 ROS_FATAL("GazeboInterface plugin missing <jointCommandRefsTopic>, cannot proceed");
00085 return;
00086 }
00087 else
00088 {
00089 jointCommandRefsTopic = _sdf->GetElement("jointCommandRefsTopic")->Get<std::string>();
00090 }
00091
00092 if (!_sdf->HasElement("advancedMode"))
00093 {
00094 ROS_INFO("GazeboInterface plugin missing <advancedMode>, defaults to false");
00095 advancedMode = false;
00096 }
00097 else
00098 {
00099 std::string strVal = _sdf->GetElement("advancedMode")->Get<std::string>();
00100
00101 if (strVal == "1")
00102 {
00103 advancedMode = true;
00104 }
00105 else if (strVal == "0")
00106 {
00107 advancedMode = false;
00108 }
00109 else
00110 {
00111 ROS_WARN("GazeboInterface plugin <advancedMode> should be type bool (true/false), defaults to false");
00112 advancedMode = false;
00113 }
00114 }
00115
00116 ROS_INFO("GazeboInterface plugin advancedMode: %s", advancedMode ? "true" : "false");
00117
00118 if (advancedMode)
00119 {
00120 if (!_sdf->HasElement("jointControlTopic"))
00121 {
00122 ROS_FATAL("GazeboInterface plugin missing <jointControlTopic>, cannot proceed");
00123 return;
00124 }
00125 else
00126 {
00127 jointControlTopic = _sdf->GetElement("jointControlTopic")->Get<std::string>();
00128 }
00129
00130 if (!_sdf->HasElement("jointStatusTopic"))
00131 {
00132 ROS_FATAL("GazeboInterface plugin missing <jointStatusTopic>, cannot proceed");
00133 return;
00134 }
00135 else
00136 {
00137 jointStatusTopic = _sdf->GetElement("jointStatusTopic")->Get<std::string>();
00138 }
00139
00140 if (!_sdf->HasElement("jointStatusRate"))
00141 {
00142 jointStatusStepTime = 0.;
00143 }
00144 else
00145 {
00146 jointStatusStepTime = 1. / _sdf->GetElement("jointStatusRate")->Get<double>();
00147 }
00148 }
00149
00150
00151 rosNodePtr.reset(new ros::NodeHandle(robotNamespace));
00152 paramsNodePtr.reset(new ros::NodeHandle(paramsNamespace));
00153
00154
00155
00156 updateConnectionPtr = event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboInterface::update, this));
00157
00158 ROS_INFO("Gazebo Interface plugin loaded");
00159 }
00160
00161 void GazeboInterface::traverseParams(XmlRpc::XmlRpcValue param, std::map<std::string, XmlRpc::XmlRpcValue>& valMap, std::string searchKey,
00162 std::string ns, std::string name)
00163 {
00164 std::string fullName;
00165
00166 if (name.empty())
00167 {
00168 fullName = ns;
00169 }
00170 else
00171 {
00172 if (ns.empty())
00173 {
00174 fullName = name;
00175 }
00176 else
00177 {
00178 fullName = ns + "/" + name;
00179 }
00180 }
00181
00182 if (param.getType() == XmlRpc::XmlRpcValue::TypeStruct)
00183 {
00184
00185 for (XmlRpc::XmlRpcValue::iterator paramIt = param.begin(); paramIt != param.end(); ++paramIt)
00186 {
00187 traverseParams(paramIt->second, valMap, searchKey, fullName, paramIt->first);
00188 }
00189 }
00190 else if (searchKey == "")
00191 {
00192
00193 valMap.insert(std::make_pair(fullName, param));
00194 }
00195 else if (searchKey == name)
00196 {
00197
00198 valMap.insert(std::make_pair(ns, param));
00199 }
00200
00201
00202 }
00203
00204 bool GazeboInterface::getDoubleVal(XmlRpc::XmlRpcValue& val, double& doubleVal)
00205 {
00206 if (val.getType() == XmlRpc::XmlRpcValue::TypeInt)
00207 {
00208 doubleVal = (double)(int)val;
00209 }
00210 else if (val.getType() == XmlRpc::XmlRpcValue::TypeDouble)
00211 {
00212 doubleVal = (double)val;
00213 }
00214 else
00215 {
00216 return false;
00217 }
00218
00219 return true;
00220 }
00221
00222 void GazeboInterface::Init()
00223 {
00224 ROS_DEBUG("add joints");
00225
00226 physics::Joint_V model_joints = modelPtr->GetJoints();
00227
00228
00229 for (physics::Joint_V::iterator j_it = model_joints.begin(); j_it != model_joints.end(); ++j_it)
00230 {
00231 robotControllerPtr->addJoint((*j_it), advancedMode);
00232 ROS_DEBUG("Add %s to controller", (*j_it)->GetName().c_str());
00233 }
00234
00235 XmlRpc::XmlRpcValue param;
00236
00237
00238 if (paramsNodePtr->getParam("dependency", param))
00239 {
00240 ROS_DEBUG("set dependencies");
00241
00242 std::map<std::string, XmlRpc::XmlRpcValue> dependentChildrenMap;
00243 traverseParams(param, dependentChildrenMap, "children");
00244
00245 std::map<std::string, XmlRpc::XmlRpcValue> dependentFactorsMap;
00246 traverseParams(param, dependentFactorsMap, "factors");
00247
00248
00249 for (std::map<std::string, XmlRpc::XmlRpcValue>::iterator depIt = dependentChildrenMap.begin();
00250 depIt != dependentChildrenMap.end(); ++depIt)
00251 {
00252 XmlRpc::XmlRpcValue factorVal = dependentFactorsMap[depIt->first];
00253
00254
00255 if (depIt->second.getType() == XmlRpc::XmlRpcValue::TypeString)
00256 {
00257 double val;
00258
00259 if (getDoubleVal(factorVal, val))
00260 {
00261
00262 ROS_INFO("Add joint dependency: %s, %s, %f", ((std::string)depIt->second).c_str(), depIt->first.c_str(), (double)factorVal);
00263 robotControllerPtr->addJointDependency((std::string)depIt->second, depIt->first, (double)factorVal);
00264 }
00265 else
00266 {
00267 ROS_WARN("Add dependency for %s (child) to %s (parent) not completed because factor not an appropriate type (double or int)",
00268 ((std::string)depIt->second).c_str(), depIt->first.c_str());
00269 }
00270 }
00271 else if (depIt->second.getType() == XmlRpc::XmlRpcValue::TypeArray)
00272 {
00273 if (factorVal.getType() == XmlRpc::XmlRpcValue::TypeArray && factorVal.size() == depIt->second.size())
00274 {
00275 for (int i = 0; i < depIt->second.size(); ++i)
00276 {
00277 if (depIt->second[i].getType() == XmlRpc::XmlRpcValue::TypeString)
00278 {
00279 double val;
00280
00281 if (getDoubleVal(factorVal[i], val))
00282 {
00283
00284 ROS_INFO("Add joint dependency: %s, %s, %f", ((std::string)depIt->second[i]).c_str(), depIt->first.c_str(), val);
00285 robotControllerPtr->addJointDependency((std::string)depIt->second[i], depIt->first, val);
00286 }
00287 else
00288 {
00289 ROS_WARN("Add dependency for %s (child) to %s (parent) not completed because factor not an appropriate type (double or int)",
00290 ((std::string)depIt->second[i]).c_str(), depIt->first.c_str());
00291 }
00292 }
00293 else
00294 {
00295 ROS_WARN("A dependency to %s (parent) not added because type is invalid", depIt->first.c_str());
00296 }
00297 }
00298 }
00299 else
00300 {
00301 ROS_WARN("Add dependency to %s (parent) not completed because children/factors array size not the same",
00302 depIt->first.c_str());
00303 }
00304 }
00305 }
00306 }
00307
00308
00309 if (paramsNodePtr->getParam("initial_position", param))
00310 {
00311 ROS_DEBUG("set initial positions");
00312 bool radians = true;
00313
00314 if (param.hasMember("radians") && param["radians"].getType() == XmlRpc::XmlRpcValue::TypeBoolean)
00315 {
00316 radians = (bool)param["radians"];
00317 ROS_DEBUG("radians: %d", radians);
00318 }
00319 else
00320 {
00321 ROS_WARN("No 'radians' member provided (or invalid type) in 'initial_position'; assumed true");
00322 }
00323
00324 std::map<std::string, XmlRpc::XmlRpcValue> initialPoseMapParams;
00325
00326 if (param.hasMember("position"))
00327 {
00328 traverseParams(param["position"], initialPoseMapParams);
00329
00330
00331 std::map<std::string, double> initialPoseMap;
00332
00333 for (std::map<std::string, XmlRpc::XmlRpcValue>::iterator poseIt = initialPoseMapParams.begin();
00334 poseIt != initialPoseMapParams.end(); ++poseIt)
00335 {
00336 double val;
00337
00338 if (getDoubleVal(poseIt->second, val))
00339 {
00340 if (radians == false)
00341 {
00342 val = GZ_DTOR(val);
00343 }
00344
00345 if (modelPtr->GetJoint(poseIt->first))
00346 {
00347 initialPoseMap.insert(std::make_pair(poseIt->first, val));
00348 ROS_DEBUG("initial position of %s set to %f", poseIt->first.c_str(), val);
00349 }
00350 else
00351 {
00352 ROS_INFO("initial position of %s ignored because model doesn't contain joint", poseIt->first.c_str());
00353 }
00354 }
00355 else
00356 {
00357 ROS_WARN("Sim initial position value (%s) ignored because it is not a valid type (double or int)", poseIt->first.c_str());
00358 }
00359 }
00360
00361
00362 robotControllerPtr->setJointPositions(initialPoseMap);
00363 }
00364 }
00365 else
00366 {
00367 ROS_WARN("No 'position' member provided in 'initial_position'");
00368 }
00369
00370
00371 if (paramsNodePtr->getParam("position_pid", param))
00372 {
00373 ROS_DEBUG("set position PIDs");
00374 std::map<std::string, XmlRpc::XmlRpcValue> positionPidMap;
00375 traverseParams(param, positionPidMap);
00376
00377
00378 for (std::map<std::string, XmlRpc::XmlRpcValue>::iterator pidIt = positionPidMap.begin();
00379 pidIt != positionPidMap.end(); ++pidIt)
00380 {
00381 if (pidIt->second.getType() == XmlRpc::XmlRpcValue::TypeArray && pidIt->second.size() >= 3)
00382 {
00383 std::vector<double> gains{0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0};
00384 bool valid = true;
00385
00386 for (int i = 0; i < pidIt->second.size(); ++ i)
00387 {
00388 valid &= getDoubleVal(pidIt->second[i], gains[i]);
00389 }
00390
00391 if (valid)
00392 {
00393 ROS_DEBUG("setPosPid: %s, %f, %f, %f, %f, %f, %f, %f", pidIt->first.c_str(), gains[0], gains[1], gains[2], gains[3], gains[4], gains[5], gains[6]);
00394 robotControllerPtr->setPosPid(pidIt->first, gains[0], gains[1], gains[2], gains[3], gains[4], gains[5], gains[6]);
00395 }
00396 else
00397 {
00398 ROS_WARN("position PID for %s not set because the values are not valid (double or int)", pidIt->first.c_str());
00399 }
00400 }
00401 else
00402 {
00403 ROS_WARN("position PID values for %s not set because it is not an array of size 3 or greater", pidIt->first.c_str());
00404 }
00405 }
00406 }
00407
00408
00409 if (paramsNodePtr->getParam("velocity_pid", param))
00410 {
00411 ROS_DEBUG("set velocity PIDs");
00412 std::map<std::string, XmlRpc::XmlRpcValue> velocityPidMap;
00413 traverseParams(param, velocityPidMap);
00414
00415
00416 for (std::map<std::string, XmlRpc::XmlRpcValue>::iterator pidIt = velocityPidMap.begin();
00417 pidIt != velocityPidMap.end(); ++pidIt)
00418 {
00419 if (pidIt->second.getType() == XmlRpc::XmlRpcValue::TypeArray && pidIt->second.size() >= 3)
00420 {
00421 std::vector<double> gains{0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0};
00422 bool valid = true;
00423
00424 for (int i = 0; i < pidIt->second.size(); ++ i)
00425 {
00426 valid &= getDoubleVal(pidIt->second[i], gains[i]);
00427 }
00428
00429 if (valid)
00430 {
00431 ROS_DEBUG("setVelPid: %s, %f, %f, %f, %f, %f, %f, %f", pidIt->first.c_str(), gains[0], gains[1], gains[2], gains[3], gains[4], gains[5], gains[6]);
00432 robotControllerPtr->setVelPid(pidIt->first, gains[0], gains[1], gains[2], gains[3], gains[4], gains[5], gains[6]);
00433 }
00434 else
00435 {
00436 ROS_WARN("velocity PID for %s not set because the values are not valid (double or int)", pidIt->first.c_str());
00437 }
00438 }
00439 else
00440 {
00441 ROS_WARN("velocity PID values for %s not set because it is not an array of size 3 or greater", pidIt->first.c_str());
00442 }
00443 }
00444 }
00445
00446
00447 if (!advancedMode)
00448 {
00449
00450 physics::Joint_V model_joints2 = modelPtr->GetJoints();
00451
00452
00453 for (physics::Joint_V::iterator j_it2 = model_joints.begin(); j_it2 != model_joints.end(); ++j_it2)
00454 {
00455 robotControllerPtr->setJointPosTarget((*j_it2)->GetName(), (*j_it2)->GetAngle(0).Radian());
00456 }
00457 }
00458
00459
00460 jointCommandsSub = rosNodePtr->subscribe(jointCommandsTopic, 5, &GazeboInterface::commandJoints, this);
00461
00462
00463 jointStatePub = rosNodePtr->advertise<sensor_msgs::JointState>(jointStatesTopic, true);
00464
00465
00466 jointCapabilitiesPub = rosNodePtr->advertise<r2_msgs::JointCapability>(jointCapabilitiesTopic, true);
00467
00468
00469 jointCommandRefsPub = rosNodePtr->advertise<r2_msgs::JointCommand>(jointCommandRefsTopic, true);
00470
00471 if (advancedMode)
00472 {
00473
00474 jointControlSub = rosNodePtr->subscribe(jointControlTopic, 5, &GazeboInterface::controlJoints, this);
00475
00476
00477 jointStatusPub = rosNodePtr->advertise<r2_msgs::JointStatusArray>(jointStatusTopic, true);
00478 }
00479
00480 ROS_INFO("Gazebo Interface plugin initialized");
00481 }
00482
00483 void GazeboInterface::update()
00484 {
00485 common::Time currTime = modelPtr->GetWorld()->GetSimTime();
00486
00487
00488 robotControllerPtr->update();
00489
00490
00491 if ((currTime - prevStatesUpdateTime).Double() >= jointStatesStepTime)
00492 {
00493 prevStatesUpdateTime = currTime;
00494 sensor_msgs::JointStatePtr msgPtr(new sensor_msgs::JointState);
00495 r2_msgs::JointCommandPtr refPtr(new r2_msgs::JointCommand);
00496 r2_msgs::JointCapabilityPtr capPtr(new r2_msgs::JointCapability);
00497 msgPtr->header.stamp = ros::Time::now();
00498 refPtr->header.stamp = ros::Time::now();
00499
00500
00501 robotControllerPtr->getJointStates(jointStates);
00502
00503
00504 for (std::map<std::string, RobotController::JointState>::const_iterator stateIt = jointStates.begin(); stateIt != jointStates.end(); ++stateIt)
00505 {
00506 std::string::size_type index = stateIt->first.find("fixed");
00507
00508 if (index != std::string::npos)
00509 {
00510 continue;
00511 }
00512
00513 index = stateIt->first.find("/joint");
00514
00515 if (index != std::string::npos)
00516 {
00517 std::string name = stateIt->first;
00518 msgPtr->name.push_back(name);
00519 msgPtr->position.push_back(stateIt->second.position);
00520 msgPtr->velocity.push_back(stateIt->second.velocity);
00521 msgPtr->effort.push_back(stateIt->second.effort);
00522 }
00523 else
00524 {
00525 msgPtr->name.push_back(stateIt->first);
00526 msgPtr->position.push_back(stateIt->second.position);
00527 msgPtr->velocity.push_back(stateIt->second.velocity);
00528 msgPtr->effort.push_back(stateIt->second.effort);
00529 }
00530 }
00531
00532
00533 robotControllerPtr->getJointTargets(jointCommandRefs);
00534
00535
00536 for (std::map<std::string, RobotController::JointState>::const_iterator refsIt = jointCommandRefs.begin(); refsIt != jointCommandRefs.end(); ++refsIt)
00537 {
00538 std::string::size_type index = refsIt->first.find("fixed");
00539
00540 if (index == std::string::npos)
00541 {
00542 refPtr->name.push_back(refsIt->first);
00543 refPtr->desiredPosition.push_back(refsIt->second.position);
00544 refPtr->desiredPositionVelocityLimit.push_back(refsIt->second.velocity);
00545 refPtr->feedForwardTorque.push_back(refsIt->second.effort);
00546 refPtr->proportionalGain.push_back(0);
00547 refPtr->derivativeGain.push_back(0);
00548 refPtr->integralGain.push_back(0);
00549 refPtr->positionLoopTorqueLimit.push_back(0);
00550 refPtr->positionLoopWindupLimit.push_back(0);
00551 refPtr->torqueLoopVelocityLimit.push_back(0);
00552 }
00553 }
00554
00555
00556 robotControllerPtr->getJointLimits(jointLimits);
00557
00558
00559 for (std::map<std::string, std::pair<double, double> >::const_iterator limsIt = jointLimits.begin(); limsIt != jointLimits.end(); ++limsIt)
00560 {
00561 std::string::size_type index = limsIt->first.find("fixed");
00562
00563 if (index == std::string::npos)
00564 {
00565 capPtr->name.push_back(limsIt->first);
00566 capPtr->positionLimitMax.push_back(limsIt->second.second);
00567 capPtr->positionLimitMin.push_back(limsIt->second.first);
00568 capPtr->velocityLimit.push_back(2.5);
00569 capPtr->torqueLimit.push_back(1000.);
00570 }
00571 }
00572
00573 jointCommandRefsPub.publish(refPtr);
00574 jointStatePub.publish(msgPtr);
00575
00576 jointCapabilitiesPub.publish(capPtr);
00577 }
00578
00579
00580 if (advancedMode && (currTime - prevStatusUpdateTime).Double() >= jointStatusStepTime)
00581 {
00582 prevStatusUpdateTime = currTime;
00583 robotControllerPtr->publishJointStatuses(jointStatusPub);
00584 }
00585 }
00586
00587 void GazeboInterface::commandJoints(const sensor_msgs::JointState::ConstPtr& msg)
00588 {
00589 bool setPos = msg->position.size() >= msg->name.size();
00590 bool setVel = msg->velocity.size() >= msg->name.size();
00591 bool setEffort = msg->effort.size() >= msg->name.size();
00592
00593 ROS_DEBUG("GazeboInterface received joint command");
00594
00595 for (unsigned int i = 0; i < msg->name.size(); ++i)
00596 {
00597 if (setPos)
00598 {
00599 robotControllerPtr->setJointPosTarget(msg->name[i], msg->position[i]);
00600 }
00601 else if (setEffort)
00602 {
00603 robotControllerPtr->setJointEffortTarget(msg->name[i], msg->effort[i]);
00604 }
00605 else if (setVel)
00606 {
00607 robotControllerPtr->setJointVelTarget(msg->name[i], msg->velocity[i]);
00608 }
00609 }
00610 }
00611
00612
00613 void GazeboInterface::controlJoints(const r2_msgs::JointControl::ConstPtr& msg)
00614 {
00615 ROS_DEBUG("GazeboInterface received joint control");
00616 robotControllerPtr->setJointControl(msg);
00617 }
00618
00619 GZ_REGISTER_MODEL_PLUGIN(GazeboInterface)