hwi_switch_robot_hw_sim.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 // cob_gazebo_ros_control
20 #include <boost/algorithm/string/replace.hpp>
21 
22 namespace cob_gazebo_ros_control
23 {
24 
26  const std::string& robot_namespace,
27  ros::NodeHandle model_nh,
28  gazebo::physics::ModelPtr parent_model,
29  const urdf::Model *const urdf_model,
30  std::vector<transmission_interface::TransmissionInfo> transmissions)
31 {
32  // getJointLimits() searches joint_limit_nh for joint limit parameters. The format of each
33  // parameter's name is "joint_limits/<joint name>". An example is "joint_limits/axle_joint".
34  const ros::NodeHandle joint_limit_nh(model_nh, robot_namespace);
35 
36  // Resize vectors to our DOF
38  {
39  n_dof_ = enabled_joints_.size();
40  ROS_INFO_STREAM("JointFiltering is enabled! DoF: "<<n_dof_);
41  }
42  else
43  {
44  n_dof_ = transmissions.size();
45  ROS_INFO_STREAM("JointFiltering is disabled! DoF: "<<n_dof_);
46  }
47 
48  joint_names_.resize(n_dof_);
49  joint_types_.resize(n_dof_);
56  joint_position_.resize(n_dof_);
57  joint_velocity_.resize(n_dof_);
58  joint_effort_.resize(n_dof_);
62 
63  // Initialize values
64  unsigned int index = 0;
65  for(unsigned int j=0; j < transmissions.size(); j++)
66  {
67  // Check that this transmission has one joint
68  if(transmissions[j].joints_.size() == 0)
69  {
70  ROS_WARN_STREAM_NAMED("hwi_switch_robot_hw_sim","Transmission " << transmissions[j].name_
71  << " has no associated joints.");
72  continue;
73  }
74  else if(transmissions[j].joints_.size() > 1)
75  {
76  ROS_WARN_STREAM_NAMED("hwi_switch_robot_hw_sim","Transmission " << transmissions[j].name_
77  << " has more than one joint. Currently the default robot hardware simulation "
78  << " interface only supports one.");
79  continue;
80  }
81 
82  std::vector<std::string> joint_interfaces = transmissions[j].joints_[0].hardware_interfaces_;
83  if (joint_interfaces.empty() &&
84  !(transmissions[j].actuators_.empty()) &&
85  !(transmissions[j].actuators_[0].hardware_interfaces_.empty()))
86  {
87  // TODO: Deprecate HW interface specification in actuators in ROS J
88  joint_interfaces = transmissions[j].actuators_[0].hardware_interfaces_;
89  ROS_WARN_STREAM_NAMED("hwi_switch_robot_hw_sim", "The <hardware_interface> element of tranmission " <<
90  transmissions[j].name_ << " should be nested inside the <joint> element, not <actuator>. " <<
91  "The transmission will be properly loaded, but please update " <<
92  "your robot model to remain compatible with future versions of the plugin.");
93  }
94  if (joint_interfaces.empty())
95  {
96  ROS_WARN_STREAM_NAMED("hwi_switch_robot_hw_sim", "Joint " << transmissions[j].joints_[0].name_ <<
97  " of transmission " << transmissions[j].name_ << " does not specify any hardware interface. " <<
98  "Not adding it to the robot hardware simulation.");
99  continue;
100  }
101  else if (joint_interfaces.size() > 1)
102  {
103  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "Joint " << transmissions[j].joints_[0].name_ <<
104  " of transmission " << transmissions[j].name_ << " specifies multiple hardware interfaces. " <<
105  "This feature is now available.");
106  }
107 
109  {
110  if(enabled_joints_.find(transmissions[j].joints_[0].name_)!=enabled_joints_.end())
111  {
112  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "Found enabled joint '"<<transmissions[j].joints_[0].name_<<"'; j "<<j<<"; index: "<<index);
113  }
114  else
115  {
116  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "Joint '"<<transmissions[j].joints_[0].name_<<"' is not enabled; j "<<j<<"; index: "<<index);
117  continue;
118  }
119  }
120  else
121  {
122  index = j;
123  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "JointFiltering is disabled. Use joint '"<<transmissions[j].joints_[0].name_<<"'; j "<<j<<"; index: "<<index);
124  }
125 
126  // Add data from transmission
127  joint_names_[index] = transmissions[j].joints_[0].name_;
128  joint_position_[index] = 1.0;
129  joint_velocity_[index] = 0.0;
130  joint_effort_[index] = 1.0; // N/m for continuous joints
131  joint_effort_command_[index] = 0.0;
132  joint_position_command_[index] = 0.0;
133  joint_velocity_command_[index] = 0.0;
134 
135 
136  // Create joint state interface for all joints
138  joint_names_[index], &joint_position_[index], &joint_velocity_[index], &joint_effort_[index]));
139 
140  // Decide what kind of command interface this actuator/joint has
141  hardware_interface::JointHandle joint_handle;
142 
143  // Parse all HW-Interfaces available for each joint and store information
144  for(unsigned int i=0; i<joint_interfaces.size(); i++)
145  {
146  // Debug
147  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim","Loading joint '" << joint_names_[index]
148  << "' of type '" << joint_interfaces[i] << "'");
149 
150  // Deprecated Syntax handling
151  std::string& hardware_interface = joint_interfaces[i];
152  if(hardware_interface == "EffortJointInterface" || hardware_interface == "PositionJointInterface" || hardware_interface == "VelocityJointInterface") {
153  ROS_WARN_STREAM("Deprecated syntax, please prepend 'hardware_interface/' to '" << hardware_interface << "' within the <hardwareInterface> tag in joint '" << joint_names_[index] << "'.");
154  hardware_interface = "hardware_interface/"+joint_interfaces[i];
155  }
156 
157  // Add hardware interface and joint to map of map_hwinterface_to_joints_
158  std::string hw_interface_type = boost::algorithm::replace_all_copy(hardware_interface, "/", "::");
159  if(map_hwinterface_to_joints_.find(hw_interface_type)!=map_hwinterface_to_joints_.end())
160  {
161  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "HW-Interface " << hw_interface_type << " already registered. Adding joint " << joint_names_[index] << " to list.");
162  std::map< std::string, std::set<std::string> >::iterator it;
163  it=map_hwinterface_to_joints_.find(hw_interface_type);
164  it->second.insert(joint_names_[index]);
165  }
166  else
167  {
168  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "New HW-Interface registered " << hw_interface_type << ". Adding joint " << joint_names_[index] << " to list.");
169  std::set<std::string> supporting_joints;
170  supporting_joints.insert(joint_names_[index]);
171  map_hwinterface_to_joints_.insert( std::pair< std::string, std::set<std::string> >(hw_interface_type, supporting_joints) );
172  }
173 
174  if(hw_interface_type == "hardware_interface::EffortJointInterface")
175  {
176  // Create effort joint interface
177  ControlMethod control_method = EFFORT;
178  if(i==0){ joint_control_methods_[index] = control_method; } //use first entry for startup
179  map_hwinterface_to_controlmethod_.insert( std::pair<std::string, ControlMethod>(hw_interface_type, control_method) );
180 
182  &joint_effort_command_[index]);
183  ej_interface_.registerHandle(joint_handle);
184 
185  registerJointLimits(joint_names_[index], joint_handle, control_method,
186  joint_limit_nh, urdf_model,
187  &joint_types_[index], &joint_lower_limits_[index], &joint_upper_limits_[index],
188  &joint_effort_limits_[index]);
189  }
190  else if(hw_interface_type == "hardware_interface::PositionJointInterface")
191  {
192  // Create position joint interface
193  ControlMethod control_method = POSITION;
194  if(i==0){ joint_control_methods_[index] = control_method; } //use first entry for startup
195  map_hwinterface_to_controlmethod_.insert( std::pair<std::string, ControlMethod>(hw_interface_type, control_method) );
196 
198  &joint_position_command_[index]);
199  pj_interface_.registerHandle(joint_handle);
200 
201  registerJointLimits(joint_names_[index], joint_handle, control_method,
202  joint_limit_nh, urdf_model,
203  &joint_types_[index], &joint_lower_limits_[index], &joint_upper_limits_[index],
204  &joint_effort_limits_[index]);
205  }
206  else if(hw_interface_type == "hardware_interface::VelocityJointInterface")
207  {
208  // Create velocity joint interface
209  ControlMethod control_method = VELOCITY;
210  if(i==0){ joint_control_methods_[index] = control_method; } //use first entry for startup
211  map_hwinterface_to_controlmethod_.insert( std::pair<std::string, ControlMethod>(hw_interface_type, control_method) );
212 
214  &joint_velocity_command_[index]);
215  vj_interface_.registerHandle(joint_handle);
216 
217  registerJointLimits(joint_names_[index], joint_handle, control_method,
218  joint_limit_nh, urdf_model,
219  &joint_types_[index], &joint_lower_limits_[index], &joint_upper_limits_[index],
220  &joint_effort_limits_[index]);
221  }
222  else
223  {
224  ROS_FATAL_STREAM_NAMED("hwi_switch_robot_hw_sim","No matching hardware interface found for '"
225  << hardware_interface );
226  return false;
227  }
228  }
229 
230  gazebo::physics::JointPtr joint = parent_model->GetJoint(joint_names_[index]);
231  if (!joint)
232  {
233  ROS_ERROR_STREAM_NAMED("hwi_switch_robot_hw_sim", "This robot has a joint named \"" << joint_names_[index]
234  << "\" which is not in the gazebo model.");
235  return false;
236  }
237  sim_joints_.push_back(joint);
238 
239 
240  // get physics engine type
241 #if GAZEBO_MAJOR_VERSION >= 8
242  gazebo::physics::PhysicsEnginePtr physics = gazebo::physics::get_world()->Physics();
243 #else
244  gazebo::physics::PhysicsEnginePtr physics = gazebo::physics::get_world()->GetPhysicsEngine();
245 #endif
246  physics_type_ = physics->GetType();
247  if (physics_type_.empty())
248  {
249  ROS_WARN_STREAM_NAMED("default_robot_hw_sim", "No physics type found.");
250  }
251 
252 
253  // ToDo: Can a joint (gazebo::physics::JointPtr) be used for EFFORT if joint->SetMaxForce has been called before?
255  {
256  // joint->SetMaxForce() must be called if joint->SetAngle() or joint->SetVelocity() are
257  // going to be called. joint->SetMaxForce() must *not* be called if joint->SetForce() is
258  // going to be called.
259  #if GAZEBO_MAJOR_VERSION > 2
260  joint->SetParam("fmax", 0, joint_effort_limits_[index]);
261  #else
262  joint->SetMaxForce(0, joint_effort_limits_[index]);
263  #endif
264  }
265 
266  index++;
267  }
268 
269  // Register interfaces
274 
275  // Initialize the emergency stop code.
276  state_valid_ = true;
277  e_stop_active_ = false;
278  last_e_stop_active_ = false;
279 
280  return true;
281 }
282 
283 bool HWISwitchRobotHWSim::enableJointFiltering(ros::NodeHandle nh, std::string filter_joints_param)
284 {
285  enabled_joints_.clear();
286  enable_joint_filtering_ = false;
287 
288  std::vector<std::string> joints;
289  if(!nh.getParam(filter_joints_param, joints))
290  {
291  ROS_ERROR_STREAM_NAMED("hwi_switch_robot_hw_sim", "Parameter '"<<filter_joints_param<<"' not set");
292  return false;
293  }
294 
295  for(std::vector<std::string>::iterator it = joints.begin() ; it != joints.end(); ++it)
296  {
297  enabled_joints_.insert(*it);
298  }
299 
301  return true;
302 }
303 
304 bool HWISwitchRobotHWSim::canSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list) const
305 {
306  //for all controllers to be started check whether all resources provide the required hardware_interface
307  //conflicts, i.e. different hardware_interfaces for the same resource is checked in checkForConflict()
308  //stopped controllers stay in there current mode as there is no no_operation_mode in gazebo
309  for (std::list<hardware_interface::ControllerInfo>::const_iterator list_it = start_list.begin(); list_it != start_list.end(); ++list_it)
310  {
311  for (std::vector<hardware_interface::InterfaceResources>::const_iterator res_it = list_it->claimed_resources.begin(); res_it != list_it->claimed_resources.end(); ++res_it)
312  {
313  for(std::set<std::string>::iterator set_it = res_it->resources.begin(); set_it != res_it->resources.end(); ++set_it)
314  {
315  if(map_hwinterface_to_joints_.at(res_it->hardware_interface).find(*set_it) == map_hwinterface_to_joints_.at(res_it->hardware_interface).end())
316  {
317  ROS_ERROR_STREAM_NAMED("hwi_switch_robot_hw_sim", "Cannot switch because resource \'" << *set_it << "\' does not provide HW-Interface \'" << res_it->hardware_interface << "\'");
318  return false;
319  }
320  }
321  }
322  }
323  return true;
324 }
325 
326 void HWISwitchRobotHWSim::doSwitch(const std::list<hardware_interface::ControllerInfo> &start_list, const std::list<hardware_interface::ControllerInfo> &stop_list)
327 {
328  //for all controllers to be started
329  for (std::list<hardware_interface::ControllerInfo>::const_iterator list_it = start_list.begin(); list_it != start_list.end(); ++list_it)
330  {
331  for (std::vector<hardware_interface::InterfaceResources>::const_iterator res_it = list_it->claimed_resources.begin(); res_it != list_it->claimed_resources.end(); ++res_it)
332  {
333  //for all joints corresponding to this RobotHW
334  for(unsigned int i=0; i<joint_names_.size(); i++)
335  {
336  //if joint is in resource list of controller to be started
337  if(res_it->resources.find(joint_names_[i]) != res_it->resources.end())
338  {
339  if(map_hwinterface_to_controlmethod_.find(res_it->hardware_interface) != map_hwinterface_to_controlmethod_.end())
340  {
341  ControlMethod current_control_method = map_hwinterface_to_controlmethod_.find(res_it->hardware_interface)->second;
342 
345  joint_velocity_command_[i] = 0.0;
346  joint_effort_command_[i] = 0.0;
347 
353  try{ ej_interface_.getHandle(joint_names_[i]).setCommand(joint_effort_command_[i]); }
355 
359 
360  joint_control_methods_[i] = current_control_method;
361 
362  ROS_DEBUG_STREAM_NAMED("hwi_switch_robot_hw_sim", "Resource \'" << joint_names_[i] << "\' switched to HW-Interface \'" << res_it->hardware_interface << "\'");
363  }
364  }
365  }
366  }
367  }
368 }
369 
370 void HWISwitchRobotHWSim::stateValid(const bool valid)
371 {
372  state_valid_ = valid;
373 }
374 
375 }
376 
std::vector< double > joint_upper_limits_
virtual bool enableJointFiltering(ros::NodeHandle nh, std::string filter_joints_param)
#define ROS_DEBUG_STREAM_NAMED(name, args)
#define ROS_ERROR_STREAM_NAMED(name, args)
joint_limits_interface::PositionJointSoftLimitsInterface pj_limits_interface_
hardware_interface::PositionJointInterface pj_interface_
joint_limits_interface::PositionJointSaturationInterface pj_sat_interface_
std::vector< double > joint_position_command_
std::vector< double > joint_lower_limits_
std::vector< double > joint_position_
std::map< std::string, ControlMethod > map_hwinterface_to_controlmethod_
hardware_interface::VelocityJointInterface vj_interface_
virtual bool canSwitch(const std::list< hardware_interface::ControllerInfo > &start_list, const std::list< hardware_interface::ControllerInfo > &stop_list) const
virtual bool initSim(const std::string &robot_namespace, ros::NodeHandle model_nh, gazebo::physics::ModelPtr parent_model, const urdf::Model *const urdf_model, std::vector< transmission_interface::TransmissionInfo > transmissions)
hardware_interface::JointStateInterface js_interface_
hardware_interface::EffortJointInterface ej_interface_
std::vector< double > joint_velocity_
std::vector< std::string > joint_names_
virtual void doSwitch(const std::list< hardware_interface::ControllerInfo > &start_list, const std::list< hardware_interface::ControllerInfo > &stop_list)
std::vector< gazebo::physics::JointPtr > sim_joints_
std::vector< ControlMethod > joint_control_methods_
#define ROS_FATAL_STREAM_NAMED(name, args)
std::vector< double > joint_effort_
void registerJointLimits(const std::string &joint_name, const hardware_interface::JointHandle &joint_handle, const ControlMethod ctrl_method, const ros::NodeHandle &joint_limit_nh, const urdf::Model *const urdf_model, int *const joint_type, double *const lower_limit, double *const upper_limit, double *const effort_limit)
std::vector< double > joint_effort_command_
#define ROS_WARN_STREAM(args)
void registerHandle(const JointStateHandle &handle)
JointStateHandle getHandle(const std::string &name)
#define ROS_INFO_STREAM(args)
bool getParam(const std::string &key, std::string &s) const
PLUGINLIB_EXPORT_CLASS(transmission_interface::BiDirectionalEffortJointInterfaceProvider, transmission_interface::RequisiteProvider)
std::vector< double > joint_velocity_command_
std::vector< double > joint_effort_limits_
#define ROS_WARN_STREAM_NAMED(name, args)
std::map< std::string, std::set< std::string > > map_hwinterface_to_joints_


cob_gazebo_ros_control
Author(s): Felix Messmer
autogenerated on Mon Sep 28 2020 03:19:19