Skip to content

Commit 9e98ec2

Browse files
committed
Ensure backwards compatibility
This ensures backwards compatibility in multiple ways: - When using this with a description not containing the effort interface, it will simply not be exported. Therefore, when trying to start an effort controller that will not work, since the interfaces aren't available. - When using this with a robot software version not supporting torque control this will reject activating effort-controllers.
1 parent bcf9820 commit 9e98ec2

File tree

2 files changed

+59
-33
lines changed

2 files changed

+59
-33
lines changed

ur_robot_driver/include/ur_robot_driver/hardware_interface.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ class URPositionHardwareInterface : public hardware_interface::SystemInterface
231231
bool initialized_;
232232
double system_interface_initialized_;
233233
std::atomic_bool async_thread_shutdown_;
234+
urcl::VersionInformation version_info_;
234235
double get_robot_software_version_major_;
235236
double get_robot_software_version_minor_;
236237
double get_robot_software_version_bugfix_;

ur_robot_driver/src/hardware_interface.cpp

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -157,51 +157,55 @@ URPositionHardwareInterface::on_init(const hardware_interface::HardwareComponent
157157
trajectory_joint_accelerations_.reserve(32768);
158158

159159
for (const hardware_interface::ComponentInfo& joint : info_.joints) {
160-
if (joint.command_interfaces.size() != 3) {
160+
auto has_cmd_interface = [](const hardware_interface::ComponentInfo& joint, const std::string& interface_name) {
161+
auto it = find_if(
162+
joint.command_interfaces.begin(), joint.command_interfaces.end(),
163+
[&interface_name](const hardware_interface::InterfaceInfo& obj) { return obj.name == interface_name; });
164+
return it != joint.command_interfaces.end();
165+
};
166+
167+
if (!has_cmd_interface(joint, hardware_interface::HW_IF_POSITION)) {
161168
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"),
162-
"Joint '%s' has %zu command interfaces found. 3 expected.", joint.name.c_str(),
163-
joint.command_interfaces.size());
169+
"Joint '%s' does not contain a '%s' command interface.", joint.name.c_str(),
170+
hardware_interface::HW_IF_POSITION);
164171
return hardware_interface::CallbackReturn::ERROR;
165172
}
166173

167-
if (joint.command_interfaces[0].name != hardware_interface::HW_IF_POSITION) {
174+
if (!has_cmd_interface(joint, hardware_interface::HW_IF_VELOCITY)) {
168175
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"),
169-
"Joint '%s' have %s command interfaces found as first command interface. '%s' expected.",
170-
joint.name.c_str(), joint.command_interfaces[0].name.c_str(), hardware_interface::HW_IF_POSITION);
176+
"Joint '%s' does not contain a '%s' command interface.", joint.name.c_str(),
177+
hardware_interface::HW_IF_VELOCITY);
171178
return hardware_interface::CallbackReturn::ERROR;
172179
}
173180

174-
if (joint.command_interfaces[1].name != hardware_interface::HW_IF_VELOCITY) {
175-
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"),
176-
"Joint '%s' have %s command interfaces found as second command interface. '%s' expected.",
177-
joint.name.c_str(), joint.command_interfaces[1].name.c_str(), hardware_interface::HW_IF_VELOCITY);
178-
return hardware_interface::CallbackReturn::ERROR;
179-
}
181+
// We treat the torque command interface as optional here for now. This should ensure backwards
182+
// compatibility with older descriptions.
180183

181-
if (joint.state_interfaces.size() != 3) {
182-
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"), "Joint '%s' has %zu state interface. 3 expected.",
183-
joint.name.c_str(), joint.state_interfaces.size());
184-
return hardware_interface::CallbackReturn::ERROR;
185-
}
184+
auto has_state_interface = [](const hardware_interface::ComponentInfo& joint, const std::string& interface_name) {
185+
auto it = find_if(
186+
joint.state_interfaces.begin(), joint.state_interfaces.end(),
187+
[&interface_name](const hardware_interface::InterfaceInfo& obj) { return obj.name == interface_name; });
188+
return it != joint.state_interfaces.end();
189+
};
186190

187-
if (joint.state_interfaces[0].name != hardware_interface::HW_IF_POSITION) {
191+
if (!has_state_interface(joint, hardware_interface::HW_IF_POSITION)) {
188192
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"),
189-
"Joint '%s' have %s state interface as first state interface. '%s' expected.", joint.name.c_str(),
190-
joint.state_interfaces[0].name.c_str(), hardware_interface::HW_IF_POSITION);
193+
"Joint '%s' does not contain a '%s' state interface.", joint.name.c_str(),
194+
hardware_interface::HW_IF_POSITION);
191195
return hardware_interface::CallbackReturn::ERROR;
192196
}
193197

194-
if (joint.state_interfaces[1].name != hardware_interface::HW_IF_VELOCITY) {
198+
if (!has_state_interface(joint, hardware_interface::HW_IF_VELOCITY)) {
195199
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"),
196-
"Joint '%s' have %s state interface as second state interface. '%s' expected.", joint.name.c_str(),
197-
joint.state_interfaces[1].name.c_str(), hardware_interface::HW_IF_VELOCITY);
200+
"Joint '%s' does not contain a '%s' state interface.", joint.name.c_str(),
201+
hardware_interface::HW_IF_VELOCITY);
198202
return hardware_interface::CallbackReturn::ERROR;
199203
}
200204

201-
if (joint.state_interfaces[2].name != hardware_interface::HW_IF_EFFORT) {
205+
if (!has_state_interface(joint, hardware_interface::HW_IF_EFFORT)) {
202206
RCLCPP_FATAL(rclcpp::get_logger("URPositionHardwareInterface"),
203-
"Joint '%s' have %s state interface as third state interface. '%s' expected.", joint.name.c_str(),
204-
joint.state_interfaces[2].name.c_str(), hardware_interface::HW_IF_EFFORT);
207+
"Joint '%s' does not contain a '%s' state interface.", joint.name.c_str(),
208+
hardware_interface::HW_IF_EFFORT);
205209
return hardware_interface::CallbackReturn::ERROR;
206210
}
207211
}
@@ -335,6 +339,12 @@ std::vector<hardware_interface::StateInterface> URPositionHardwareInterface::exp
335339

336340
std::vector<hardware_interface::CommandInterface> URPositionHardwareInterface::export_command_interfaces()
337341
{
342+
auto has_cmd_interface = [](const hardware_interface::ComponentInfo& joint, const std::string& interface_name) {
343+
auto it =
344+
find_if(joint.command_interfaces.begin(), joint.command_interfaces.end(),
345+
[&interface_name](const hardware_interface::InterfaceInfo& obj) { return obj.name == interface_name; });
346+
return it != joint.command_interfaces.end();
347+
};
338348
std::vector<hardware_interface::CommandInterface> command_interfaces;
339349
for (size_t i = 0; i < info_.joints.size(); ++i) {
340350
command_interfaces.emplace_back(hardware_interface::CommandInterface(
@@ -343,8 +353,10 @@ std::vector<hardware_interface::CommandInterface> URPositionHardwareInterface::e
343353
command_interfaces.emplace_back(hardware_interface::CommandInterface(
344354
info_.joints[i].name, hardware_interface::HW_IF_VELOCITY, &urcl_velocity_commands_[i]));
345355

346-
command_interfaces.emplace_back(hardware_interface::CommandInterface(
347-
info_.joints[i].name, hardware_interface::HW_IF_EFFORT, &urcl_torque_commands_[i]));
356+
if (has_cmd_interface(info_.joints[i], hardware_interface::HW_IF_EFFORT)) {
357+
command_interfaces.emplace_back(hardware_interface::CommandInterface(
358+
info_.joints[i].name, hardware_interface::HW_IF_EFFORT, &urcl_torque_commands_[i]));
359+
}
348360
}
349361
// Obtain the tf_prefix from the urdf so that we can have the general interface multiple times
350362
// NOTE using the tf_prefix at this point is some kind of workaround. One should actually go through the list of gpio
@@ -646,11 +658,11 @@ URPositionHardwareInterface::on_configure(const rclcpp_lifecycle::State& previou
646658
}
647659

648660
// Export version information to state interfaces
649-
urcl::VersionInformation version_info = ur_driver_->getVersion();
650-
get_robot_software_version_major_ = version_info.major;
651-
get_robot_software_version_minor_ = version_info.minor;
652-
get_robot_software_version_build_ = version_info.build;
653-
get_robot_software_version_bugfix_ = version_info.bugfix;
661+
version_info_ = ur_driver_->getVersion();
662+
get_robot_software_version_major_ = version_info_.major;
663+
get_robot_software_version_minor_ = version_info_.minor;
664+
get_robot_software_version_build_ = version_info_.build;
665+
get_robot_software_version_bugfix_ = version_info_.bugfix;
654666

655667
async_thread_ = std::make_shared<std::thread>(&URPositionHardwareInterface::asyncThread, this);
656668

@@ -1200,6 +1212,19 @@ hardware_interface::return_type URPositionHardwareInterface::prepare_command_mod
12001212
}
12011213
}
12021214

1215+
// effort control is only available from 5.23.0 / 10.10.0
1216+
if (std::any_of(start_modes_.begin(), start_modes_.end(), [&](const std::vector<std::string>& modes) {
1217+
return std::any_of(modes.begin(), modes.end(),
1218+
[&](const std::string& mode) { return mode == hardware_interface::HW_IF_EFFORT; });
1219+
})) {
1220+
if ((version_info_.major == 5 && version_info_.minor < 23) ||
1221+
(version_info_.major == 10 && version_info_.minor < 10) || version_info_.major < 5) {
1222+
RCLCPP_ERROR(get_logger(), "Requested to use effort interface on a robot version that doesn't support it. Torque "
1223+
"control is available from robot software 5.23.0 / 10.10.0 on.");
1224+
return hardware_interface::return_type::ERROR;
1225+
}
1226+
}
1227+
12031228
if (!std::all_of(start_modes_.begin() + 1, start_modes_.end(),
12041229
[&](const std::vector<std::string>& other) { return other == start_modes_[0]; })) {
12051230
RCLCPP_ERROR(get_logger(), "Start modes of all joints have to be the same.");

0 commit comments

Comments
 (0)