parse.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * BSD 3-Clause License
3  *
4  * Copyright (c) 2021, Qiayuan Liao
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * * Redistributions of source code must retain the above copyright notice, this
11  * list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright notice,
14  * this list of conditions and the following disclaimer in the documentation
15  * and/or other materials provided with the distribution.
16  *
17  * * Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived from
19  * this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE
25  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *******************************************************************************/
33 
34 //
35 // Created by qiayuan on 5/16/21.
36 //
37 
39 
45 
46 namespace rm_hw
47 {
48 // Lots of ugly parse xml code...
49 
51 {
53  try
54  {
55  for (auto it = act_coeffs.begin(); it != act_coeffs.end(); ++it)
56  {
57  ActCoeff act_coeff{};
58 
59  // All motor
60  if (it->second.hasMember("act2pos"))
61  act_coeff.act2pos = xmlRpcGetDouble(act_coeffs[it->first], "act2pos", 0.);
62  else
63  ROS_ERROR_STREAM("Actuator type " << it->first << " has no associated act2pos.");
64  if (it->second.hasMember("act2vel"))
65  act_coeff.act2vel = xmlRpcGetDouble(act_coeffs[it->first], "act2vel", 0.);
66  else
67  ROS_ERROR_STREAM("Actuator type " << it->first << " has no associated act2vel.");
68  if (it->second.hasMember("act2effort"))
69  act_coeff.act2effort = xmlRpcGetDouble(act_coeffs[it->first], "act2effort", 0.);
70  else
71  ROS_ERROR_STREAM("Actuator type " << it->first << " has no associated act2effort.");
72  if (it->second.hasMember("pos2act"))
73  act_coeff.pos2act = xmlRpcGetDouble(act_coeffs[it->first], "pos2act", 0.);
74  else
75  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated pos2act.");
76  if (it->second.hasMember("vel2act"))
77  act_coeff.vel2act = xmlRpcGetDouble(act_coeffs[it->first], "vel2act", 0.);
78  else
79  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated vel2act.");
80  if (it->second.hasMember("effort2act"))
81  act_coeff.effort2act = xmlRpcGetDouble(act_coeffs[it->first], "effort2act", 0.0);
82  else
83  ROS_ERROR_STREAM("Actuator type " << it->first << " has no associated effort2act.");
84  if (it->second.hasMember("max_out"))
85  act_coeff.max_out = xmlRpcGetDouble(act_coeffs[it->first], "max_out", 0.0);
86  else
87  ROS_ERROR_STREAM("Actuator type " << it->first << " has no associated max_out.");
88 
89  // MIT Cheetah Motor
90  if (it->second.hasMember("act2pos_offset"))
91  act_coeff.act2pos_offset = xmlRpcGetDouble(act_coeffs[it->first], "act2pos_offset", -12.5);
92  else
93  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated act2pos_offset.");
94  if (it->second.hasMember("act2vel_offset"))
95  act_coeff.act2vel_offset = xmlRpcGetDouble(act_coeffs[it->first], "act2vel_offset", -65.0);
96  else
97  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated act2vel_offset.");
98  if (it->second.hasMember("act2effort_offset"))
99  act_coeff.act2effort_offset = xmlRpcGetDouble(act_coeffs[it->first], "act2effort_offset", -18.0);
100  else
101  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated act2effort_offset.");
102  if (it->second.hasMember("kp2act"))
103  act_coeff.kp2act = xmlRpcGetDouble(act_coeffs[it->first], "kp2act", 8.19);
104  else
105  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated kp2act.");
106  if (it->second.hasMember("kp2act"))
107  act_coeff.kp2act = xmlRpcGetDouble(act_coeffs[it->first], "kd2act", 819);
108  else
109  ROS_DEBUG_STREAM("Actuator type " << it->first << " has no associated kd2act.");
110 
111  std::string type = it->first;
112  if (type2act_coeffs_.find(type) == type2act_coeffs_.end())
113  type2act_coeffs_.insert(std::make_pair(type, act_coeff));
114  else
115  ROS_ERROR_STREAM("Repeat actuator coefficient of type: " << type);
116  }
117  }
118  catch (XmlRpc::XmlRpcException& e)
119  {
120  ROS_FATAL_STREAM("Exception raised by XmlRpc while reading the "
121  << "configuration: " << e.getMessage() << ".\n"
122  << "Please check the configuration, particularly parameter types.");
123  return false;
124  }
125  return true;
126 }
127 
128 bool RmRobotHW::parseActData(XmlRpc::XmlRpcValue& act_datas, ros::NodeHandle& robot_hw_nh)
129 {
131  try
132  {
133  for (auto it = act_datas.begin(); it != act_datas.end(); ++it)
134  {
135  if (!it->second.hasMember("bus"))
136  {
137  ROS_ERROR_STREAM("Actuator " << it->first << " has no associated bus.");
138  continue;
139  }
140  else if (!it->second.hasMember("type"))
141  {
142  ROS_ERROR_STREAM("Actuator " << it->first << " has no associated type.");
143  continue;
144  }
145  else if (!it->second.hasMember("id"))
146  {
147  ROS_ERROR_STREAM("Actuator " << it->first << " has no associated ID.");
148  continue;
149  }
150  bool need_calibration = false;
151  if (!it->second.hasMember("need_calibration"))
152  ROS_DEBUG_STREAM("Actuator " << it->first << " set no need calibration by default.");
153  else
154  need_calibration = it->second["need_calibration"];
155  std::string bus = act_datas[it->first]["bus"], type = act_datas[it->first]["type"];
156  int id = static_cast<int>(act_datas[it->first]["id"]);
157  // check define of act_coeffs
158  if (type2act_coeffs_.find(type) == type2act_coeffs_.end())
159  {
160  ROS_ERROR_STREAM("Type " << type << " has no associated coefficient.");
161  return false;
162  }
163  // for bus interface
164  if (bus_id2act_data_.find(bus) == bus_id2act_data_.end())
165  bus_id2act_data_.insert(std::make_pair(bus, std::unordered_map<int, ActData>()));
166 
167  if (!(bus_id2act_data_[bus].find(id) == bus_id2act_data_[bus].end()))
168  {
169  ROS_ERROR_STREAM("Repeat actuator on bus " << bus << " and ID " << id);
170  return false;
171  }
172  else
173  {
174  ros::NodeHandle nh = ros::NodeHandle(robot_hw_nh, "actuators/" + it->first);
175  bus_id2act_data_[bus].insert(std::make_pair(id, ActData{ .name = it->first,
176  .type = type,
177  .stamp = ros::Time::now(),
178  .seq = 0,
179  .halted = false,
180  .need_calibration = need_calibration,
181  .calibrated = false,
182  .calibration_reading = false,
183  .q_raw = 0,
184  .qd_raw = 0,
185  .temp = 0,
186  .q_circle = 0,
187  .q_last = 0,
188  .frequency = 0,
189  .pos = 0,
190  .vel = 0,
191  .effort = 0,
192  .cmd_pos = 0,
193  .cmd_vel = 0,
194  .cmd_effort = 0,
195  .exe_effort = 0,
196  .offset = 0,
197  .lp_filter = new LowPassFilter(nh) }));
198  }
199 
200  // for ros_control interface
201  hardware_interface::ActuatorStateHandle act_state(bus_id2act_data_[bus][id].name, &bus_id2act_data_[bus][id].pos,
202  &bus_id2act_data_[bus][id].vel,
203  &bus_id2act_data_[bus][id].effort);
204  rm_control::ActuatorExtraHandle act_extra(bus_id2act_data_[bus][id].name, &bus_id2act_data_[bus][id].halted,
205  &bus_id2act_data_[bus][id].need_calibration,
206  &bus_id2act_data_[bus][id].calibrated,
207  &bus_id2act_data_[bus][id].calibration_reading,
208  &bus_id2act_data_[bus][id].pos, &bus_id2act_data_[bus][id].offset);
210  act_extra_interface_.registerHandle(act_extra);
211  // RoboMaster motors are effect actuator
212  if (type.find("rm") != std::string::npos || type.find("cheetah") != std::string::npos)
213  {
215  hardware_interface::ActuatorHandle(act_state, &bus_id2act_data_[bus][id].exe_effort));
216  }
217  else
218  {
219  ROS_ERROR_STREAM("Actuator " << it->first << "'s type neither RoboMaster(rm_xxx) nor Cheetah(cheetah_xxx)");
220  return false;
221  }
222  }
226  is_actuator_specified_ = true;
227  }
228  catch (XmlRpc::XmlRpcException& e)
229  {
230  ROS_FATAL_STREAM("Exception raised by XmlRpc while reading the "
231  << "configuration: " << e.getMessage() << ".\n"
232  << "Please check the configuration, particularly parameter types.");
233  return false;
234  }
235  return true;
236 }
237 
239 {
241  try
242  {
243  for (auto it = imu_datas.begin(); it != imu_datas.end(); ++it)
244  {
245  std::string name = it->first;
246  if (!it->second.hasMember("frame_id"))
247  {
248  ROS_ERROR_STREAM("Imu " << name << " has no associated frame id.");
249  continue;
250  }
251  else if (!it->second.hasMember("bus"))
252  {
253  ROS_ERROR_STREAM("Imu " << name << " has no associated bus.");
254  continue;
255  }
256  else if (!it->second.hasMember("id"))
257  {
258  ROS_ERROR_STREAM("Imu " << name << " has no associated ID.");
259  continue;
260  }
261  else if (!it->second.hasMember("orientation_covariance_diagonal"))
262  {
263  ROS_ERROR_STREAM("Imu " << name << " has no associated orientation covariance diagonal.");
264  continue;
265  }
266  else if (!it->second.hasMember("angular_velocity_covariance"))
267  {
268  ROS_ERROR_STREAM("Imu " << name << " has no associated angular velocity covariance.");
269  continue;
270  }
271  else if (!it->second.hasMember("linear_acceleration_covariance"))
272  {
273  ROS_ERROR_STREAM("Imu " << name << " has no associated linear acceleration covariance.");
274  continue;
275  }
276  else if (!it->second.hasMember("angular_vel_offset"))
277  {
278  ROS_ERROR_STREAM("Imu " << name << " has no associated angular_vel_offset type");
279  continue;
280  }
281  else if (!it->second.hasMember("angular_vel_coeff"))
282  {
283  ROS_ERROR_STREAM("Imu " << name << " has no associated angular velocity coefficient.");
284  continue;
285  }
286  else if (!it->second.hasMember("accel_coeff"))
287  {
288  ROS_ERROR_STREAM("Imu " << name << " has no associated linear acceleration coefficient.");
289  continue;
290  }
291  else if (!it->second.hasMember("temp_coeff"))
292  {
293  ROS_ERROR_STREAM("Imu " << name << " has no associated temperate coefficient.");
294  continue;
295  }
296  else if (!it->second.hasMember("filter"))
297  {
298  ROS_ERROR_STREAM("Imu " << name << " has no associated filter type");
299  continue;
300  }
301  else if (!it->second.hasMember("angular_vel_offset"))
302  {
303  ROS_ERROR_STREAM("Imu " << name << " has no associated angular_vel_offset type");
304  continue;
305  }
306  XmlRpc::XmlRpcValue angular_vel_offsets = imu_datas[name]["angular_vel_offset"];
307  ROS_ASSERT(angular_vel_offsets.getType() == XmlRpc::XmlRpcValue::TypeArray);
308  ROS_ASSERT(angular_vel_offsets.size() == 3);
309  for (int i = 0; i < angular_vel_offsets.size(); ++i)
310  ROS_ASSERT(angular_vel_offsets[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
311  XmlRpc::XmlRpcValue ori_cov = imu_datas[name]["orientation_covariance_diagonal"];
313  ROS_ASSERT(ori_cov.size() == 3);
314  for (int i = 0; i < ori_cov.size(); ++i)
315  ROS_ASSERT(ori_cov[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
316  XmlRpc::XmlRpcValue angular_cov = imu_datas[name]["angular_velocity_covariance"];
318  ROS_ASSERT(angular_cov.size() == 3);
319  for (int i = 0; i < angular_cov.size(); ++i)
320  ROS_ASSERT(angular_cov[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
321  XmlRpc::XmlRpcValue linear_cov = imu_datas[name]["linear_acceleration_covariance"];
323  ROS_ASSERT(linear_cov.size() == 3);
324  for (int i = 0; i < linear_cov.size(); ++i)
325  ROS_ASSERT(linear_cov[i].getType() == XmlRpc::XmlRpcValue::TypeDouble);
326  std::string filter_type = imu_datas[name]["filter"];
327  // TODO(Zhenyu Ye): Add more types of filter.
328  rm_common::ImuFilterBase* imu_filter;
329  if (filter_type.find("complementary") != std::string::npos)
330  imu_filter = new rm_common::ImuComplementaryFilter;
331  else
332  {
333  ROS_ERROR_STREAM("Imu " << name << " doesn't has filter type " << filter_type);
334  return false;
335  }
336  imu_filter->init(it->second, name);
337 
338  std::string frame_id = imu_datas[name]["frame_id"], bus = imu_datas[name]["bus"];
339  int id = static_cast<int>(imu_datas[name]["id"]);
340 
341  // for bus interface
342  if (bus_id2imu_data_.find(bus) == bus_id2imu_data_.end())
343  bus_id2imu_data_.insert(std::make_pair(bus, std::unordered_map<int, ImuData>()));
344 
345  if (!(bus_id2imu_data_[bus].find(id) == bus_id2imu_data_[bus].end()))
346  {
347  ROS_ERROR_STREAM("Repeat Imu on bus " << bus << " and ID " << id);
348  return false;
349  }
350  else
351  bus_id2imu_data_[bus].insert(std::make_pair(
352  id, ImuData{ .time_stamp = {},
353  .imu_name = name,
354  .ori = {},
355  .angular_vel = {},
356  .linear_acc = {},
357  .angular_vel_offset = { static_cast<double>(angular_vel_offsets[0]),
358  static_cast<double>(angular_vel_offsets[1]),
359  static_cast<double>(angular_vel_offsets[2]) },
360  .ori_cov = { static_cast<double>(ori_cov[0]), 0., 0., 0., static_cast<double>(ori_cov[1]), 0.,
361  0., 0., static_cast<double>(ori_cov[2]) },
362  .angular_vel_cov = { static_cast<double>(angular_cov[0]), 0., 0., 0.,
363  static_cast<double>(angular_cov[1]), 0., 0., 0.,
364  static_cast<double>(angular_cov[2]) },
365  .linear_acc_cov = { static_cast<double>(linear_cov[0]), 0., 0., 0.,
366  static_cast<double>(linear_cov[1]), 0., 0., 0.,
367  static_cast<double>(linear_cov[2]) },
368  .temperature = 0.0,
369  .angular_vel_coeff = xmlRpcGetDouble(imu_datas[name], "angular_vel_coeff", 0.),
370  .accel_coeff = xmlRpcGetDouble(imu_datas[name], "accel_coeff", 0.),
371  .temp_coeff = xmlRpcGetDouble(imu_datas[name], "temp_coeff", 0.),
372  .temp_offset = xmlRpcGetDouble(imu_datas[name], "temp_offset", 0.),
373  .accel_updated = false,
374  .gyro_updated = false,
375  .camera_trigger = false,
376  .enabled_trigger = false,
377  .imu_filter = imu_filter }));
378  // for ros_control interface
379  hardware_interface::ImuSensorHandle imu_sensor_handle(
380  name, frame_id, bus_id2imu_data_[bus][id].ori, bus_id2imu_data_[bus][id].ori_cov,
381  bus_id2imu_data_[bus][id].angular_vel, bus_id2imu_data_[bus][id].angular_vel_cov,
382  bus_id2imu_data_[bus][id].linear_acc, bus_id2imu_data_[bus][id].linear_acc_cov);
383  imu_sensor_interface_.registerHandle(imu_sensor_handle);
384  rm_imu_sensor_interface_.registerHandle(
385  rm_control::RmImuSensorHandle(imu_sensor_handle, &bus_id2imu_data_[bus][id].time_stamp));
386  }
387  registerInterface(&imu_sensor_interface_);
388  registerInterface(&rm_imu_sensor_interface_);
389  }
390  catch (XmlRpc::XmlRpcException& e)
391  {
392  ROS_FATAL_STREAM("Exception raised by XmlRpc while reading the "
393  << "configuration: " << e.getMessage() << ".\n"
394  << "Please check the configuration, particularly parameter types.");
395  return false;
396  }
397  return true;
398 }
399 
400 bool RmRobotHW::parseGpioData(XmlRpc::XmlRpcValue& gpio_datas, ros::NodeHandle& robot_hw_nh)
401 {
402  for (auto it = gpio_datas.begin(); it != gpio_datas.end(); ++it)
403  {
404  if (it->second.hasMember("pin"))
405  {
406  rm_control::GpioData gpio_data;
407  gpio_data.name = it->first;
408  if (std::string(gpio_datas[it->first]["direction"]) == "in")
409  {
410  gpio_data.type = rm_control::INPUT;
411  }
412  else if (std::string(gpio_datas[it->first]["direction"]) == "out")
413  {
414  gpio_data.type = rm_control::OUTPUT;
415  }
416  else
417  {
418  ROS_ERROR("Type set error of %s!", it->first.data());
419  continue;
420  }
421  gpio_data.pin = gpio_datas[it->first]["pin"];
422  gpio_data.value = new bool(false);
423  gpio_manager_.setGpioDirection(gpio_data);
424  gpio_manager_.gpio_state_values.push_back(gpio_data);
425  rm_control::GpioStateHandle gpio_state_handle(it->first, gpio_data.type,
426  gpio_manager_.gpio_state_values.back().value);
427  gpio_state_interface_.registerHandle(gpio_state_handle);
428 
429  if (gpio_data.type == rm_control::OUTPUT)
430  {
431  gpio_manager_.gpio_command_values.push_back(gpio_data);
432  rm_control::GpioCommandHandle gpio_command_handle(it->first, gpio_data.type,
433  gpio_manager_.gpio_command_values.back().value);
434  gpio_command_interface_.registerHandle(gpio_command_handle);
435  }
436  }
437  else
438  {
439  ROS_ERROR("Module %s hasn't set pin ID", it->first.data());
440  }
441  }
442  return true;
443 }
444 
446 {
448  try
449  {
450  for (auto it = tof_datas.begin(); it != tof_datas.end(); ++it)
451  {
452  if (!it->second.hasMember("bus"))
453  {
454  ROS_ERROR_STREAM("TOF02-i " << it->first << " has no associated bus.");
455  continue;
456  }
457  else if (!it->second.hasMember("id"))
458  {
459  ROS_ERROR_STREAM("TOF02-i " << it->first << " has no associated ID.");
460  continue;
461  }
462 
463  std::string bus = tof_datas[it->first]["bus"];
464  int id = static_cast<int>(tof_datas[it->first]["id"]);
465 
466  // for bus interface
467  if (bus_id2tof_data_.find(bus) == bus_id2tof_data_.end())
468  bus_id2tof_data_.insert(std::make_pair(bus, std::unordered_map<int, TofData>()));
469 
470  if (!(bus_id2tof_data_[bus].find(id) == bus_id2tof_data_[bus].end()))
471  {
472  ROS_ERROR_STREAM("Repeat TF02 on bus " << bus << " and ID " << id);
473  return false;
474  }
475  else
476  bus_id2tof_data_[bus].insert(std::make_pair(id, TofData{ .strength = {}, .distance = {} }));
477  // for ros_control interface
478  rm_control::TofRadarHandle tof_radar_handle(it->first, &bus_id2tof_data_[bus][id].distance,
479  &bus_id2tof_data_[bus][id].strength);
480  tof_radar_interface_.registerHandle(tof_radar_handle);
481  }
482  registerInterface(&tof_radar_interface_);
483  }
484  catch (XmlRpc::XmlRpcException& e)
485  {
486  ROS_FATAL_STREAM("Exception raised by XmlRpc while reading the "
487  << "configuration: " << e.getMessage() << ".\n"
488  << "Please check the configuration, particularly parameter types.");
489  return false;
490  }
491  return true;
492 }
493 
495 {
496  if (urdf_model_ == nullptr)
497  urdf_model_ = std::make_shared<urdf::Model>();
498  // get the urdf param on param server
499  root_nh.getParam("/robot_description", urdf_string_);
500  return !urdf_string_.empty() && urdf_model_->initString(urdf_string_);
501 }
502 
504 {
506  return true;
507  try
508  {
510  std::make_unique<transmission_interface::TransmissionInterfaceLoader>(this, &robot_transmissions_);
511  }
512  catch (const std::invalid_argument& ex)
513  {
514  ROS_ERROR_STREAM("Failed to create transmission interface loader. " << ex.what());
515  return false;
516  }
517  catch (const pluginlib::LibraryLoadException& ex)
518  {
519  ROS_ERROR_STREAM("Failed to create transmission interface loader. " << ex.what());
520  return false;
521  }
522  catch (...)
523  {
524  ROS_ERROR_STREAM("Failed to create transmission interface loader. ");
525  return false;
526  }
527 
528  // Perform transmission loading
530  {
531  return false;
532  }
535 
536  auto effort_joint_interface = this->get<hardware_interface::EffortJointInterface>();
537  std::vector<std::string> names = effort_joint_interface->getNames();
538  for (const auto& name : names)
539  effort_joint_handles_.push_back(effort_joint_interface->getHandle(name));
540 
541  return true;
542 }
543 
545 {
547  return true;
548 
549  joint_limits_interface::JointLimits joint_limits; // Position
550  joint_limits_interface::SoftJointLimits soft_limits; // Soft Position
551 
552  for (const auto& joint_handle : effort_joint_handles_)
553  {
554  bool has_joint_limits{}, has_soft_limits{};
555  std::string name = joint_handle.getName();
556  // Get limits from URDF
557  urdf::JointConstSharedPtr urdf_joint = urdf_model_->getJoint(joint_handle.getName());
558  if (urdf_joint == nullptr)
559  {
560  ROS_ERROR_STREAM("URDF joint not found " << name);
561  return false;
562  }
563  // Get limits from URDF
564  if (joint_limits_interface::getJointLimits(urdf_joint, joint_limits))
565  {
566  has_joint_limits = true;
567  ROS_DEBUG_STREAM("Joint " << name << " has URDF position limits.");
568  }
569  else if (urdf_joint->type != urdf::Joint::CONTINUOUS)
570  ROS_DEBUG_STREAM("Joint " << name << " does not have a URDF limit.");
571  // Get soft limits from URDF
572  if (joint_limits_interface::getSoftJointLimits(urdf_joint, soft_limits))
573  {
574  has_soft_limits = true;
575  ROS_DEBUG_STREAM("Joint " << name << " has soft joint limits from URDF.");
576  }
577  else
578  ROS_DEBUG_STREAM("Joint " << name << " does not have soft joint limits from URDF.");
579  // Get limits from ROS param
580  if (joint_limits_interface::getJointLimits(joint_handle.getName(), root_nh, joint_limits))
581  {
582  has_joint_limits = true;
583  ROS_DEBUG_STREAM("Joint " << name << " has rosparam position limits.");
584  }
585  // Get soft limits from ROS param
586  if (joint_limits_interface::getSoftJointLimits(joint_handle.getName(), root_nh, soft_limits))
587  {
588  has_soft_limits = true;
589  ROS_DEBUG_STREAM("Joint " << name << " has soft joint limits from ROS param.");
590  }
591  else
592  ROS_DEBUG_STREAM("Joint " << name << " does not have soft joint limits from ROS param.");
593 
594  // Slightly reduce the joint limits to prevent floating point errors
595  if (joint_limits.has_position_limits)
596  {
597  joint_limits.min_position += std::numeric_limits<double>::epsilon();
598  joint_limits.max_position -= std::numeric_limits<double>::epsilon();
599  }
600  if (has_soft_limits)
601  { // Use soft limits
602  ROS_DEBUG_STREAM("Using soft saturation limits");
603  effort_jnt_soft_limits_interface_.registerHandle(
604  joint_limits_interface::EffortJointSoftLimitsHandle(joint_handle, joint_limits, soft_limits));
605  }
606  else if (has_joint_limits)
607  {
608  ROS_DEBUG_STREAM("Using saturation limits (not soft limits)");
609  effort_jnt_saturation_interface_.registerHandle(
610  joint_limits_interface::EffortJointSaturationHandle(joint_handle, joint_limits));
611  }
612  }
613  return true;
614 }
615 
616 } // namespace rm_hw
XmlRpc::XmlRpcValue::size
int size() const
rm_hw::RmRobotHW::jnt_to_act_effort_
transmission_interface::JointToActuatorEffortInterface * jnt_to_act_effort_
Definition: hardware_interface.h:259
rm_hw::RmRobotHW::effort_jnt_saturation_interface_
joint_limits_interface::EffortJointSaturationInterface effort_jnt_saturation_interface_
Definition: hardware_interface.h:260
rm_control::GpioData::value
bool * value
joint_limits_interface::EffortJointSoftLimitsHandle
xmlRpcGetDouble
double xmlRpcGetDouble(XmlRpc::XmlRpcValue &value)
joint_limits_interface::JointLimits
rm_control::OUTPUT
OUTPUT
rm_hw::RmRobotHW::act_extra_interface_
rm_control::ActuatorExtraInterface act_extra_interface_
Definition: hardware_interface.h:251
ROS_ERROR_STREAM
#define ROS_ERROR_STREAM(args)
rm_hw::RmRobotHW::parseActData
bool parseActData(XmlRpc::XmlRpcValue &act_datas, ros::NodeHandle &robot_hw_nh)
Check whether actuator is specified and load specified params.
Definition: parse.cpp:159
rm_hw::RmRobotHW::gpio_state_interface_
rm_control::GpioStateInterface gpio_state_interface_
Definition: hardware_interface.h:248
XmlRpc::XmlRpcException::getMessage
const std::string & getMessage() const
rm_hw::RmRobotHW::act_to_jnt_state_
transmission_interface::ActuatorToJointStateInterface * act_to_jnt_state_
Definition: hardware_interface.h:258
hardware_interface::InterfaceManager::get
T * get()
ros::NodeHandle::getParam
bool getParam(const std::string &key, bool &b) const
ROS_FATAL_STREAM
#define ROS_FATAL_STREAM(args)
hardware_interface::InterfaceManager::registerInterface
void registerInterface(T *iface)
joint_limits_interface::getJointLimits
bool getJointLimits(const std::string &joint_name, const ros::NodeHandle &nh, JointLimits &limits)
rm_hw::RmRobotHW::parseImuData
bool parseImuData(XmlRpc::XmlRpcValue &imu_datas, ros::NodeHandle &robot_hw_nh)
Check whether some params that are related to imu are set up and load these params.
Definition: parse.cpp:269
hardware_interface::ActuatorStateHandle
rm_hw::GpioManager::setGpioDirection
void setGpioDirection(rm_control::GpioData gpioData)
Definition: gpio_manager.cpp:16
rm_hw::RmRobotHW::loadUrdf
bool loadUrdf(ros::NodeHandle &root_nh)
Load urdf of robot from param server.
Definition: parse.cpp:525
rm_hw::RmRobotHW::parseGpioData
bool parseGpioData(XmlRpc::XmlRpcValue &gpio_datas, ros::NodeHandle &robot_hw_nh)
Check whether somme params that are related to gpio are set up and load these params.
Definition: parse.cpp:431
joint_limits_interface::JointLimits::max_position
double max_position
rm_control::INPUT
INPUT
rm_hw::RmRobotHW::setupTransmission
bool setupTransmission(ros::NodeHandle &root_nh)
Set up transmission.
Definition: parse.cpp:534
rm_control::GpioData::pin
int pin
rm_hw::RmRobotHW::effort_jnt_soft_limits_interface_
joint_limits_interface::EffortJointSoftLimitsInterface effort_jnt_soft_limits_interface_
Definition: hardware_interface.h:261
rm_hw::RmRobotHW::type2act_coeffs_
std::unordered_map< std::string, ActCoeff > type2act_coeffs_
Definition: hardware_interface.h:270
ROS_DEBUG_STREAM
#define ROS_DEBUG_STREAM(args)
rm_control::GpioData::name
std::string name
imu_complementary_filter.h
transmission_interface::ActuatorToJointStateInterface
XmlRpc::XmlRpcValue::TypeStruct
TypeStruct
rm_hw::TofData::strength
double strength
Definition: types.h:120
TransmissionInterface< JointToActuatorEffortHandle >::getHandle
JointToActuatorEffortHandle getHandle(const std::string &name)
rm_hw::RmRobotHW::urdf_model_
std::shared_ptr< urdf::Model > urdf_model_
Definition: hardware_interface.h:267
rm_hw::RmRobotHW::gpio_command_interface_
rm_control::GpioCommandInterface gpio_command_interface_
Definition: hardware_interface.h:249
XmlRpc::XmlRpcValue::TypeDouble
TypeDouble
rm_control::RmImuSensorHandle
rm_hw::RmRobotHW::parseTofData
bool parseTofData(XmlRpc::XmlRpcValue &tof_datas, ros::NodeHandle &robot_hw_nh)
Definition: parse.cpp:476
rm_common::ImuFilterBase
rm_common::ImuComplementaryFilter
rm_hw::RmRobotHW::bus_id2act_data_
std::unordered_map< std::string, std::unordered_map< int, ActData > > bus_id2act_data_
Definition: hardware_interface.h:271
rm_hw::RmRobotHW::effort_joint_handles_
std::vector< hardware_interface::JointHandle > effort_joint_handles_
Definition: hardware_interface.h:262
rm_hw::RmRobotHW::gpio_manager_
GpioManager gpio_manager_
Definition: hardware_interface.h:247
hardware_interface::ActuatorHandle
joint_limits_rosparam.h
rm_control::GpioData
rm_hw::RmRobotHW::urdf_string_
std::string urdf_string_
Definition: hardware_interface.h:266
rm_hw::RmRobotHW::robot_transmissions_
transmission_interface::RobotTransmissions robot_transmissions_
Definition: hardware_interface.h:257
ResourceManager< ActuatorStateHandle >::registerHandle
void registerHandle(const ActuatorStateHandle &handle)
XmlRpc::XmlRpcValue::end
iterator end()
XmlRpc::XmlRpcValue::getType
const Type & getType() const
transmission_interface_loader.h
XmlRpc::XmlRpcValue::TypeArray
TypeArray
XmlRpc::XmlRpcException
hardware_interface::ImuSensorHandle
hardware_interface.h
joint_limits_interface::JointLimits::min_position
double min_position
rm_control::TofRadarHandle
rm_control::GpioCommandHandle
joint_limits_urdf.h
rm_hw::RmRobotHW::act_state_interface_
hardware_interface::ActuatorStateInterface act_state_interface_
Definition: hardware_interface.h:250
ROS_ERROR
#define ROS_ERROR(...)
rm_hw::RmRobotHW::is_actuator_specified_
bool is_actuator_specified_
Definition: hardware_interface.h:243
rm_control::GpioStateHandle
ros_utilities.h
rm_hw::GpioManager::gpio_command_values
std::vector< rm_control::GpioData > gpio_command_values
Definition: gpio_manager.h:28
pluginlib::LibraryLoadException
rm_hw::RmRobotHW::transmission_loader_
std::unique_ptr< transmission_interface::TransmissionInterfaceLoader > transmission_loader_
Definition: hardware_interface.h:256
rm_hw::RmRobotHW::setupJointLimit
bool setupJointLimit(ros::NodeHandle &root_nh)
Set up joint limit.
Definition: parse.cpp:575
XmlRpc::XmlRpcValue::begin
iterator begin()
transmission_interface::JointToActuatorEffortInterface
rm_hw
Definition: control_loop.h:48
joint_limits_interface::EffortJointSaturationHandle
joint_limits_interface::SoftJointLimits
joint_limits_interface::getSoftJointLimits
bool getSoftJointLimits(const std::string &joint_name, const ros::NodeHandle &nh, SoftJointLimits &soft_limits)
ROS_ASSERT
#define ROS_ASSERT(cond)
rm_control::GpioData::type
GpioType type
rm_hw::RmRobotHW::parseActCoeffs
bool parseActCoeffs(XmlRpc::XmlRpcValue &act_coeffs)
Check whether some coefficients that are related to actuator are set up and load these coefficients.
Definition: parse.cpp:81
joint_limits_interface::JointLimits::has_position_limits
bool has_position_limits
rm_hw::GpioManager::gpio_state_values
std::vector< rm_control::GpioData > gpio_state_values
Definition: gpio_manager.h:27
rm_control::ActuatorExtraHandle
rm_hw::RmRobotHW::effort_act_interface_
hardware_interface::EffortActuatorInterface effort_act_interface_
Definition: hardware_interface.h:252
rm_hw::TofData
Definition: types.h:118
rm_common::ImuFilterBase::init
bool init(XmlRpc::XmlRpcValue &imu_data, const std::string &name)
XmlRpc::XmlRpcValue
LowPassFilter
ros::NodeHandle
ros::Time::now
static Time now()


rm_hw
Author(s): Qiayuan Liao
autogenerated on Tue May 6 2025 02:23:44