Skip to content

Commit 8f2dfa9

Browse files
author
Felix Exner (fexner)
authored
Allow setting the analog output domain when setting an analog IO (#1123)
1 parent fd75459 commit 8f2dfa9

File tree

6 files changed

+67
-2
lines changed

6 files changed

+67
-2
lines changed

ur_controllers/doc/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ Advertised services
129129
* ``~/resend_robot_program [std_srvs/srv/Trigger]``: When :ref:`headless_mode` is used, this
130130
service can be used to restart the *External Control* program on the robot.
131131
* ``~/set_io [ur_msgs/srv/SetIO]``: Set an output pin on the robot.
132+
* ``~/set_analog_output [ur_msgs/srv/SetAnalogOutput]``: Set an analog output on the robot. This
133+
also allows specifying the domain.
132134
* ``~/set_payload [ur_msgs/srv/SetPayload]``: Change the robot's payload on-the-fly.
133135
* ``~/set_speed_slider [ur_msgs/srv/SetSpeedSliderFraction]``: Set the value of the speed slider.
134136
* ``~/zero_ftsensor [std_srvs/srv/Trigger]``: Zeroes the reported wrench of the force torque

ur_controllers/include/ur_controllers/gpio_controller.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "ur_dashboard_msgs/msg/robot_mode.hpp"
5252
#include "ur_dashboard_msgs/msg/safety_mode.hpp"
5353
#include "ur_msgs/srv/set_io.hpp"
54+
#include "ur_msgs/srv/set_analog_output.hpp"
5455
#include "ur_msgs/srv/set_speed_slider_fraction.hpp"
5556
#include "ur_msgs/srv/set_payload.hpp"
5657
#include "rclcpp/time.hpp"
@@ -79,6 +80,7 @@ enum CommandInterfaces
7980
ZERO_FTSENSOR_ASYNC_SUCCESS = 32,
8081
HAND_BACK_CONTROL_CMD = 33,
8182
HAND_BACK_CONTROL_ASYNC_SUCCESS = 34,
83+
ANALOG_OUTPUTS_DOMAIN = 35,
8284
};
8385

8486
enum StateInterfaces
@@ -122,6 +124,9 @@ class GPIOController : public controller_interface::ControllerInterface
122124
private:
123125
bool setIO(ur_msgs::srv::SetIO::Request::SharedPtr req, ur_msgs::srv::SetIO::Response::SharedPtr resp);
124126

127+
bool setAnalogOutput(ur_msgs::srv::SetAnalogOutput::Request::SharedPtr req,
128+
ur_msgs::srv::SetAnalogOutput::Response::SharedPtr resp);
129+
125130
bool setSpeedSlider(ur_msgs::srv::SetSpeedSliderFraction::Request::SharedPtr req,
126131
ur_msgs::srv::SetSpeedSliderFraction::Response::SharedPtr resp);
127132

@@ -161,6 +166,7 @@ class GPIOController : public controller_interface::ControllerInterface
161166
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr hand_back_control_srv_;
162167
rclcpp::Service<ur_msgs::srv::SetSpeedSliderFraction>::SharedPtr set_speed_slider_srv_;
163168
rclcpp::Service<ur_msgs::srv::SetIO>::SharedPtr set_io_srv_;
169+
rclcpp::Service<ur_msgs::srv::SetAnalogOutput>::SharedPtr set_analog_output_srv_;
164170
rclcpp::Service<ur_msgs::srv::SetPayload>::SharedPtr set_payload_srv_;
165171
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr tare_sensor_srv_;
166172

ur_controllers/src/gpio_controller.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ controller_interface::InterfaceConfiguration GPIOController::command_interface_c
9797
config.names.emplace_back(tf_prefix + "hand_back_control/hand_back_control_cmd");
9898
config.names.emplace_back(tf_prefix + "hand_back_control/hand_back_control_async_success");
9999

100+
config.names.emplace_back(tf_prefix + "gpio/analog_output_domain_cmd");
101+
100102
return config;
101103
}
102104

@@ -293,6 +295,9 @@ ur_controllers::GPIOController::on_activate(const rclcpp_lifecycle::State& /*pre
293295
program_state_pub_ = get_node()->create_publisher<std_msgs::msg::Bool>("~/robot_program_running", qos_latched);
294296
set_io_srv_ = get_node()->create_service<ur_msgs::srv::SetIO>(
295297
"~/set_io", std::bind(&GPIOController::setIO, this, std::placeholders::_1, std::placeholders::_2));
298+
set_analog_output_srv_ = get_node()->create_service<ur_msgs::srv::SetAnalogOutput>(
299+
"~/set_analog_output",
300+
std::bind(&GPIOController::setAnalogOutput, this, std::placeholders::_1, std::placeholders::_2));
296301

297302
set_speed_slider_srv_ = get_node()->create_service<ur_msgs::srv::SetSpeedSliderFraction>(
298303
"~/set_speed_slider",
@@ -357,7 +362,7 @@ bool GPIOController::setIO(ur_msgs::srv::SetIO::Request::SharedPtr req, ur_msgs:
357362
command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].set_value(ASYNC_WAITING);
358363
command_interfaces_[CommandInterfaces::ANALOG_OUTPUTS_CMD + req->pin].set_value(static_cast<double>(req->state));
359364

360-
RCLCPP_INFO(get_node()->get_logger(), "Setting analog output '%d' to state: '%1.0f'.", req->pin, req->state);
365+
RCLCPP_INFO(get_node()->get_logger(), "Setting analog output '%d' to state: '%f'.", req->pin, req->state);
361366

362367
if (!waitForAsyncCommand([&]() { return command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].get_value(); })) {
363368
RCLCPP_WARN(get_node()->get_logger(), "Could not verify that io was set. (This might happen when using the "
@@ -385,6 +390,46 @@ bool GPIOController::setIO(ur_msgs::srv::SetIO::Request::SharedPtr req, ur_msgs:
385390
}
386391
}
387392

393+
bool GPIOController::setAnalogOutput(ur_msgs::srv::SetAnalogOutput::Request::SharedPtr req,
394+
ur_msgs::srv::SetAnalogOutput::Response::SharedPtr resp)
395+
{
396+
std::string domain_string = "UNKNOWN";
397+
switch (req->data.domain) {
398+
case ur_msgs::msg::Analog::CURRENT:
399+
domain_string = "CURRENT";
400+
break;
401+
case ur_msgs::msg::Analog::VOLTAGE:
402+
domain_string = "VOLTAGE";
403+
break;
404+
default:
405+
RCLCPP_ERROR(get_node()->get_logger(), "Domain must be either 0 (CURRENT) or 1 (VOLTAGE)");
406+
resp->success = false;
407+
return false;
408+
}
409+
410+
if (req->data.pin < 0 || req->data.pin > 1) {
411+
RCLCPP_ERROR(get_node()->get_logger(), "Invalid pin selected. Only pins 0 and 1 are allowed.");
412+
resp->success = false;
413+
return false;
414+
}
415+
416+
command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].set_value(ASYNC_WAITING);
417+
command_interfaces_[CommandInterfaces::ANALOG_OUTPUTS_CMD + req->data.pin].set_value(
418+
static_cast<float>(req->data.state));
419+
command_interfaces_[CommandInterfaces::ANALOG_OUTPUTS_DOMAIN].set_value(static_cast<double>(req->data.domain));
420+
421+
RCLCPP_INFO(get_node()->get_logger(), "Setting analog output '%d' to state: '%f' in domain %s.", req->data.pin,
422+
req->data.state, domain_string.c_str());
423+
424+
if (!waitForAsyncCommand([&]() { return command_interfaces_[CommandInterfaces::IO_ASYNC_SUCCESS].get_value(); })) {
425+
RCLCPP_WARN(get_node()->get_logger(), "Could not verify that io was set. (This might happen when using the "
426+
"mocked interface)");
427+
}
428+
429+
resp->success = static_cast<bool>(command_interfaces_[IO_ASYNC_SUCCESS].get_value());
430+
return resp->success;
431+
}
432+
388433
bool GPIOController::setSpeedSlider(ur_msgs::srv::SetSpeedSliderFraction::Request::SharedPtr req,
389434
ur_msgs::srv::SetSpeedSliderFraction::Response::SharedPtr resp)
390435
{

ur_robot_driver/include/ur_robot_driver/hardware_interface.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class URPositionHardwareInterface : public hardware_interface::SystemInterface
177177
// asynchronous commands
178178
std::array<double, 18> standard_dig_out_bits_cmd_;
179179
std::array<double, 2> standard_analog_output_cmd_;
180+
double analog_output_domain_cmd_;
180181
double tool_voltage_cmd_;
181182
double io_async_success_;
182183
double target_speed_fraction_cmd_;

ur_robot_driver/src/hardware_interface.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ std::vector<hardware_interface::CommandInterface> URPositionHardwareInterface::e
310310
command_interfaces.emplace_back(hardware_interface::CommandInterface(
311311
tf_prefix + "gpio", "standard_analog_output_cmd_" + std::to_string(i), &standard_analog_output_cmd_[i]));
312312
}
313+
command_interfaces.emplace_back(
314+
hardware_interface::CommandInterface(tf_prefix + "gpio", "analog_output_domain_cmd", &analog_output_domain_cmd_));
313315

314316
command_interfaces.emplace_back(
315317
hardware_interface::CommandInterface(tf_prefix + "gpio", "tool_voltage_cmd", &tool_voltage_cmd_));
@@ -685,6 +687,8 @@ void URPositionHardwareInterface::initAsyncIO()
685687
standard_analog_output_cmd_[i] = NO_NEW_CMD_;
686688
}
687689

690+
analog_output_domain_cmd_ = NO_NEW_CMD_;
691+
688692
tool_voltage_cmd_ = NO_NEW_CMD_;
689693

690694
payload_mass_ = NO_NEW_CMD_;
@@ -714,7 +718,13 @@ void URPositionHardwareInterface::checkAsyncIO()
714718

715719
for (size_t i = 0; i < 2; ++i) {
716720
if (!std::isnan(standard_analog_output_cmd_[i]) && ur_driver_ != nullptr) {
717-
io_async_success_ = ur_driver_->getRTDEWriter().sendStandardAnalogOutput(i, standard_analog_output_cmd_[i]);
721+
urcl::AnalogOutputType domain = urcl::AnalogOutputType::SET_ON_TEACH_PENDANT;
722+
if (!std::isnan(analog_output_domain_cmd_) && ur_driver_ != nullptr) {
723+
domain = static_cast<urcl::AnalogOutputType>(analog_output_domain_cmd_);
724+
analog_output_domain_cmd_ = NO_NEW_CMD_;
725+
}
726+
io_async_success_ =
727+
ur_driver_->getRTDEWriter().sendStandardAnalogOutput(i, standard_analog_output_cmd_[i], domain);
718728
standard_analog_output_cmd_[i] = NO_NEW_CMD_;
719729
}
720730
}

ur_robot_driver/urdf/ur.ros2_control.xacro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114

115115
<command_interface name="standard_analog_output_cmd_0"/>
116116
<command_interface name="standard_analog_output_cmd_1"/>
117+
<command_interface name="analog_output_domain_cmd"/>
117118

118119
<command_interface name="tool_voltage_cmd"/>
119120

0 commit comments

Comments
 (0)