Skip to content

Commit 82f8a22

Browse files
mergify[bot]urmahp
andauthored
Added services to set tool voltage and zero force torque sensor (#466) (#582)
Added launch arguments for reverse ip and script command interface port. (cherry picked from commit c196eb4) Co-authored-by: Mads Holm Peters <[email protected]>
1 parent d61c268 commit 82f8a22

File tree

5 files changed

+122
-24
lines changed

5 files changed

+122
-24
lines changed

ur_controllers/include/ur_controllers/gpio_controller.hpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,19 @@ enum CommandInterfaces
6363
{
6464
DIGITAL_OUTPUTS_CMD = 0u,
6565
ANALOG_OUTPUTS_CMD = 18,
66-
IO_ASYNC_SUCCESS = 20,
67-
TARGET_SPEED_FRACTION_CMD = 21,
68-
TARGET_SPEED_FRACTION_ASYNC_SUCCESS = 22,
69-
RESEND_ROBOT_PROGRAM_CMD = 23,
70-
RESEND_ROBOT_PROGRAM_ASYNC_SUCCESS = 24,
71-
PAYLOAD_MASS = 25,
72-
PAYLOAD_COG_X = 26,
73-
PAYLOAD_COG_Y = 27,
74-
PAYLOAD_COG_Z = 28,
75-
PAYLOAD_ASYNC_SUCCESS = 29,
66+
TOOL_VOLTAGE_CMD = 20,
67+
IO_ASYNC_SUCCESS = 21,
68+
TARGET_SPEED_FRACTION_CMD = 22,
69+
TARGET_SPEED_FRACTION_ASYNC_SUCCESS = 23,
70+
RESEND_ROBOT_PROGRAM_CMD = 24,
71+
RESEND_ROBOT_PROGRAM_ASYNC_SUCCESS = 25,
72+
PAYLOAD_MASS = 26,
73+
PAYLOAD_COG_X = 27,
74+
PAYLOAD_COG_Y = 28,
75+
PAYLOAD_COG_Z = 29,
76+
PAYLOAD_ASYNC_SUCCESS = 30,
77+
ZERO_FTSENSOR_CMD = 31,
78+
ZERO_FTSENSOR_ASYNC_SUCCESS = 32,
7679
};
7780

7881
enum StateInterfaces
@@ -125,6 +128,8 @@ class GPIOController : public controller_interface::ControllerInterface
125128
bool setPayload(const ur_msgs::srv::SetPayload::Request::SharedPtr req,
126129
ur_msgs::srv::SetPayload::Response::SharedPtr resp);
127130

131+
bool zeroFTSensor(std_srvs::srv::Trigger::Request::SharedPtr req, std_srvs::srv::Trigger::Response::SharedPtr resp);
132+
128133
void publishIO();
129134

130135
void publishToolData();
@@ -150,6 +155,7 @@ class GPIOController : public controller_interface::ControllerInterface
150155
rclcpp::Service<ur_msgs::srv::SetSpeedSliderFraction>::SharedPtr set_speed_slider_srv_;
151156
rclcpp::Service<ur_msgs::srv::SetIO>::SharedPtr set_io_srv_;
152157
rclcpp::Service<ur_msgs::srv::SetPayload>::SharedPtr set_payload_srv_;
158+
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr tare_sensor_srv_;
153159

154160
std::shared_ptr<rclcpp::Publisher<ur_msgs::msg::IOStates>> io_pub_;
155161
std::shared_ptr<rclcpp::Publisher<ur_msgs::msg::ToolDataMsg>> tool_data_pub_;

ur_controllers/src/gpio_controller.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ controller_interface::InterfaceConfiguration GPIOController::command_interface_c
6161
config.names.emplace_back("gpio/standard_analog_output_cmd_" + std::to_string(i));
6262
}
6363

64+
config.names.emplace_back("gpio/tool_voltage_cmd");
65+
6466
config.names.emplace_back("gpio/io_async_success");
6567

6668
config.names.emplace_back("speed_scaling/target_speed_fraction_cmd");
@@ -78,6 +80,10 @@ controller_interface::InterfaceConfiguration GPIOController::command_interface_c
7880
config.names.emplace_back("payload/cog.z");
7981
config.names.emplace_back("payload/payload_async_success");
8082

83+
// zero ft sensor
84+
config.names.emplace_back("zero_ftsensor/zero_ftsensor_cmd");
85+
config.names.emplace_back("zero_ftsensor/zero_ftsensor_async_success");
86+
8187
return config;
8288
}
8389

@@ -274,6 +280,10 @@ ur_controllers::GPIOController::on_activate(const rclcpp_lifecycle::State& /*pre
274280

275281
set_payload_srv_ = get_node()->create_service<ur_msgs::srv::SetPayload>(
276282
"~/set_payload", std::bind(&GPIOController::setPayload, this, std::placeholders::_1, std::placeholders::_2));
283+
284+
tare_sensor_srv_ = get_node()->create_service<std_srvs::srv::Trigger>(
285+
"~/zero_ftsensor",
286+
std::bind(&GPIOController::zeroFTSensor, this, std::placeholders::_1, std::placeholders::_2));
277287
} catch (...) {
278288
return LifecycleNodeInterface::CallbackReturn::ERROR;
279289
}
@@ -326,6 +336,19 @@ bool GPIOController::setIO(ur_msgs::srv::SetIO::Request::SharedPtr req, ur_msgs:
326336
std::this_thread::sleep_for(std::chrono::milliseconds(50));
327337
}
328338

339+
resp->success = static_cast<bool>(command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].get_value());
340+
return resp->success;
341+
} else if (req->fun == req->FUN_SET_TOOL_VOLTAGE) {
342+
command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].set_value(ASYNC_WAITING);
343+
command_interfaces_[CommandInterfaces::TOOL_VOLTAGE_CMD].set_value(static_cast<double>(req->state));
344+
345+
RCLCPP_INFO(get_node()->get_logger(), "Setting tool voltage to: '%1.0f'.", req->state);
346+
347+
while (command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].get_value() == ASYNC_WAITING) {
348+
// Asynchronous wait until the hardware interface has set the io value
349+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
350+
}
351+
329352
resp->success = static_cast<bool>(command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].get_value());
330353
return resp->success;
331354
} else {
@@ -413,6 +436,31 @@ bool GPIOController::setPayload(const ur_msgs::srv::SetPayload::Request::SharedP
413436
return true;
414437
}
415438

439+
bool GPIOController::zeroFTSensor(std_srvs::srv::Trigger::Request::SharedPtr /*req*/,
440+
std_srvs::srv::Trigger::Response::SharedPtr resp)
441+
{
442+
// reset success flag
443+
command_interfaces_[CommandInterfaces::ZERO_FTSENSOR_ASYNC_SUCCESS].set_value(ASYNC_WAITING);
444+
// call the service in the hardware
445+
command_interfaces_[CommandInterfaces::ZERO_FTSENSOR_CMD].set_value(1.0);
446+
447+
while (command_interfaces_[CommandInterfaces::ZERO_FTSENSOR_ASYNC_SUCCESS].get_value() == ASYNC_WAITING) {
448+
// Asynchronous wait until the hardware interface has set the slider value
449+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
450+
}
451+
452+
resp->success = static_cast<bool>(command_interfaces_[CommandInterfaces::ZERO_FTSENSOR_ASYNC_SUCCESS].get_value());
453+
454+
if (resp->success) {
455+
RCLCPP_INFO(get_node()->get_logger(), "Successfully zeroed the force torque sensor");
456+
} else {
457+
RCLCPP_ERROR(get_node()->get_logger(), "Could not zero the force torque sensor");
458+
return false;
459+
}
460+
461+
return true;
462+
}
463+
416464
void GPIOController::initMsgs()
417465
{
418466
io_msg_.digital_in_states.resize(standard_digital_output_cmd_.size());

ur_robot_driver/include/ur_robot_driver/hardware_interface.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,14 @@ class URPositionHardwareInterface : public hardware_interface::SystemInterface
174174
// asynchronous commands
175175
std::array<double, 18> standard_dig_out_bits_cmd_;
176176
std::array<double, 2> standard_analog_output_cmd_;
177+
double tool_voltage_cmd_;
177178
double io_async_success_;
178179
double target_speed_fraction_cmd_;
179180
double scaling_async_success_;
180181
double resend_robot_program_cmd_;
181182
double resend_robot_program_async_success_;
183+
double zero_ftsensor_cmd_;
184+
double zero_ftsensor_async_success_;
182185
bool first_pass_;
183186
bool initialized_;
184187
double system_interface_initialized_;

ur_robot_driver/launch/ur_control.launch.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ def launch_setup(context, *args, **kwargs):
6969
tool_device_name = LaunchConfiguration("tool_device_name")
7070
tool_tcp_port = LaunchConfiguration("tool_tcp_port")
7171
tool_voltage = LaunchConfiguration("tool_voltage")
72+
reverse_ip = LaunchConfiguration("reverse_ip")
73+
script_command_port = LaunchConfiguration("script_command_port")
7274

7375
joint_limit_params = PathJoinSubstitution(
7476
[FindPackageShare(description_package), "config", ur_type, "joint_limits.yaml"]
@@ -173,6 +175,12 @@ def launch_setup(context, *args, **kwargs):
173175
"tool_voltage:=",
174176
tool_voltage,
175177
" ",
178+
"reverse_ip:=",
179+
reverse_ip,
180+
" ",
181+
"script_command_port:=",
182+
script_command_port,
183+
" ",
176184
]
177185
)
178186
robot_description = {"robot_description": robot_description_content}
@@ -540,5 +548,19 @@ def generate_launch_description():
540548
description="Tool voltage that will be setup.",
541549
)
542550
)
551+
declared_arguments.append(
552+
DeclareLaunchArgument(
553+
"reverse_ip",
554+
default_value="0.0.0.0",
555+
description="IP that will be used for the robot controller to communicate back to the driver.",
556+
)
557+
)
558+
declared_arguments.append(
559+
DeclareLaunchArgument(
560+
"script_command_port",
561+
default_value="50004",
562+
description="Port that will be opened to forward script commands from the driver to the robot",
563+
)
564+
)
543565

544566
return LaunchDescription(declared_arguments + [OpaqueFunction(function=launch_setup)])

ur_robot_driver/src/hardware_interface.cpp

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,14 @@ std::vector<hardware_interface::CommandInterface> URPositionHardwareInterface::e
264264
"gpio", "standard_analog_output_cmd_" + std::to_string(i), &standard_analog_output_cmd_[i]));
265265
}
266266

267+
command_interfaces.emplace_back(hardware_interface::CommandInterface("gpio", "tool_voltage_cmd", &tool_voltage_cmd_));
268+
269+
command_interfaces.emplace_back(
270+
hardware_interface::CommandInterface("zero_ftsensor", "zero_ftsensor_cmd", &zero_ftsensor_cmd_));
271+
272+
command_interfaces.emplace_back(hardware_interface::CommandInterface("zero_ftsensor", "zero_ftsensor_async_success",
273+
&zero_ftsensor_async_success_));
274+
267275
return command_interfaces;
268276
}
269277

@@ -289,6 +297,16 @@ URPositionHardwareInterface::on_activate(const rclcpp_lifecycle::State& previous
289297
int reverse_port = stoi(info_.hardware_parameters["reverse_port"]);
290298
// The driver will offer an interface to receive the program's URScript on this port.
291299
int script_sender_port = stoi(info_.hardware_parameters["script_sender_port"]);
300+
// IP that will be used for the robot controller to communicate back to the driver.
301+
std::string reverse_ip = info_.hardware_parameters["reverse_ip"];
302+
if (reverse_ip == "0.0.0.0") {
303+
reverse_ip = "";
304+
}
305+
// Port that will be opened to send trajectory points from the driver to the robot. Note: this feature hasn't been
306+
// implemented in ROS2
307+
int trajectory_port = 50003;
308+
// Port that will be opened to forward script commands from the driver to the robot
309+
int script_command_port = stoi(info_.hardware_parameters["script_command_port"]);
292310
// std::string tf_prefix = info_.hardware_parameters["tf_prefix"];
293311
// std::string tf_prefix;
294312

@@ -381,7 +399,7 @@ URPositionHardwareInterface::on_activate(const rclcpp_lifecycle::State& previous
381399
robot_ip, script_filename, output_recipe_filename, input_recipe_filename,
382400
std::bind(&URPositionHardwareInterface::handleRobotProgramState, this, std::placeholders::_1), headless_mode,
383401
std::move(tool_comm_setup), (uint32_t)reverse_port, (uint32_t)script_sender_port, servoj_gain,
384-
servoj_lookahead_time, non_blocking_read_);
402+
servoj_lookahead_time, non_blocking_read_, reverse_ip, trajectory_port, script_command_port);
385403
} catch (urcl::ToolCommNotAvailable& e) {
386404
RCLCPP_FATAL_STREAM(rclcpp::get_logger("URPositionHardwareInterface"), "See parameter use_tool_communication");
387405

@@ -541,6 +559,7 @@ hardware_interface::return_type URPositionHardwareInterface::read(const rclcpp::
541559
urcl_velocity_commands_ = { { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } };
542560
target_speed_fraction_cmd_ = NO_NEW_CMD_;
543561
resend_robot_program_cmd_ = NO_NEW_CMD_;
562+
zero_ftsensor_cmd_ = NO_NEW_CMD_;
544563
initialized_ = true;
545564
}
546565

@@ -594,6 +613,8 @@ void URPositionHardwareInterface::initAsyncIO()
594613
standard_analog_output_cmd_[i] = NO_NEW_CMD_;
595614
}
596615

616+
tool_voltage_cmd_ = NO_NEW_CMD_;
617+
597618
payload_mass_ = NO_NEW_CMD_;
598619
payload_center_of_gravity_ = { NO_NEW_CMD_, NO_NEW_CMD_, NO_NEW_CMD_ };
599620
}
@@ -623,6 +644,11 @@ void URPositionHardwareInterface::checkAsyncIO()
623644
}
624645
}
625646

647+
if (!std::isnan(tool_voltage_cmd_) && ur_driver_ != nullptr) {
648+
io_async_success_ = ur_driver_->setToolVoltage(static_cast<urcl::ToolVoltage>(tool_voltage_cmd_));
649+
tool_voltage_cmd_ = NO_NEW_CMD_;
650+
}
651+
626652
if (!std::isnan(target_speed_fraction_cmd_) && ur_driver_ != nullptr) {
627653
scaling_async_success_ = ur_driver_->getRTDEWriter().sendSpeedSlider(target_speed_fraction_cmd_);
628654
target_speed_fraction_cmd_ = NO_NEW_CMD_;
@@ -640,22 +666,15 @@ void URPositionHardwareInterface::checkAsyncIO()
640666
if (!std::isnan(payload_mass_) && !std::isnan(payload_center_of_gravity_[0]) &&
641667
!std::isnan(payload_center_of_gravity_[1]) && !std::isnan(payload_center_of_gravity_[2]) &&
642668
ur_driver_ != nullptr) {
643-
try {
644-
// create command as string from interfaces
645-
// ROS1 driver hardware_interface.cpp#L450-L456
646-
std::stringstream str_command;
647-
str_command.imbue(std::locale::classic());
648-
str_command << "sec setup():" << std::endl
649-
<< " set_payload(" << payload_mass_ << ", [" << payload_center_of_gravity_[0] << ", "
650-
<< payload_center_of_gravity_[1] << ", " << payload_center_of_gravity_[2] << "])" << std::endl
651-
<< "end";
652-
payload_async_success_ = ur_driver_->sendScript(str_command.str());
653-
} catch (const urcl::UrException& e) {
654-
RCLCPP_ERROR(rclcpp::get_logger("URPositionHardwareInterface"), "Service Call failed: '%s'", e.what());
655-
}
669+
payload_async_success_ = ur_driver_->setPayload(payload_mass_, payload_center_of_gravity_);
656670
payload_mass_ = NO_NEW_CMD_;
657671
payload_center_of_gravity_ = { NO_NEW_CMD_, NO_NEW_CMD_, NO_NEW_CMD_ };
658672
}
673+
674+
if (!std::isnan(zero_ftsensor_cmd_) && ur_driver_ != nullptr) {
675+
zero_ftsensor_async_success_ = ur_driver_->zeroFTSensor();
676+
zero_ftsensor_cmd_ = NO_NEW_CMD_;
677+
}
659678
}
660679

661680
void URPositionHardwareInterface::updateNonDoubleValues()

0 commit comments

Comments
 (0)