IOBPlugin.cpp
Go to the documentation of this file.
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   // initialize ros
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   // ros node
00075   this->rosNode = new ros::NodeHandle("");
00076 
00077   this->model = _parent;
00078   this->world = this->model->GetWorld();
00079 
00080   // save sdf
00081   this->sdf = _sdf;
00082 
00083   // initialize update time
00084   this->lastControllerUpdateTime = this->world->GetSimTime();
00085 
00086   // creating joints from ros param
00087   if (this->rosNode->hasParam(this->controller_name)) {
00088     { // read synchronized_command from rosparam
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     { // read synchronized_command from rosparam
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     { // read velocity_feedback from rosparam
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     { // read use_joint_effort from rosparam
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     { // read publish_joint_state from rosparam
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       // joint name
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       // Force sensor setting
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           // setup force sensor publishers
00243           boost::shared_ptr<std::vector<boost::shared_ptr<geometry_msgs::WrenchStamped> > > forceValQueue(new std::vector<boost::shared_ptr<geometry_msgs::WrenchStamped> >);
00244           // forceValQueue->resize(this->force_sensor_average_window_size);
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       // IMU sensor setting
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               // Get imu sensors
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   // get pointers to joints from gazebo
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   // get effort limits from gazebo
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     // initialize PID states: error terms
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     // TODO: hardcoded for now
00338 #define JOINT_DAMPING_LOWER_BOUND 0.1
00339     for (unsigned int i = 0; i < this->jointNames.size(); ++i)
00340     {
00341       // set max allowable damping coefficient to
00342       //  max effort allowed / max velocity allowed
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     // We are not sending names due to the fact that there is an enum
00373     // joint indices in ...
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     // effort average
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     // for reference
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       // for effort feedback
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       // for velocity feedback
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       // for effort feedback
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       // for velocity feedback
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   // ros callback queue for processing subscription
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       // store these directly on altasState, more efficient for pub later
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   // pull down controller parameters
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       // this is so ugly
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       // store these directly on altasState, more efficient for pub later
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   // publish multi queue
00506   this->pmq.startServiceThread();
00507 
00508   // pull down controller parameters
00509   this->LoadPIDGainsFromParameter();
00510 
00511   // ROS Controller API
00512   this->pubRobotStateQueue = this->pmq.addPub<RobotState>();
00513   this->pubRobotState = this->rosNode->advertise<RobotState>(this->robot_name + "/robot_state", 100, true);
00514 
00515   // ros topic subscribtions
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   // Enable TCP_NODELAY because TCP causes bursty communication with high jitter,
00521   IOBCommandSo.transport_hints = ros::TransportHints().reliable().tcpNoDelay(true);
00522   this->subIOBCommand = this->rosNode->subscribe(IOBCommandSo);
00523 
00524   { // reset_joint_reference service
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     // ros service
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     // ros callback queue for processing subscription
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   // Update Joint Command
00564   boost::mutex::scoped_lock lock(this->mutex);
00565 
00566   this->jointCommand.header.stamp = _msg.header.stamp;
00567 
00568   // for jointCommand, only position, velocity and efforts are used.
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     // the rest are stored in robotState for publication
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     // use velocity feedback
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   // publish joint_state
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   //ROS_DEBUG("update");
00683   common::Time curTime = this->world->GetSimTime();
00684   if (curTime > this->lastControllerUpdateTime) {
00685     // gather robot state data
00686     this->GetRobotStates(curTime);
00687 
00688     this->publish_count++;
00689     if(this->publish_count % this->publish_step == 0) {
00690       // publish robot states
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         //ROS_DEBUG("return notify");
00699         return_service_cond_.notify_all();
00700 
00701         //ROS_DEBUG("service wait");
00702         wait_service_cond_.wait(lock);
00703       }
00704     } else if (this->use_loose_synchronized) { // loose synchronization
00705       ros::Time rnow;
00706       rnow.fromSec(curTime.Double());
00707       int counter = 0;
00708       //if ((rnow - this->jointCommand.header.stamp).toSec() > 0.002) {
00709       //  ROS_WARN("%f update fail %f", rnow.toSec(), this->jointCommand.header.stamp.toSec());
00710       //}
00711       while ((rnow - this->jointCommand.header.stamp).toSec() > this->iob_period) {
00712         ros::WallDuration(0, 200000).sleep(); // 0.2 ms
00713         if(counter++ > 100) {
00714           ROS_WARN_THROTTLE(5, "timeout: loose synchronization / you should check hrpsys is working");
00715           break;
00716         }
00717       }
00718       //if(counter > 0) {
00719       //  ROS_WARN("%f recover %f", rnow.toSec(), this->jointCommand.header.stamp.toSec());
00720       //}
00721     }
00722     {
00723       boost::mutex::scoped_lock lock(this->mutex);
00724       if (this->use_velocity_feedback) {
00725         // velocity control
00726         this->UpdatePID_Velocity_Control((curTime - this->lastControllerUpdateTime).Double());
00727       } else {
00728         // effort control
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     //ROS_DEBUG("service notify");
00743     wait_service_cond_.notify_all();
00744 
00745     //ROS_DEBUG("return wait");
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   // set reference to actual
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   // populate robotState from robot
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   // joint states
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         //this->robotState.effort[i] = a.Dot(w.body1Torque);
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   // enqueue force sensor values
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           // convert force
00841           math::Vector3 force_trans = it->second.pose->rot * wrench.body2Force;
00842           math::Vector3 torque_trans = it->second.pose->rot * wrench.body2Torque;
00843           // rotate force
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           // rotate torque + additional torque
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   // imu sensors
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     // truncate joint position within range of motion
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     // update max force
00951     this->joints[i]->SetMaxForce(0, this->joints[i]->GetEffortLimit(0));
00952     // clamp max velocity
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     // apply velocity to joint
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     // truncate joint position within range of motion
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     // Take advantage of cfm damping by passing kp_velocity through
00981     // to intrinsic joint damping coefficient.  Simulating
00982     // infinite bandwidth kp_velocity.
00983     //
00984     // kp_velocity is truncated within (jointDampingModel, jointDampingMax).
00985     //
00986     // To take advantage of utilizing full range of cfm damping dynamically
00987     // for controlling the robot, set model damping (jointDmapingModel)
00988     // to jointDampingMin first.
00989     double jointDampingCoef = math::clamp(
00990       static_cast<double>(this->robotState.kp_velocity[i]),
00991       this->jointDampingModel[i], this->jointDampingMax[i]);
00992 
00993     // skip set joint damping if value is not changing
00994     if (!math::equal(this->lastJointCFMDamping[i], jointDampingCoef))
00995     {
00996       this->joints[i]->SetDamping(0, jointDampingCoef);
00997       this->lastJointCFMDamping[i] = jointDampingCoef;
00998     }
00999 
01000     // approximate effort generated by a non-zero joint velocity state
01001     // this is the approximate force of the infinite bandwidth
01002     // kp_velocity term, we'll use this to bound additional forces later.
01003     // Force generated by cfm damping from damping coefficient smaller than
01004     // jointDampingModel is generated for free.
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     // use gain params to compute force cmd
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     // keep unclamped force for integral tie-back calculation
01034     double forceClamped = math::clamp(forceUnclamped, -this->effortLimit[i], this->effortLimit[i]);
01035 
01036     // clamp force after integral tie-back
01037     // shift by kpVelocityDampingEffort to prevent controller from
01038     // exerting too much force from use of kp_velocity --> cfm damping
01039     // pass through.
01040     forceClamped = math::clamp(forceUnclamped,
01041                                -this->effortLimit[i] + kpVelocityDampingEffort,
01042                                this->effortLimit[i] + kpVelocityDampingEffort);
01043 
01044     // integral tie-back during control saturation if using integral gain
01045     if (!math::equal(forceClamped, forceUnclamped) &&
01046         !math::equal(static_cast<double>(this->robotState.ki_position[i]), 0.0)) {
01047       // lock integral term to provide continuous control as system moves
01048       // out of staturation
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     // clamp force after integral tie-back
01054     forceClamped = math::clamp(forceUnclamped, -this->effortLimit[i], this->effortLimit[i]);
01055 
01056     // apply force to joint
01057     this->joints[i]->SetForce(0, forceClamped);
01058 
01059     // fill in jointState efforts
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 }


hrpsys_gazebo_general
Author(s): Yohei Kakiuchi , Kei Okada , Masaki Murooka
autogenerated on Thu Jun 6 2019 20:56:53