gazebo_ros_controller_manager.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <sr_gazebo_plugins/gazebo_ros_controller_manager.h>
00031 #include <fstream>
00032 #include <iostream>
00033 #include <math.h>
00034 #include <unistd.h>
00035 #include <set>
00036 
00037 #include <gazebo/physics/World.hh>
00038 #include <gazebo/physics/HingeJoint.hh>
00039 #include <gazebo/sensors/Sensor.hh>
00040 #include <gazebo/common/Exception.hh>
00041 #include <gazebo/physics/PhysicsTypes.hh>
00042 #include <gazebo/physics/Base.hh>
00043 
00044 #include <sdf/sdf.hh>
00045 #include <sdf/Param.hh>
00046 
00047 #include <angles/angles.h>
00048 #include <urdf/model.h>
00049 
00050 #include <sr_hardware_interface/sr_actuator.hpp>
00051 
00052 using namespace ros_ethercat_model;
00053 using namespace std;
00054 using boost::ptr_unordered_map;
00055 
00056 namespace gazebo
00057 {
00058 
00059 GazeboRosControllerManager::GazeboRosControllerManager()
00060   : state_(NULL), cm_(NULL), fake_state_(NULL), rosnode_(NULL), stop_(false)
00061 {
00062 }
00063 
00064 GazeboRosControllerManager::~GazeboRosControllerManager()
00065 {
00066   ROS_DEBUG("Calling FiniChild in GazeboRosControllerManager");
00067 
00068 #ifdef USE_CBQ
00069   controller_manager_queue_.clear();
00070   controller_manager_queue_.disable();
00071   controller_manager_callback_queue_thread_.join();
00072 #endif
00073   stop_ = true;
00074   ros_spinner_thread_.join();
00075   ROS_DEBUG("spinner terminated");
00076   self_test_.reset();
00077   delete cm_;
00078   delete rosnode_;
00079   delete state_;
00080 }
00081 
00082 void GazeboRosControllerManager::Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
00083 {
00084   // Get then name of the parent model
00085   string modelName = _sdf->GetParent()->Get<string>("name");
00086 
00087   // Get the world name.
00088   world = _parent->GetWorld();
00089 
00090   // Get a pointer to the model
00091   parent_model_ = _parent;
00092 
00093   // Error message if the model couldn't be found
00094   if (!parent_model_)
00095     ROS_ERROR("Unable to get parent model");
00096 
00097   // Listen to the update event. This event is broadcast every
00098   // simulation iteration.
00099   updateConnection = event::Events::ConnectWorldUpdateBegin(boost::bind(&GazeboRosControllerManager::UpdateChild, this));
00100   ROS_DEBUG_STREAM("plugin model name: " << modelName);
00101 
00102   if (getenv("CHECK_SPEEDUP"))
00103   {
00104     wall_start_ = world->GetRealTime().Double();
00105     sim_start_ = world->GetSimTime().Double();
00106   }
00107 
00108   // get parameter name
00109   robotNamespace = "";
00110   if (_sdf->HasElement("robotNamespace"))
00111     robotNamespace = _sdf->GetElement("robotNamespace")->Get<string>();
00112 
00113   robotParam = "robot_description";
00114   if (_sdf->HasElement("robotParam"))
00115     robotParam = _sdf->GetElement("robotParam")->Get<string>();
00116 
00117   robotParam = robotNamespace + "/" + robotParam;
00118 
00119   if (!ros::isInitialized())
00120   {
00121     int argc = 0;
00122     char** argv = NULL;
00123     ros::init(argc, argv, "gazebo", ros::init_options::NoSigintHandler | ros::init_options::AnonymousName);
00124   }
00125   rosnode_ = new ros::NodeHandle(robotNamespace);
00126   ROS_INFO("starting gazebo_ros_controller_manager plugin in ns: %s", robotNamespace.c_str());
00127 
00128   // Use the robots namespace, not gazebos
00129   self_test_.reset(new shadow_robot::SrSelfTest(true, robotNamespace));
00130 
00131   // ros_ethercat calls ros::spin(), we'll thread out one spinner here to mimic that
00132   ros_spinner_thread_ = boost::thread(boost::bind(&GazeboRosControllerManager::ControllerManagerROSThread, this));
00133 
00134   rosnode_->param("gazebo/start_robot_calibrated", fake_calibration_, true);
00135 
00136   // setup the robot state
00137   ReadPr2Xml();
00138 
00139   // The gazebo joints and mechanism joints should match up.
00140   if (state_ != NULL) // could be NULL if ReadPr2Xml is unsuccessful
00141   {
00142     for (ptr_unordered_map<string, JointState>::iterator it = state_->model_.joint_states_.begin();
00143          it != state_->model_.joint_states_.end();
00144          ++it)
00145     {
00146       // fill the gazebo joints pointer vector
00147       physics::JointPtr joint = parent_model_->GetJoint(it->first);
00148       if (joint)
00149         joints_.push_back(joint);
00150       else
00151         ROS_ERROR_STREAM("A joint named " << it->first << " is not part of Mechanism Controlled joints");
00152     }
00153   }
00154 
00155   // Get the Gazebo simulation period
00156   ros::Duration gazebo_period(parent_model_->GetWorld()->GetPhysicsEngine()->GetMaxStepSize());
00157 
00158   // Decide the plugin control period
00159   if (_sdf->HasElement("controlPeriod"))
00160   {
00161     control_period_ = ros::Duration(_sdf->Get<double>("controlPeriod"));
00162 
00163     // Check the period against the simulation period
00164     if (control_period_ < gazebo_period)
00165     {
00166       ROS_DEBUG_STREAM("Desired controller update period (" << control_period_
00167                        << " s) is faster than the gazebo simulation period (" << gazebo_period << " s).");
00168     }
00169     else if (control_period_ > gazebo_period)
00170     {
00171       ROS_DEBUG_STREAM("Desired controller update period (" << control_period_
00172                        << " s) is slower than the gazebo simulation period (" << gazebo_period << " s).");
00173     }
00174   }
00175   else
00176   {
00177     control_period_ = gazebo_period;
00178     ROS_DEBUG_STREAM("Control period not found in URDF/SDF, defaulting to Gazebo period of "
00179                      << control_period_);
00180   }
00181 
00182 #ifdef USE_CBQ
00183   // start custom queue for controller manager
00184   controller_manager_callback_queue_thread_ =
00185     boost::thread(boost::bind(&GazeboRosControllerManager::ControllerManagerQueueThread, this));
00186 #endif
00187 
00188 }
00189 
00190 // Called on world reset
00191 
00192 void GazeboRosControllerManager::ResetChild()
00193 {
00194   // Reset timing variables to not pass negative update periods to controllers on world reset
00195   last_update_sim_time_ros_ = ros::Time();
00196   last_write_sim_time_ros_ = ros::Time();
00197 }
00198 
00199 void GazeboRosControllerManager::UpdateChild()
00200 {
00201   if (world->IsPaused() || !fake_state_ || !cm_)
00202     return;
00203 
00204   // Get the simulation time and period
00205   common::Time gz_time_now = parent_model_->GetWorld()->GetSimTime();
00206   ros::Time sim_time_ros(gz_time_now.sec, gz_time_now.nsec);
00207   ros::Duration sim_period = sim_time_ros - last_update_sim_time_ros_;
00208   if (getenv("CHECK_SPEEDUP"))
00209   {
00210     double wall_elapsed = world->GetRealTime().Double() - wall_start_;
00211     double sim_elapsed = world->GetSimTime().Double() - sim_start_;
00212     ROS_DEBUG_STREAM(" real time: " << wall_elapsed
00213                      << "  sim time: " << sim_elapsed
00214                      << "  speed up: " << sim_elapsed / wall_elapsed);
00215   }
00216   ROS_ASSERT(joints_.size() == fake_state_->joint_states_.size());
00217 
00218   // Check if we should update the controllers
00219   if (sim_period >= control_period_)
00220   {
00221     // Store this simulation time
00222     last_update_sim_time_ros_ = sim_time_ros;
00223 
00224     //--------------------------------------------------
00225     //  Pushes out simulation state
00226     //--------------------------------------------------
00227 
00228     // Copies the state from the gazebo joints into the mechanism joints.
00229     for (size_t i = 0; i < joints_.size(); ++i)
00230     {
00231       JointState *fst = fake_state_->getJointState(joints_[i]->GetName());
00232 
00233       if (joints_[i]->HasType(physics::Base::HINGE_JOINT))
00234         fst->position_ += angles::shortest_angular_distance(fst->position_, joints_[i]->GetAngle(0).Radian());
00235       else if (joints_[i]->HasType(physics::Base::SLIDER_JOINT))
00236         fst->position_ = joints_[i]->GetAngle(0).Radian();
00237 
00238       fst->velocity_ = joints_[i]->GetVelocity(0);
00239     }
00240 
00241     //--------------------------------------------------
00242     //  Runs Mechanism Control
00243     //--------------------------------------------------
00244     fake_state_->current_time_ = ros::Time(world->GetSimTime().Double());
00245     cm_->update(sim_time_ros, sim_period);
00246   }
00247 
00248   //--------------------------------------------------
00249   //  Takes in actuation commands
00250   //--------------------------------------------------
00251 
00252   // Copies the commands from the mechanism joints into the gazebo joints.
00253   for (size_t i = 0; i < joints_.size(); ++i)
00254   {
00255     string joint_name = joints_[i]->GetName();
00256 
00257     JointState *fst = fake_state_->getJointState(joint_name);
00258 
00259     // joints 1 and 2 of fingers ff, mf, rf, lf share an actuator
00260     // at this moment only commanded_effort_ in joint 2 is up to date
00261     double effort = fst->commanded_effort_;
00262 
00263     if(joint_name.size() > 3)
00264     {
00265       if (joint_name[joint_name.size() - 1] == '2' && (joint_name[joint_name.size() -4] == 'F' ||
00266                                                        joint_name[joint_name.size() -4] == 'M' ||
00267                                                        joint_name[joint_name.size() -4] == 'R' ||
00268                                                        joint_name[joint_name.size() -4] == 'L'))
00269       {
00270         joint_name[joint_name.size() - 1] = '1';
00271 
00272         JointState *fst1 = fake_state_->getJointState(joint_name);
00273         effort = fst1->commanded_effort_;
00274       }
00275     }
00276 
00277     double damping_coef = 0;
00278     if (fst->joint_->dynamics)
00279       damping_coef = fst->joint_->dynamics->damping;
00280     
00281     double current_velocity = joints_[i]->GetVelocity(0);
00282     // using implicit spring damper from gazebo instead of explicit.
00283     //double damping_force = damping_coef * current_velocity;
00284     //double effort_command = effort - damping_force;
00285     double effort_command = effort;
00286     //enforce limits (are these limites enforced in gazebo ?)
00287     //if (fst->joint_->limits)
00288     //{
00289       //double effort_limit= fst->joint_->limits->effort;
00290       //effort_command=std::min(std::max(effort_command, -effort_limit), effort_limit);
00291     //}
00292     joints_[i]->SetForce(0, effort_command);
00293   }
00294   last_write_sim_time_ros_ = sim_time_ros;
00295 }
00296 
00297 void GazeboRosControllerManager::ReadPr2Xml()
00298 {
00299 
00300   string urdf_param_name;
00301   string urdf_string;
00302   // search and wait for robot_description on param server
00303   while (urdf_string.empty())
00304   {
00305     ROS_DEBUG_STREAM("gazebo controller manager plugin is waiting for urdf: " << robotParam << " on the param server");
00306     if (rosnode_->searchParam(robotParam, urdf_param_name))
00307     {
00308       rosnode_->getParam(urdf_param_name, urdf_string);
00309       ROS_DEBUG_STREAM("found upstream");
00310     }
00311     else
00312     {
00313       rosnode_->getParam(robotParam, urdf_string);
00314       ROS_DEBUG_STREAM("found in node namespace");
00315     }
00316     ROS_DEBUG_STREAM(robotParam << "\n------\n" << urdf_param_name << "\n------\n" << urdf_string);
00317     usleep(100000);
00318   }
00319   ROS_DEBUG_STREAM("gazebo controller manager got pr2.xml from param server, parsing it...");
00320 
00321   // initialize TiXmlDocument doc with a string
00322   TiXmlDocument doc;
00323   if (!doc.Parse(urdf_string.c_str()) && doc.Error())
00324   {
00325     ROS_ERROR_STREAM("Could not load the gazebo controller manager plugin's configuration file: " << urdf_string);
00326   }
00327   else
00328   {
00329     // Pulls out the list of actuators used in the robot configuration.
00330 
00331     struct GetActuators : public TiXmlVisitor
00332     {
00333       set<string> actuators;
00334 
00335       virtual bool VisitEnter(const TiXmlElement &elt, const TiXmlAttribute *)
00336       {
00337         if (elt.ValueStr() == string("actuator") && elt.Attribute("name"))
00338           actuators.insert(elt.Attribute("name"));
00339         else if (elt.ValueStr() == string("rightActuator") && elt.Attribute("name"))
00340           actuators.insert(elt.Attribute("name"));
00341         else if (elt.ValueStr() == string("leftActuator") && elt.Attribute("name"))
00342           actuators.insert(elt.Attribute("name"));
00343         return true;
00344       }
00345     } get_actuators;
00346     doc.RootElement()->Accept(&get_actuators);
00347 
00348     state_ = new RosEthercat(*rosnode_, "", true, doc.RootElement());
00349     fake_state_ = &state_->model_;
00350 
00351     // load a controller manager
00352     cm_ = new controller_manager::ControllerManager(state_, *rosnode_);
00353 
00354     fake_state_->current_time_ = ros::Time(world->GetSimTime().Double());
00355 
00356     for (ptr_unordered_map<string, JointState>::iterator jit = state_->model_.joint_states_.begin();
00357          jit != state_->model_.joint_states_.end();
00358          ++jit)
00359     {
00360       jit->second->calibrated_ = fake_calibration_;
00361     }
00362   }
00363 
00364 }
00365 
00366 #ifdef USE_CBQ
00367 
00368 // custom callback queue
00369 
00370 void GazeboRosControllerManager::ControllerManagerQueueThread()
00371 {
00372   ROS_INFO_STREAM("Callback thread id=" << boost::this_thread::get_id());
00373 
00374   static const double timeout = 0.01;
00375 
00376   while (rosnode_->ok())
00377   {
00378     controller_manager_queue_.callAvailable(ros::WallDuration(timeout));
00379   }
00380 }
00381 #endif
00382 
00383 void GazeboRosControllerManager::ControllerManagerROSThread()
00384 {
00385   ROS_INFO_STREAM("Callback thread id=" << boost::this_thread::get_id());
00386 
00387   while (rosnode_->ok() && !stop_)
00388   {
00389     self_test_->checkTest();
00390     usleep(1000);
00391     ros::spinOnce();
00392   }
00393 }
00394 // Register this plugin with the simulator
00395 GZ_REGISTER_MODEL_PLUGIN(GazeboRosControllerManager)
00396 } // namespace gazebo


sr_gazebo_plugins
Author(s): adapted by Ugo(software@shadowrobot.com), Sachin Chitta, Stu Glaser, John Hsu
autogenerated on Sun Aug 16 2015 13:59:08