Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00085 string modelName = _sdf->GetParent()->Get<string>("name");
00086
00087
00088 world = _parent->GetWorld();
00089
00090
00091 parent_model_ = _parent;
00092
00093
00094 if (!parent_model_)
00095 ROS_ERROR("Unable to get parent model");
00096
00097
00098
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
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
00129 self_test_.reset(new shadow_robot::SrSelfTest(true, robotNamespace));
00130
00131
00132 ros_spinner_thread_ = boost::thread(boost::bind(&GazeboRosControllerManager::ControllerManagerROSThread, this));
00133
00134 rosnode_->param("gazebo/start_robot_calibrated", fake_calibration_, true);
00135
00136
00137 ReadPr2Xml();
00138
00139
00140 if (state_ != NULL)
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
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
00156 ros::Duration gazebo_period(parent_model_->GetWorld()->GetPhysicsEngine()->GetMaxStepSize());
00157
00158
00159 if (_sdf->HasElement("controlPeriod"))
00160 {
00161 control_period_ = ros::Duration(_sdf->Get<double>("controlPeriod"));
00162
00163
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
00184 controller_manager_callback_queue_thread_ =
00185 boost::thread(boost::bind(&GazeboRosControllerManager::ControllerManagerQueueThread, this));
00186 #endif
00187
00188 }
00189
00190
00191
00192 void GazeboRosControllerManager::ResetChild()
00193 {
00194
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
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
00219 if (sim_period >= control_period_)
00220 {
00221
00222 last_update_sim_time_ros_ = sim_time_ros;
00223
00224
00225
00226
00227
00228
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
00243
00244 fake_state_->current_time_ = ros::Time(world->GetSimTime().Double());
00245 cm_->update(sim_time_ros, sim_period);
00246 }
00247
00248
00249
00250
00251
00252
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
00260
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
00283
00284
00285 double effort_command = effort;
00286
00287
00288
00289
00290
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
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
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
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
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
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
00395 GZ_REGISTER_MODEL_PLUGIN(GazeboRosControllerManager)
00396 }