00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string>
00004
00005 #include <gazebo/transport/Node.hh>
00006 #include <gazebo/common/Assert.hh>
00007
00008 #include "IOBPlugin.h"
00009
00010 namespace gazebo
00011 {
00012 GZ_REGISTER_MODEL_PLUGIN(IOBPlugin);
00013
00014 IOBPlugin::IOBPlugin() : publish_joint_state(false),
00015 publish_joint_state_step(0),
00016 publish_joint_state_counter(0),
00017 use_synchronized_command(false),
00018 use_velocity_feedback(false),
00019 use_joint_effort(false),
00020 use_loose_synchronized(true),
00021 iob_period(0.005),
00022 force_sensor_average_window_size(6),
00023 force_sensor_average_cnt(0),
00024 effort_average_window_size(6),
00025 effort_average_cnt(0),
00026 publish_step(2),
00027 publish_count(0)
00028 {
00029 }
00030
00031 IOBPlugin::~IOBPlugin() {
00032 }
00033
00034 void IOBPlugin::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf) {
00035
00036 this->controller_name = "hrpsys_gazebo_configuration";
00037 if (_sdf->HasElement("controller")) {
00038 this->controller_name = _sdf->Get<std::string>("controller");
00039 }
00040
00041 this->robot_name = _parent->GetScopedName();
00042 if (_sdf->HasElement("robotname")) {
00043 this->robot_name = _sdf->Get<std::string>("robotname");
00044 ROS_WARN("USE ROBOT NAME from URDF: %s, scoped name(%s)",
00045 this->robot_name.c_str(),
00046 _parent->GetScopedName().c_str());
00047 }
00048 this->controller_name = this->robot_name + "/" + this->controller_name;
00049
00050 if (_sdf->HasElement("force_sensor_average_window_size")) {
00051 this->force_sensor_average_window_size = _sdf->Get<float>("force_sensor_average_window_size");
00052 }
00053
00054 this->use_synchronized_command = false;
00055 if (_sdf->HasElement("synchronized_command")) {
00056 this->use_synchronized_command = _sdf->Get<bool>("synchronized_command");
00057 std::cerr << ";; use synchronized command" << std::endl;
00058 }
00059
00060 this->use_velocity_feedback = false;
00061 if (_sdf->HasElement("velocity_feedback")) {
00062 this->use_velocity_feedback = _sdf->Get<bool>("velocity_feedback");
00063 std::cerr << ";; use velocity feedback" << std::endl;
00064 }
00065
00066
00067 if (!ros::isInitialized()) {
00068 gzerr << "Not loading plugin since ROS hasn't been "
00069 << "properly initialized. Try starting gazebo with ros plugin:\n"
00070 << " gazebo -s libgazebo_ros_api_plugin.so\n";
00071 return;
00072 }
00073
00074
00075 this->rosNode = new ros::NodeHandle("");
00076
00077 this->model = _parent;
00078 this->world = this->model->GetWorld();
00079
00080
00081 this->sdf = _sdf;
00082
00083
00084 this->lastControllerUpdateTime = this->world->GetSimTime();
00085
00086
00087 if (this->rosNode->hasParam(this->controller_name)) {
00088 {
00089 std::string pname = this->controller_name + "/use_synchronized_command";
00090 if (this->rosNode->hasParam(pname)) {
00091 bool ret;
00092 this->rosNode->getParam(pname, ret);
00093 if (!this->use_synchronized_command) {
00094 this->use_synchronized_command = ret;
00095 } else {
00096 ROS_WARN("override use_synchronized_command at %d by %d",
00097 this->use_synchronized_command, ret);
00098 }
00099 }
00100 }
00101 {
00102 std::string pname = this->controller_name + "/use_loose_synchronized";
00103 if (this->rosNode->hasParam(pname)) {
00104 bool ret = false;
00105 this->rosNode->getParam(pname, ret);
00106 this->use_loose_synchronized = ret;
00107 }
00108 ROS_INFO("loose synchronized %d", this->use_loose_synchronized);
00109 }
00110 {
00111 std::string pname = this->controller_name + "/use_velocity_feedback";
00112 if (this->rosNode->hasParam(pname)) {
00113 bool ret;
00114 this->rosNode->getParam(pname, ret);
00115 ROS_WARN("override use_veolcity_feedback at %d by %d",
00116 this->use_velocity_feedback, ret);
00117 this->use_velocity_feedback = ret;
00118 }
00119 }
00120 {
00121 std::string pname = this->controller_name + "/use_joint_effort";
00122 if (this->rosNode->hasParam(pname)) {
00123 bool ret;
00124 this->rosNode->getParam(pname, ret);
00125 ROS_INFO("use_joint_effort %d", ret);
00126 this->use_joint_effort = ret;
00127 }
00128 }
00129 {
00130 std::string pname = this->controller_name + "/iob_rate";
00131 if (this->rosNode->hasParam(pname)) {
00132 double rate;
00133 this->rosNode->getParam(pname, rate);
00134 ROS_INFO("iob rate %f", rate);
00135 this->iob_period = 1.0 / rate;
00136 }
00137 }
00138 {
00139 std::string pname = this->controller_name + "/force_sensor_average_window_size";
00140 if (this->rosNode->hasParam(pname)) {
00141 int asize;
00142 this->rosNode->getParam(pname, asize);
00143 force_sensor_average_window_size = asize;
00144 ROS_INFO("force_sensor_average_window_size %d", asize);
00145 }
00146 }
00147 {
00148 std::string pname = this->controller_name + "/publish_joint_state";
00149 if (this->rosNode->hasParam(pname)) {
00150 std::string topic;
00151 if (this->rosNode->hasParam(pname + "/topic")) {
00152 this->rosNode->getParam(pname + "/topic", topic);
00153 } else {
00154 topic = this->robot_name + "/joint_state";
00155 }
00156
00157 this->publish_joint_state_counter = 0;
00158 this->publish_joint_state_step = 1;
00159 if (this->rosNode->hasParam(pname + "/step")) {
00160 int stp;
00161 this->rosNode->getParam(pname + "/step", stp);
00162 this->publish_joint_state_step = stp;
00163 }
00164
00165 this->pubJointStateQueue = this->pmq.addPub<sensor_msgs::JointState>();
00166 this->pubJointState
00167 = this->rosNode->advertise<sensor_msgs::JointState>(topic, 100, true);
00168 ROS_INFO("publish joint state");
00169 this->publish_joint_state = true;
00170 }
00171 }
00172 XmlRpc::XmlRpcValue param_val;
00173 this->rosNode->getParam(this->controller_name, param_val);
00174 if (param_val.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00175 std::string rname = param_val["robotname"];
00176 XmlRpc::XmlRpcValue joint_lst = param_val["joints"];
00177 XmlRpc::XmlRpcValue fsensors = param_val["force_torque_sensors"];
00178 XmlRpc::XmlRpcValue fsensors_config = param_val["force_torque_sensors_config"];
00179 XmlRpc::XmlRpcValue imusensors = param_val["imu_sensors"];
00180 XmlRpc::XmlRpcValue imusensors_config = param_val["imu_sensors_config"];
00181
00182 if (rname != this->robot_name) {
00183 ROS_WARN("mismatch robotnames: %s (ros parameter) != %s (gazebo element)",
00184 rname.c_str(), this->robot_name.c_str());
00185 } else {
00186 ROS_INFO("robotname: %s", rname.c_str());
00187 }
00188
00189 if (joint_lst.getType() == XmlRpc::XmlRpcValue::TypeArray) {
00190 for(int s = 0; s < joint_lst.size(); s++) {
00191 std::string n = joint_lst[s];
00192 ROS_INFO("add joint: %s", n.c_str());
00193 this->jointNames.push_back(n);
00194 }
00195 } else {
00196 ROS_WARN("Controlled Joints: no setting exists");
00197 }
00198
00199 if (fsensors.getType() == XmlRpc::XmlRpcValue::TypeArray &&
00200 fsensors_config.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00201 for(int s = 0; s < fsensors.size(); s++) {
00202 this->forceSensorNames.push_back(fsensors[s]);
00203 }
00204 for(XmlRpc::XmlRpcValue::iterator f = fsensors_config.begin(); f != fsensors_config.end(); f++) {
00205 std::string sensor_name = f->first;
00206 if (f->second.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00207 std::string jn = f->second["joint_name"];
00208 std::string fi = f->second["frame_id"];
00209 ROS_INFO("force: %s, %s %s", sensor_name.c_str(), jn.c_str(), fi.c_str());
00210
00211 struct force_sensor_info fsi;
00212 fsi.joint = this->model->GetJoint(jn);
00213 if(!fsi.joint) {
00214 gzerr << "force torque joint (" << jn << ") not found\n";
00215 } else {
00216 fsi.frame_id = fi;
00217 XmlRpc::XmlRpcValue trs = f->second["translation"];
00218 XmlRpc::XmlRpcValue rot = f->second["rotation"];
00219 fsi.pose.reset();
00220 if ((trs.getType() == XmlRpc::XmlRpcValue::TypeArray) ||
00221 (rot.getType() == XmlRpc::XmlRpcValue::TypeArray)) {
00222 math::Vector3 vtr;
00223 math::Quaternion qt;
00224 if (trs.getType() == XmlRpc::XmlRpcValue::TypeArray) {
00225 vtr.x = xmlrpc_value_as_double(trs[0]);
00226 vtr.y = xmlrpc_value_as_double(trs[1]);
00227 vtr.z = xmlrpc_value_as_double(trs[2]);
00228 }
00229 if (rot.getType() == XmlRpc::XmlRpcValue::TypeArray) {
00230 qt.w = xmlrpc_value_as_double(rot[0]);
00231 qt.x = xmlrpc_value_as_double(rot[1]);
00232 qt.y = xmlrpc_value_as_double(rot[2]);
00233 qt.z = xmlrpc_value_as_double(rot[3]);
00234 }
00235 fsi.pose = PosePtr(new math::Pose (vtr, qt));
00236 this->forceSensors[sensor_name] = fsi;
00237 }
00238 }
00239 } else {
00240 ROS_ERROR("Force-Torque sensor: %s has invalid configuration", sensor_name.c_str());
00241 }
00242
00243 boost::shared_ptr<std::vector<boost::shared_ptr<geometry_msgs::WrenchStamped> > > forceValQueue(new std::vector<boost::shared_ptr<geometry_msgs::WrenchStamped> >);
00244
00245 for ( int i=0; i<this->force_sensor_average_window_size; i++ ){
00246 boost::shared_ptr<geometry_msgs::WrenchStamped> fbuf(new geometry_msgs::WrenchStamped);
00247 forceValQueue->push_back(fbuf);
00248 }
00249 this->forceValQueueMap[sensor_name] = forceValQueue;
00250 }
00251 } else {
00252 ROS_WARN("Force-Torque sensor: no setting exists");
00253 }
00254
00255 if (imusensors.getType() == XmlRpc::XmlRpcValue::TypeArray &&
00256 imusensors_config.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00257 for(int s = 0; s < imusensors.size(); s++) {
00258 this->imuSensorNames.push_back(imusensors[s]);
00259 }
00260 for(XmlRpc::XmlRpcValue::iterator im = imusensors_config.begin(); im != imusensors_config.end(); im++) {
00261 std::string sensor_name = im->first;
00262 if (im->second.getType() == XmlRpc::XmlRpcValue::TypeStruct) {
00263 std::string sn = im->second["ros_name"];
00264 std::string ln = im->second["link_name"];
00265 std::string fi = im->second["frame_id"];
00266 ROS_INFO("imu: %s, %s, %s, %s", sensor_name.c_str(), sn.c_str(),
00267 ln.c_str(), fi.c_str());
00268
00269 struct imu_sensor_info msi;
00270 msi.sensor_name = sn;
00271 msi.frame_id = fi;
00272 msi.link = this->model->GetLink(ln);
00273
00274 if (!msi.link) {
00275 gzerr << ln << " not found\n";
00276 } else {
00277
00278 msi.sensor = boost::dynamic_pointer_cast<sensors::ImuSensor>
00279 (sensors::SensorManager::Instance()->GetSensor
00280 (this->world->GetName() + "::" + msi.link->GetScopedName() + "::" + msi.sensor_name));
00281
00282 if (!msi.sensor) {
00283 gzerr << sensor_name << "(" \
00284 << (this->world->GetName() + "::" + msi.link->GetScopedName() + "::" + msi.sensor_name) \
00285 <<" not found\n" << "\n";
00286 }
00287 imuSensors[sensor_name] = msi;
00288 }
00289 } else {
00290 ROS_ERROR("IMU sensor: %s has invalid configuration", sensor_name.c_str());
00291 }
00292 }
00293 } else {
00294 ROS_WARN("IMU sensor: no setting exists");
00295 }
00296 } else {
00297 ROS_WARN_STREAM("param: " << this->controller_name << ", configuration is not an array.");
00298 }
00299 } else {
00300 ROS_ERROR_STREAM("controller: " << this->controller_name << " has no parameter.");
00301 }
00302
00303
00304 this->joints.resize(this->jointNames.size());
00305 ROS_INFO("joints size = %ld", this->joints.size());
00306 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00307 this->joints[i] = this->model->GetJoint(this->jointNames[i]);
00308 if (!this->joints[i]) {
00309 ROS_ERROR("%s robot expected joint[%s] not present, plugin not loaded",
00310 this->robot_name.c_str(), this->jointNames[i].c_str());
00311 return;
00312 }
00313 if (this->use_joint_effort) {
00314 this->joints[i]->SetProvideFeedback(true);
00315 }
00316 }
00317
00318
00319 this->effortLimit.resize(this->jointNames.size());
00320 for (unsigned i = 0; i < this->effortLimit.size(); ++i) {
00321 this->effortLimit[i] = this->joints[i]->GetEffortLimit(0);
00322 ROS_DEBUG("effort_limit: %s %f", this->joints[i]->GetName().c_str(), this->joints[i]->GetEffortLimit(0));
00323 }
00324
00325 {
00326
00327 this->errorTerms.resize(this->joints.size());
00328 for (unsigned i = 0; i < this->errorTerms.size(); ++i) {
00329 this->errorTerms[i].q_p = 0;
00330 this->errorTerms[i].d_q_p_dt = 0;
00331 this->errorTerms[i].k_i_q_i = 0;
00332 this->errorTerms[i].qd_p = 0;
00333 }
00334 }
00335
00336 {
00337
00338 #define JOINT_DAMPING_LOWER_BOUND 0.1
00339 for (unsigned int i = 0; i < this->jointNames.size(); ++i)
00340 {
00341
00342
00343 double maxEffort = this->joints[i]->GetEffortLimit(0);
00344 double maxVelocity = this->joints[i]->GetVelocityLimit(0);
00345 if (math::equal(maxVelocity, 0.0))
00346 {
00347 ROS_ERROR("Set Joint Damping Upper Limit: Joint[%s] "
00348 "effort limit [%f] velocity limit[%f]: "
00349 "velocity limit is unbounded, artificially setting "
00350 "damping coefficient max limit to 1.0. This should not"
00351 "have happened for Atlas robot, please check your model.",
00352 this->jointNames[i].c_str(), maxEffort, maxVelocity);
00353 maxVelocity = maxEffort;
00354 }
00355
00356 this->jointDampingMax.push_back(maxEffort / maxVelocity * 50);
00357
00358 this->jointDampingMin.push_back(JOINT_DAMPING_LOWER_BOUND);
00359
00360 this->jointDampingModel.push_back(this->joints[i]->GetDamping(0));
00361
00362 this->lastJointCFMDamping.push_back(this->joints[i]->GetDamping(0));
00363
00364 ROS_INFO("Bounds for joint[%s] is [%f, %f], model default is [%f]",
00365 this->jointNames[i].c_str(),
00366 this->jointDampingMin[i], this->jointDampingMax[i],
00367 this->jointDampingModel[i]);
00368 }
00369 }
00370
00371 {
00372
00373
00374 this->robotState.position.resize(this->joints.size());
00375 this->robotState.velocity.resize(this->joints.size());
00376 this->robotState.effort.resize(this->joints.size());
00377
00378 effortValQueue.resize(0);
00379 for(int i = 0; i < this->effort_average_window_size; i++) {
00380 boost::shared_ptr<std::vector<double> > vbuf(new std::vector<double> (this->joints.size()));
00381 effortValQueue.push_back(vbuf);
00382 }
00383
00384 this->robotState.ref_position.resize(this->joints.size());
00385 this->robotState.ref_velocity.resize(this->joints.size());
00386 if (!this->use_velocity_feedback) {
00387
00388 this->robotState.kp_position.resize(this->joints.size());
00389 this->robotState.ki_position.resize(this->joints.size());
00390 this->robotState.kd_position.resize(this->joints.size());
00391 this->robotState.kp_velocity.resize(this->joints.size());
00392 this->robotState.i_effort_min.resize(this->joints.size());
00393 this->robotState.i_effort_max.resize(this->joints.size());
00394 } else {
00395
00396 this->robotState.kpv_position.resize(this->joints.size());
00397 this->robotState.kpv_velocity.resize(this->joints.size());
00398 }
00399 }
00400
00401 {
00402 this->jointCommand.position.resize(this->joints.size());
00403 this->jointCommand.velocity.resize(this->joints.size());
00404 this->jointCommand.effort.resize(this->joints.size());
00405 if (!this->use_velocity_feedback) {
00406
00407 this->jointCommand.kp_position.resize(this->joints.size());
00408 this->jointCommand.ki_position.resize(this->joints.size());
00409 this->jointCommand.kd_position.resize(this->joints.size());
00410 this->jointCommand.kp_velocity.resize(this->joints.size());
00411 this->jointCommand.i_effort_min.resize(this->joints.size());
00412 this->jointCommand.i_effort_max.resize(this->joints.size());
00413 } else {
00414
00415 this->jointCommand.kpv_position.resize(this->joints.size());
00416 this->jointCommand.kpv_velocity.resize(this->joints.size());
00417 }
00418
00419 this->ZeroJointCommand();
00420 }
00421
00422
00423 this->deferredLoadThread = boost::thread(boost::bind(&IOBPlugin::DeferredLoad, this));
00424 }
00425
00426 void IOBPlugin::ZeroJointCommand() {
00427 for (unsigned i = 0; i < this->jointNames.size(); ++i) {
00428 this->jointCommand.position[i] = 0;
00429 this->jointCommand.velocity[i] = 0;
00430 this->jointCommand.effort[i] = 0;
00431 if (!this->use_velocity_feedback) {
00432
00433 this->robotState.kp_position[i] = 0;
00434 this->robotState.ki_position[i] = 0;
00435 this->robotState.kd_position[i] = 0;
00436 this->robotState.kp_velocity[i] = 0;
00437 this->robotState.i_effort_min[i] = 0;
00438 this->robotState.i_effort_max[i] = 0;
00439 } else {
00440 this->robotState.kpv_position[i] = 0;
00441 this->robotState.kpv_velocity[i] = 0;
00442 }
00443 }
00444 this->jointCommand.desired_controller_period_ms = 0;
00445 }
00446
00447 void IOBPlugin::LoadPIDGainsFromParameter() {
00448
00449 std::string namestr(this->controller_name);
00450
00451 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00452 std::string joint_ns(namestr);
00453 joint_ns += ("/gains/" + this->joints[i]->GetName() + "/");
00454
00455 if (this->use_velocity_feedback) {
00456 double p_v_val, vp_v_val;
00457 std::string p_v_str = std::string(joint_ns)+"p_v";
00458 std::string vp_v_str = std::string(joint_ns)+"vp_v";
00459 if (!this->rosNode->getParam(p_v_str, p_v_val)) {
00460 ROS_WARN("IOBPlugin: couldn't find a P_V param for %s", joint_ns.c_str());
00461 }
00462 if (!this->rosNode->getParam(vp_v_str, vp_v_val)) {
00463 ROS_WARN("IOBPlugin: couldn't find a VP_V param for %s", joint_ns.c_str());
00464 }
00465
00466 this->robotState.kpv_position[i] = p_v_val;
00467 this->robotState.kpv_velocity[i] = vp_v_val;
00468 } else {
00469
00470 double p_val = 0, i_val = 0, d_val = 0, i_clamp_val = 0, vp_val = 0;
00471 std::string p_str = std::string(joint_ns)+"p";
00472 std::string i_str = std::string(joint_ns)+"i";
00473 std::string d_str = std::string(joint_ns)+"d";
00474 std::string i_clamp_str = std::string(joint_ns)+"i_clamp";
00475 std::string vp_str = std::string(joint_ns)+"vp";
00476
00477 if (!this->rosNode->getParam(p_str, p_val)) {
00478 ROS_WARN("IOBPlugin: couldn't find a P param for %s", joint_ns.c_str());
00479 }
00480 if (!this->rosNode->getParam(i_str, i_val)) {
00481 ROS_WARN("IOBPlugin: couldn't find a I param for %s", joint_ns.c_str());
00482 }
00483 if (!this->rosNode->getParam(d_str, d_val)) {
00484 ROS_WARN("IOBPlugin: couldn't find a D param for %s", joint_ns.c_str());
00485 }
00486 if (!this->rosNode->getParam(i_clamp_str, i_clamp_val)) {
00487 ROS_WARN("IOBPlugin: couldn't find a I_CLAMP param for %s", joint_ns.c_str());
00488 }
00489 if (!this->rosNode->getParam(vp_str, vp_val)) {
00490 ROS_WARN("IOBPlugin: couldn't find a VP param for %s", joint_ns.c_str());
00491 }
00492
00493
00494 this->robotState.kp_position[i] = p_val;
00495 this->robotState.ki_position[i] = i_val;
00496 this->robotState.kd_position[i] = d_val;
00497 this->robotState.i_effort_min[i] = -i_clamp_val;
00498 this->robotState.i_effort_max[i] = i_clamp_val;
00499 this->robotState.kp_velocity[i] = vp_val;
00500 }
00501 }
00502 }
00503
00504 void IOBPlugin::DeferredLoad() {
00505
00506 this->pmq.startServiceThread();
00507
00508
00509 this->LoadPIDGainsFromParameter();
00510
00511
00512 this->pubRobotStateQueue = this->pmq.addPub<RobotState>();
00513 this->pubRobotState = this->rosNode->advertise<RobotState>(this->robot_name + "/robot_state", 100, true);
00514
00515
00516 ros::SubscribeOptions IOBCommandSo =
00517 ros::SubscribeOptions::create<JointCommand>(this->robot_name + "/joint_command", 100,
00518 boost::bind(&IOBPlugin::SetJointCommand, this, _1),
00519 ros::VoidPtr(), &this->rosQueue);
00520
00521 IOBCommandSo.transport_hints = ros::TransportHints().reliable().tcpNoDelay(true);
00522 this->subIOBCommand = this->rosNode->subscribe(IOBCommandSo);
00523
00524 {
00525 ros::AdvertiseServiceOptions IOBRefServO =
00526 ros::AdvertiseServiceOptions::create<std_srvs::Empty>
00527 (this->robot_name + "/reset_joint_reference", boost::bind(&IOBPlugin::serviceRefCallback, this, _1, _2),
00528 ros::VoidPtr(), &this->rosQueue);
00529 this->jointrefServ = this->rosNode->advertiseService(IOBRefServO);
00530 }
00531
00532 if (this->use_synchronized_command) {
00533
00534 ROS_INFO("use synchronized command");
00535
00536 ros::AdvertiseServiceOptions IOBServO =
00537 ros::AdvertiseServiceOptions::create<hrpsys_gazebo_msgs::SyncCommand>
00538 (this->robot_name + "/iob_command", boost::bind(&IOBPlugin::serviceCallback, this, _1, _2),
00539 ros::VoidPtr(), &this->srvQueue);
00540 this->controlServ = this->rosNode->advertiseService(IOBServO);
00541 #if 0
00542 ros::AdvertiseServiceOptions IOBTickServO =
00543 ros::AdvertiseServiceOptions::create<std_srvs::Empty>
00544 (this->robot_name + "/tick_synchronized_command",
00545 boost::bind(&IOBPlugin::serviceRefCallback, this, _1, _2), ros::VoidPtr(), &this->srvQueue);
00546 this->tickServ = this->rosNode->advertiseService(IOBTickServO);
00547 #endif
00548
00549 this->callbackQueeuThread_srv =
00550 boost::thread(boost::bind(&IOBPlugin::SrvQueueThread, this));
00551 }
00552
00553 this->callbackQueeuThread_msg =
00554 boost::thread(boost::bind(&IOBPlugin::RosQueueThread, this));
00555
00556 this->updateConnection =
00557 event::Events::ConnectWorldUpdateBegin(boost::bind(&IOBPlugin::UpdateStates, this));
00558 }
00559 void IOBPlugin::SetJointCommand(const JointCommand::ConstPtr &_msg) {
00560 this->SetJointCommand_impl(*_msg);
00561 }
00562 void IOBPlugin::SetJointCommand_impl(const JointCommand &_msg) {
00563
00564 boost::mutex::scoped_lock lock(this->mutex);
00565
00566 this->jointCommand.header.stamp = _msg.header.stamp;
00567
00568
00569 if (_msg.position.size() == this->jointCommand.position.size())
00570 std::copy(_msg.position.begin(), _msg.position.end(), this->jointCommand.position.begin());
00571 else
00572 ROS_DEBUG("JointCommand message contains different number of"
00573 " elements position[%ld] than expected[%ld]",
00574 _msg.position.size(), this->jointCommand.position.size());
00575
00576 if (_msg.velocity.size() == this->jointCommand.velocity.size())
00577 std::copy(_msg.velocity.begin(), _msg.velocity.end(), this->jointCommand.velocity.begin());
00578 else
00579 ROS_DEBUG("JointCommand message contains different number of"
00580 " elements velocity[%ld] than expected[%ld]",
00581 _msg.velocity.size(), this->jointCommand.velocity.size());
00582
00583 if (_msg.effort.size() == this->jointCommand.effort.size())
00584 std::copy(_msg.effort.begin(), _msg.effort.end(), this->jointCommand.effort.begin());
00585 else
00586 ROS_DEBUG("JointCommand message contains different number of"
00587 " elements effort[%ld] than expected[%ld]",
00588 _msg.effort.size(), this->jointCommand.effort.size());
00589
00590 if (!this->use_velocity_feedback) {
00591
00592 if (_msg.kp_position.size() == this->robotState.kp_position.size())
00593 std::copy(_msg.kp_position.begin(), _msg.kp_position.end(), this->robotState.kp_position.begin());
00594 else
00595 ROS_DEBUG("JointCommand message contains different number of"
00596 " elements kp_position[%ld] than expected[%ld]",
00597 _msg.kp_position.size(), this->robotState.kp_position.size());
00598
00599 if (_msg.ki_position.size() == this->robotState.ki_position.size())
00600 std::copy(_msg.ki_position.begin(), _msg.ki_position.end(), this->robotState.ki_position.begin());
00601 else
00602 ROS_DEBUG("JointCommand message contains different number of"
00603 " elements ki_position[%ld] than expected[%ld]",
00604 _msg.ki_position.size(), this->robotState.ki_position.size());
00605
00606 if (_msg.kd_position.size() == this->robotState.kd_position.size())
00607 std::copy(_msg.kd_position.begin(), _msg.kd_position.end(), this->robotState.kd_position.begin());
00608 else
00609 ROS_DEBUG("JointCommand message contains different number of"
00610 " elements kd_position[%ld] than expected[%ld]",
00611 _msg.kd_position.size(), this->robotState.kd_position.size());
00612
00613 if (_msg.kp_velocity.size() == this->robotState.kp_velocity.size())
00614 std::copy(_msg.kp_velocity.begin(), _msg.kp_velocity.end(), this->robotState.kp_velocity.begin());
00615 else
00616 ROS_DEBUG("JointCommand message contains different number of"
00617 " elements kp_velocity[%ld] than expected[%ld]",
00618 _msg.kp_velocity.size(), this->robotState.kp_velocity.size());
00619
00620 if (_msg.i_effort_min.size() == this->robotState.i_effort_min.size())
00621 std::copy(_msg.i_effort_min.begin(), _msg.i_effort_min.end(), this->robotState.i_effort_min.begin());
00622 else
00623 ROS_DEBUG("JointCommand message contains different number of"
00624 " elements i_effort_min[%ld] than expected[%ld]",
00625 _msg.i_effort_min.size(), this->robotState.i_effort_min.size());
00626
00627 if (_msg.i_effort_max.size() == this->robotState.i_effort_max.size())
00628 std::copy(_msg.i_effort_max.begin(), _msg.i_effort_max.end(), this->robotState.i_effort_max.begin());
00629 else
00630 ROS_DEBUG("JointCommand message contains different number of"
00631 " elements i_effort_max[%ld] than expected[%ld]",
00632 _msg.i_effort_max.size(), this->robotState.i_effort_max.size());
00633 } else {
00634
00635 if (_msg.kpv_position.size() == this->robotState.kpv_position.size())
00636 std::copy(_msg.kpv_position.begin(), _msg.kpv_position.end(), this->robotState.kpv_position.begin());
00637 else
00638 ROS_DEBUG("JointCommand message contains different number of"
00639 " elements kpv_position[%ld] than expected[%ld]",
00640 _msg.kpv_position.size(), this->robotState.kpv_position.size());
00641
00642 if (_msg.kpv_velocity.size() == this->robotState.kpv_velocity.size())
00643 std::copy(_msg.kpv_velocity.begin(), _msg.kpv_velocity.end(), this->robotState.kpv_velocity.begin());
00644 else
00645 ROS_DEBUG("JointCommand message contains different number of"
00646 " elements kpv_velocity[%ld] than expected[%ld]",
00647 _msg.kpv_velocity.size(), this->robotState.kpv_velocity.size());
00648 }
00649 this->jointCommand.desired_controller_period_ms =
00650 _msg.desired_controller_period_ms;
00651 }
00652 void IOBPlugin::PublishJointState() {
00653 this->publish_joint_state_counter++;
00654 if(this->publish_joint_state_step > this->publish_joint_state_counter) {
00655 return;
00656 }
00657 if(this->jointNames.size() != this->joints.size()) {
00658 ROS_ERROR("joint length miss match %ld != %ld", this->jointNames.size(), this->joints.size());
00659 return;
00660 }
00661 if(this->jointNames.size() == 0) {
00662 ROS_ERROR("joint length is zero");
00663 return;
00664 }
00665 if(!this->pubJointStateQueue || !this->pubJointState) {
00666 ROS_ERROR("no publisher %d %d", !this->pubJointStateQueue, !this->pubJointState);
00667 return;
00668 }
00669
00670 sensor_msgs::JointState jstate;
00671 jstate.header.stamp = this->robotState.header.stamp;
00672 jstate.name.resize(this->jointNames.size());
00673 jstate.position.resize(this->joints.size());
00674 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00675 jstate.name[i] = this->jointNames[i];
00676 jstate.position[i] = this->joints[i]->GetAngle(0).Radian();
00677 }
00678 this->pubJointStateQueue->push(jstate, this->pubJointState);
00679 this->publish_joint_state_counter = 0;
00680 }
00681 void IOBPlugin::UpdateStates() {
00682
00683 common::Time curTime = this->world->GetSimTime();
00684 if (curTime > this->lastControllerUpdateTime) {
00685
00686 this->GetRobotStates(curTime);
00687
00688 this->publish_count++;
00689 if(this->publish_count % this->publish_step == 0) {
00690
00691 this->pubRobotStateQueue->push(this->robotState, this->pubRobotState);
00692 if (this->publish_joint_state) this->PublishJointState();
00693 }
00694
00695 if (this->use_synchronized_command) {
00696 {
00697 boost::unique_lock<boost::mutex> lock(this->uniq_mutex);
00698
00699 return_service_cond_.notify_all();
00700
00701
00702 wait_service_cond_.wait(lock);
00703 }
00704 } else if (this->use_loose_synchronized) {
00705 ros::Time rnow;
00706 rnow.fromSec(curTime.Double());
00707 int counter = 0;
00708
00709
00710
00711 while ((rnow - this->jointCommand.header.stamp).toSec() > this->iob_period) {
00712 ros::WallDuration(0, 200000).sleep();
00713 if(counter++ > 100) {
00714 ROS_WARN_THROTTLE(5, "timeout: loose synchronization / you should check hrpsys is working");
00715 break;
00716 }
00717 }
00718
00719
00720
00721 }
00722 {
00723 boost::mutex::scoped_lock lock(this->mutex);
00724 if (this->use_velocity_feedback) {
00725
00726 this->UpdatePID_Velocity_Control((curTime - this->lastControllerUpdateTime).Double());
00727 } else {
00728
00729 this->UpdatePIDControl((curTime - this->lastControllerUpdateTime).Double());
00730 }
00731 }
00732 this->lastControllerUpdateTime = curTime;
00733 }
00734 }
00735
00736 bool IOBPlugin::serviceCallback(hrpsys_gazebo_msgs::SyncCommandRequest &req,
00737 hrpsys_gazebo_msgs::SyncCommandResponse &res)
00738 {
00739 this->SetJointCommand_impl(req.joint_command);
00740 {
00741 boost::unique_lock<boost::mutex> lock(this->uniq_mutex);
00742
00743 wait_service_cond_.notify_all();
00744
00745
00746 return_service_cond_.wait(lock);
00747 res.robot_state = this->robotState;
00748 }
00749 return true;
00750 }
00751
00752 bool IOBPlugin::serviceRefCallback(std_srvs::EmptyRequest &req,
00753 std_srvs::EmptyResponse &res)
00754 {
00755
00756 JointCommand jc;
00757 jc.position.resize(this->joints.size());
00758 jc.velocity.resize(this->joints.size());
00759 jc.effort.resize(this->joints.size());
00760
00761 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00762 jc.position[i] = this->joints[i]->GetAngle(0).Radian();
00763 jc.velocity[i] = 0;
00764 jc.effort[i] = 0;
00765 }
00766 for (unsigned i = 0; i < this->errorTerms.size(); ++i) {
00767 this->errorTerms[i].q_p = 0;
00768 this->errorTerms[i].d_q_p_dt = 0;
00769 this->errorTerms[i].k_i_q_i = 0;
00770 this->errorTerms[i].qd_p = 0;
00771 }
00772 this->SetJointCommand_impl(jc);
00773
00774 return true;
00775 }
00776
00777 void IOBPlugin::GetRobotStates(const common::Time &_curTime){
00778
00779
00780 this->robotState.header.stamp = ros::Time(_curTime.sec, _curTime.nsec);
00781
00782 boost::shared_ptr<std::vector<double > > vbuf = effortValQueue.at(this->effort_average_cnt);
00783
00784 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00785 this->robotState.position[i] = this->joints[i]->GetAngle(0).Radian();
00786 this->robotState.velocity[i] = this->joints[i]->GetVelocity(0);
00787 if (this->use_joint_effort) {
00788 physics::JointPtr j = this->joints[i];
00789 physics::JointWrench w = j->GetForceTorque(0u);
00790 {
00791 math::Vector3 a = j->GetLocalAxis(0u);
00792 vbuf->at(i) = a.Dot(w.body1Torque);
00793 this->robotState.effort[i] = 0.0;
00794
00795 }
00796 #if 0 // DEBUG
00797 {
00798 math::Vector3 a = j->GetGlobalAxis(0u);
00799 math::Vector3 m = this->joints[i]->GetChild()->GetWorldPose().rot * w.body2Torque;
00800 float ret = this->robotState.effort[i] = a.Dot(m);
00801 ROS_INFO("f[%d]->%f,%f", i, this->robotState.effort[i], ret);
00802 }
00803 #endif
00804 } else {
00805 if (this->use_velocity_feedback) {
00806 this->robotState.effort[i] = this->joints[i]->GetForce(0);
00807 }
00808 }
00809 }
00810 if (this->use_joint_effort) {
00811 for (int j = 0; j < effortValQueue.size(); j++) {
00812 boost::shared_ptr<std::vector<double > > vbuf = effortValQueue.at(j);
00813 for (int i = 0; i < this->joints.size(); i++) {
00814 this->robotState.effort[i] += vbuf->at(i);
00815 }
00816 }
00817 if (effortValQueue.size() > 0 ){
00818 for (int i = 0; i < this->joints.size(); i++) {
00819 this->robotState.effort[i] *= 1.0/effortValQueue.size();
00820 }
00821 } else {
00822 ROS_WARN("invalid force val queue size 0");
00823 }
00824 }
00825 this->effort_average_cnt = (this->effort_average_cnt+1) % this->effort_average_window_size;
00826
00827
00828 this->robotState.sensors.resize(this->forceSensorNames.size());
00829 for (unsigned int i = 0; i < this->forceSensorNames.size(); i++) {
00830 forceSensorMap::iterator it = this->forceSensors.find(this->forceSensorNames[i]);
00831 boost::shared_ptr<std::vector<boost::shared_ptr<geometry_msgs::WrenchStamped> > > forceValQueue = this->forceValQueueMap.find(this->forceSensorNames[i])->second;
00832 boost::shared_ptr<geometry_msgs::WrenchStamped> forceVal = forceValQueue->at(this->force_sensor_average_cnt);
00833 if(it != this->forceSensors.end()) {
00834 physics::JointPtr jt = it->second.joint;
00835 if (!!jt) {
00836 physics::JointWrench wrench = jt->GetForceTorque(0u);
00837 this->robotState.sensors[i].name = this->forceSensorNames[i];
00838 this->robotState.sensors[i].frame_id = it->second.frame_id;
00839 if (!!it->second.pose) {
00840
00841 math::Vector3 force_trans = it->second.pose->rot * wrench.body2Force;
00842 math::Vector3 torque_trans = it->second.pose->rot * wrench.body2Torque;
00843
00844 forceVal->wrench.force.x = force_trans.x;
00845 forceVal->wrench.force.y = force_trans.y;
00846 forceVal->wrench.force.z = force_trans.z;
00847
00848 torque_trans += it->second.pose->pos.Cross(force_trans);
00849 forceVal->wrench.torque.x = torque_trans.x;
00850 forceVal->wrench.torque.y = torque_trans.y;
00851 forceVal->wrench.torque.z = torque_trans.z;
00852 } else {
00853 forceVal->wrench.force.x = wrench.body2Force.x;
00854 forceVal->wrench.force.y = wrench.body2Force.y;
00855 forceVal->wrench.force.z = wrench.body2Force.z;
00856 forceVal->wrench.torque.x = wrench.body2Torque.x;
00857 forceVal->wrench.torque.y = wrench.body2Torque.y;
00858 forceVal->wrench.torque.z = wrench.body2Torque.z;
00859 }
00860 } else {
00861 ROS_WARN("[ForceSensorPlugin] joint not found for %s", this->forceSensorNames[i].c_str());
00862 }
00863 }
00864 this->robotState.sensors[i].force.x = 0;
00865 this->robotState.sensors[i].force.y = 0;
00866 this->robotState.sensors[i].force.z = 0;
00867 this->robotState.sensors[i].torque.x = 0;
00868 this->robotState.sensors[i].torque.y = 0;
00869 this->robotState.sensors[i].torque.z = 0;
00870 for ( int j=0; j<forceValQueue->size() ; j++ ){
00871 boost::shared_ptr<geometry_msgs::WrenchStamped> forceValBuf = forceValQueue->at(j);
00872 this->robotState.sensors[i].force.x += forceValBuf->wrench.force.x;
00873 this->robotState.sensors[i].force.y += forceValBuf->wrench.force.y;
00874 this->robotState.sensors[i].force.z += forceValBuf->wrench.force.z;
00875 this->robotState.sensors[i].torque.x += forceValBuf->wrench.torque.x;
00876 this->robotState.sensors[i].torque.y += forceValBuf->wrench.torque.y;
00877 this->robotState.sensors[i].torque.z += forceValBuf->wrench.torque.z;
00878 }
00879 if ( forceValQueue->size() > 0 ){
00880 this->robotState.sensors[i].force.x *= 1.0/forceValQueue->size();
00881 this->robotState.sensors[i].force.y *= 1.0/forceValQueue->size();
00882 this->robotState.sensors[i].force.z *= 1.0/forceValQueue->size();
00883 this->robotState.sensors[i].torque.x *= 1.0/forceValQueue->size();
00884 this->robotState.sensors[i].torque.y *= 1.0/forceValQueue->size();
00885 this->robotState.sensors[i].torque.z *= 1.0/forceValQueue->size();
00886 } else {
00887 ROS_WARN("invalid force val queue size 0");
00888 }
00889 }
00890 this->force_sensor_average_cnt = (this->force_sensor_average_cnt+1) % this->force_sensor_average_window_size;
00891
00892
00893 this->robotState.Imus.resize(this->imuSensorNames.size());
00894 for (unsigned int i = 0; i < this->imuSensorNames.size(); i++) {
00895 imuSensorMap::iterator it = this->imuSensors.find(this->imuSensorNames[i]);
00896 ImuSensorPtr sp = it->second.sensor;
00897 if(!!sp) {
00898 this->robotState.Imus[i].name = this->imuSensorNames[i];
00899 this->robotState.Imus[i].frame_id = it->second.frame_id;
00900 math::Vector3 wLocal = sp->GetAngularVelocity();
00901 math::Vector3 accel = sp->GetLinearAcceleration();
00902 math::Quaternion imuRot = sp->GetOrientation();
00903 this->robotState.Imus[i].angular_velocity.x = wLocal.x;
00904 this->robotState.Imus[i].angular_velocity.y = wLocal.y;
00905 this->robotState.Imus[i].angular_velocity.z = wLocal.z;
00906 this->robotState.Imus[i].linear_acceleration.x = accel.x;
00907 this->robotState.Imus[i].linear_acceleration.y = accel.y;
00908 this->robotState.Imus[i].linear_acceleration.z = accel.z;
00909 this->robotState.Imus[i].orientation.x = imuRot.x;
00910 this->robotState.Imus[i].orientation.y = imuRot.y;
00911 this->robotState.Imus[i].orientation.z = imuRot.z;
00912 this->robotState.Imus[i].orientation.w = imuRot.w;
00913 }
00914 }
00915 {
00916 boost::mutex::scoped_lock lock(this->mutex);
00917 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00918 this->robotState.ref_position[i] = this->jointCommand.position[i];
00919 this->robotState.ref_velocity[i] = this->jointCommand.velocity[i];
00920 }
00921 }
00922 }
00923
00924 void IOBPlugin::UpdatePID_Velocity_Control(double _dt) {
00925
00927 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00928
00929
00930 double positionTarget = math::clamp(this->jointCommand.position[i],
00931 static_cast<double>(this->joints[i]->GetLowStop(0).Radian()),
00932 static_cast<double>(this->joints[i]->GetHighStop(0).Radian()));
00933
00934 double q_p = positionTarget - this->robotState.position[i];
00935
00936 if (!math::equal(_dt, 0.0))
00937 this->errorTerms[i].d_q_p_dt = (q_p - this->errorTerms[i].q_p) / _dt;
00938
00939 this->errorTerms[i].q_p = q_p;
00940
00941 this->errorTerms[i].qd_p =
00942 this->jointCommand.velocity[i] - this->robotState.velocity[i];
00943
00944 double max_vel = this->joints[i]->GetVelocityLimit(0);
00945 double j_velocity =
00946 this->jointCommand.velocity[i] +
00947 static_cast<double>(this->robotState.kpv_position[i]) * this->errorTerms[i].q_p +
00948 static_cast<double>(this->robotState.kpv_velocity[i]) * this->errorTerms[i].qd_p;
00949
00950
00951 this->joints[i]->SetMaxForce(0, this->joints[i]->GetEffortLimit(0));
00952
00953 j_velocity = math::clamp(j_velocity, -max_vel, max_vel);
00954 #if 0
00955 ROS_INFO("%d %f / %f %f %f %f",
00956 i, this->joints[i]->GetMaxForce(0),
00957 j_velocity, positionTarget, robotState.position[i],
00958 this->robotState.kpv_position[i]);
00959 #endif
00960
00961 this->joints[i]->SetVelocity(0, j_velocity);
00962 }
00963 }
00964
00965 void IOBPlugin::UpdatePIDControl(double _dt) {
00966
00968 for (unsigned int i = 0; i < this->joints.size(); ++i) {
00969
00970 double positionTarget = math::clamp(this->jointCommand.position[i],
00971 static_cast<double>(this->joints[i]->GetLowStop(0).Radian()),
00972 static_cast<double>(this->joints[i]->GetHighStop(0).Radian()));
00973
00974 double q_p = positionTarget - this->robotState.position[i];
00975
00976 if (!math::equal(_dt, 0.0))
00977 this->errorTerms[i].d_q_p_dt = (q_p - this->errorTerms[i].q_p) / _dt;
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 double jointDampingCoef = math::clamp(
00990 static_cast<double>(this->robotState.kp_velocity[i]),
00991 this->jointDampingModel[i], this->jointDampingMax[i]);
00992
00993
00994 if (!math::equal(this->lastJointCFMDamping[i], jointDampingCoef))
00995 {
00996 this->joints[i]->SetDamping(0, jointDampingCoef);
00997 this->lastJointCFMDamping[i] = jointDampingCoef;
00998 }
00999
01000
01001
01002
01003
01004
01005 double kpVelocityDampingEffort = 0;
01006 double kpVelocityDampingCoef =
01007 jointDampingCoef - this->jointDampingModel[i];
01008 if (kpVelocityDampingCoef > 0.0)
01009 kpVelocityDampingEffort =
01010 kpVelocityDampingCoef * this->robotState.velocity[i];
01011
01012
01013 this->errorTerms[i].q_p = q_p;
01014
01015 this->errorTerms[i].qd_p =
01016 this->jointCommand.velocity[i] - this->robotState.velocity[i];
01017
01018 this->errorTerms[i].k_i_q_i = math::clamp(this->errorTerms[i].k_i_q_i +
01019 _dt *
01020 static_cast<double>(this->robotState.ki_position[i])
01021 * this->errorTerms[i].q_p,
01022 static_cast<double>(this->robotState.i_effort_min[i]),
01023 static_cast<double>(this->robotState.i_effort_max[i]));
01024
01025
01026 double forceUnclamped =
01027 static_cast<double>(this->robotState.kp_position[i]) * this->errorTerms[i].q_p +
01028 this->errorTerms[i].k_i_q_i +
01029 static_cast<double>(this->robotState.kd_position[i]) * this->errorTerms[i].d_q_p_dt +
01030 static_cast<double>(this->robotState.kp_velocity[i]) * this->errorTerms[i].qd_p +
01031 this->jointCommand.effort[i];
01032
01033
01034 double forceClamped = math::clamp(forceUnclamped, -this->effortLimit[i], this->effortLimit[i]);
01035
01036
01037
01038
01039
01040 forceClamped = math::clamp(forceUnclamped,
01041 -this->effortLimit[i] + kpVelocityDampingEffort,
01042 this->effortLimit[i] + kpVelocityDampingEffort);
01043
01044
01045 if (!math::equal(forceClamped, forceUnclamped) &&
01046 !math::equal(static_cast<double>(this->robotState.ki_position[i]), 0.0)) {
01047
01048
01049 this->errorTerms[i].k_i_q_i = math::clamp(this->errorTerms[i].k_i_q_i + (forceClamped - forceUnclamped),
01050 static_cast<double>(this->robotState.i_effort_min[i]),
01051 static_cast<double>(this->robotState.i_effort_max[i]));
01052 }
01053
01054 forceClamped = math::clamp(forceUnclamped, -this->effortLimit[i], this->effortLimit[i]);
01055
01056
01057 this->joints[i]->SetForce(0, forceClamped);
01058
01059
01060 this->robotState.effort[i] = forceClamped;
01061 }
01062 }
01063
01064 void IOBPlugin::RosQueueThread() {
01065 static const double timeout = 0.01;
01066
01067 while (this->rosNode->ok()) {
01068 ros::spinOnce();
01069 this->rosQueue.callAvailable(ros::WallDuration(timeout));
01070 }
01071 }
01072 void IOBPlugin::SrvQueueThread() {
01073 while (this->rosNode->ok()) {
01074 this->srvQueue.callAvailable();
01075 }
01076 }
01077 }