15 #include <ignition/gazebo/components/Joint.hh>
16 #include <ignition/gazebo/components/JointType.hh>
17 #include <ignition/gazebo/components/Name.hh>
18 #include <ignition/gazebo/components/ParentEntity.hh>
19 #include <ignition/gazebo/components/World.hh>
20 #include <ignition/gazebo/Model.hh>
22 #include <ignition/plugin/Register.hh>
51 const std::string& robot_description
66 std::string
getURDF(std::string param_name)
const;
78 const ignition::gazebo::Entity & _entity,
79 ignition::gazebo::EntityComponentManager & _ecm)
const;
96 std::shared_ptr<controller_manager::ControllerManager>
107 ignition::gazebo::EntityComponentManager *
ecm_{
nullptr};
120 std::map<std::string, ignition::gazebo::Entity>
122 const ignition::gazebo::Entity & _entity,
123 ignition::gazebo::EntityComponentManager & _ecm)
const
125 std::map<std::string, ignition::gazebo::Entity> output;
127 std::vector<std::string> enabledJoints;
130 auto jointEntities = _ecm.ChildrenByComponents(_entity, ignition::gazebo::components::Joint());
133 for (
const auto & jointEntity : jointEntities) {
134 const auto jointName = _ecm.Component<ignition::gazebo::components::Name>(
135 jointEntity)->Data();
139 const auto * jointType = _ecm.Component<ignition::gazebo::components::JointType>(jointEntity);
140 switch (jointType->Data()) {
141 case sdf::JointType::PRISMATIC:
142 case sdf::JointType::REVOLUTE:
143 case sdf::JointType::CONTINUOUS:
144 case sdf::JointType::GEARBOX:
149 case sdf::JointType::FIXED:
152 "[Ignition ROS Control] Fixed joint [%s] (Entity=%lu)] is skipped",
153 jointName.c_str(), jointEntity);
156 case sdf::JointType::REVOLUTE2:
157 case sdf::JointType::SCREW:
158 case sdf::JointType::BALL:
159 case sdf::JointType::UNIVERSAL:
162 "[Ignition ROS Control] Joint [%s] (Entity=%lu)] is of unsupported type."
163 " Only joints with a single axis are supported.",
164 jointName.c_str(), jointEntity);
170 "[Ignition ROS Control] Joint [%s] (Entity=%lu)] is of unknown type",
171 jointName.c_str(), jointEntity);
175 output[jointName] = jointEntity;
184 std::string urdf_string;
187 while (urdf_string.empty())
189 std::string search_param_name;
192 ROS_INFO_ONCE(
"[Ignition ROS Control] ign_ros_control_plugin is waiting for model"
193 " URDF in parameter [%s] on the ROS param server.", search_param_name.c_str());
199 ROS_INFO_ONCE(
"[Ignition ROS Control] ign_ros_control_plugin is waiting for model"
205 std::this_thread::sleep_for(std::chrono::microseconds(100000));
207 ROS_INFO_STREAM(
"[Ignition ROS Control] Recieved urdf from param server, parsing...");
232 const ignition::gazebo::Entity & _entity,
233 const std::shared_ptr<const sdf::Element> & _sdf,
234 ignition::gazebo::EntityComponentManager & _ecm,
235 ignition::gazebo::EventManager &)
238 std::string robot_namespace, robot_description, robot_hw_sim_type_str;
240 if(_sdf->HasElement(
"robotNamespace"))
242 robot_namespace = _sdf->Get<std::string>(
"robotNamespace");
246 robot_namespace =
"";
249 if (_sdf->HasElement(
"robotParam"))
251 robot_description = _sdf->Get<std::string>(
"robotParam");
255 robot_description =
"robot_description";
258 if(_sdf->HasElement(
"robotSimType"))
260 robot_hw_sim_type_str = _sdf->Get<std::string>(
"robotSimType");
264 robot_hw_sim_type_str =
"ign_ros_control/IgnitionSystem";
265 ROS_DEBUG_STREAM(
"[Ignition ROS Control] Using default plugin for RobotHWSim (none specified in URDF/SDF)\""<<robot_hw_sim_type_str<<
"\"");
267 if(_sdf->HasElement(
"updateRate"))
269 update_rate = _sdf->Get<
int>(
"updateRate");
273 ROS_ERROR(
"[Ignition ROS Control] No updateRate defined in the sdf file.");
278 std::string ros_node_name =
"ign_ros_control_plugin";
280 char* arg0 = strdup(ros_node_name.c_str());
281 char* argv[] = {arg0, 0};
285 ROS_ERROR(
"[Ignition ROS Control] Something other than this ign_ros_control_plugin started ros::init(...).");
287 dataPtr = std::make_unique<IgnitionROSControlPluginPrivate>(robot_namespace,robot_description);
290 const auto model = ignition::gazebo::Model(_entity);
291 if (!model.Valid(_ecm)) {
293 "[Ignition ROS Control] Failed to initialize because [%s] (Entity=%lu)] is not a model."
294 "Please make sure that Ignition ROS Control is attached to a valid model.",
295 model.Name(_ecm).c_str(), _entity);
300 model.Name(_ecm) <<
"] (Entity=" << _entity <<
")].");
303 auto enabledJoints = this->
dataPtr->GetEnabledJoints(
307 if (enabledJoints.size() == 0) {
315 const std::string urdf_string = this->
dataPtr->getURDF(robot_description);
316 if (!this->
dataPtr->parseTransmissionsFromURDF(urdf_string))
318 ROS_ERROR(
"[Ignition ROS Control] Error parsing URDF in gazebo_ros_control plugin, plugin not active.\n");
325 this->
dataPtr->robot_hw_sim_loader_.reset
328 "ign_ros_control::IgnitionSystemInterface"));
330 this->
dataPtr->robot_hw_ = this->
dataPtr->robot_hw_sim_loader_->createInstance(robot_hw_sim_type_str);
334 if(!this->
dataPtr->robot_hw_->initSim(this->dataPtr->model_nh_, enabledJoints, _ecm, this->dataPtr->transmissions_, update_rate))
336 ROS_FATAL(
"[Ignition ROS Control] Could not initialize robot simulation interface.");
342 this->
dataPtr->controller_manager_.reset
349 ROS_FATAL_STREAM(
"[Ignition ROS Control] Failed to create robot simulation interface loader: "<<ex.what());
354 this->
dataPtr->entity_ = _entity;
359 const ignition::gazebo::UpdateInfo & _info,
360 ignition::gazebo::EntityComponentManager & )
362 static bool warned{
false};
364 double dt = std::chrono::duration_cast<std::chrono::duration<double>>( _info.dt ).count();
368 if (this->
dataPtr->control_period_.toSec() < dt) {
370 "[Ignition ROS Control] Desired controller update period (" << this->
dataPtr->control_period_.toSec() <<
371 " s) is faster than the gazebo simulation period (" <<
372 gazebo_period.
toSec() <<
" s).");
373 }
else if (this->
dataPtr->control_period_.toSec() > gazebo_period.
toSec()) {
375 "[Ignition ROS Control] Desired controller update period (" << this->
dataPtr->control_period_.toSec() <<
376 " s) is slower than the gazebo simulation period (" <<
377 gazebo_period.
toSec() <<
" s).");
384 this->
dataPtr->robot_hw_->write();
389 const ignition::gazebo::UpdateInfo & _info,
390 const ignition::gazebo::EntityComponentManager & )
394 double sim_time = std::chrono::duration_cast<std::chrono::duration<double>>( _info.simTime ).count();
397 ros::Duration sim_period(sim_time_ros.
toSec() - this->dataPtr->last_update_sim_time_ros_.toSec());
399 if (sim_period.
toSec() >= this->dataPtr->control_period_.toSec()) {
400 this->
dataPtr->last_update_sim_time_ros_ = sim_time_ros;
401 this->
dataPtr->robot_hw_->read();
402 this->
dataPtr->controller_manager_->update(sim_time_ros, sim_period);
410 ignition::gazebo::System,
411 ign_ros_control::IgnitionROSControlPlugin::ISystemConfigure,
412 ign_ros_control::IgnitionROSControlPlugin::ISystemPreUpdate,
413 ign_ros_control::IgnitionROSControlPlugin::ISystemPostUpdate)