Skip to content

Commit d1290a7

Browse files
authored
Service to get software version of robot (#964)
* Implemented get_version service * Implemented test of get_version service and integrated it with the test of tool contact * Update ur_robot_driver/test/test_common.py Co-authored-by: Felix Exner (fexner) <[email protected]> * Renamed service to "GetRobotSoftwareVersion" everywhere. Also moved the version information from being stored in the command interface to be stored in the state interface * Remove tool contact from test. * Implemented test of get_version service and integrated it with the test of tool contact * Renamed service to "GetRobotSoftwareVersion" everywhere. Also moved the version information from being stored in the command interface to be stored in the state interface * Remove tool contact from test. * Create new URConfigurationController And moved the get_robot_software_version service in to it. * Make configuration controller thread safe Also minor cleanup and add testing of the robot software version service * Use ptr-safe RealTimeBoxBestEffort the RealTimeBox used before is not really real-time safe and the way it was implemented there was unnecessary data allocation in both, the activate method and the service callback. Using the RealTimeBoxBestEffort makes allocating additional memory unnecessary and makes things really thread-safe. * Added back files that were mistakenly deleted
1 parent 3068607 commit d1290a7

File tree

11 files changed

+304
-3
lines changed

11 files changed

+304
-3
lines changed

ur_controllers/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,16 @@ generate_parameter_library(
5454
src/scaled_joint_trajectory_controller_parameters.yaml
5555
)
5656

57+
generate_parameter_library(
58+
ur_configuration_controller_parameters
59+
src/ur_configuration_controller_parameters.yaml
60+
)
61+
5762
add_library(${PROJECT_NAME} SHARED
5863
src/scaled_joint_trajectory_controller.cpp
5964
src/speed_scaling_state_broadcaster.cpp
60-
src/gpio_controller.cpp)
65+
src/gpio_controller.cpp
66+
src/ur_configuration_controller.cpp)
6167

6268
target_include_directories(${PROJECT_NAME} PRIVATE
6369
include
@@ -66,6 +72,7 @@ target_link_libraries(${PROJECT_NAME}
6672
gpio_controller_parameters
6773
speed_scaling_state_broadcaster_parameters
6874
scaled_joint_trajectory_controller_parameters
75+
ur_configuration_controller_parameters
6976
)
7077
ament_target_dependencies(${PROJECT_NAME}
7178
${THIS_PACKAGE_INCLUDE_DEPENDS}

ur_controllers/controller_plugins.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@
1414
This controller publishes the Tool IO.
1515
</description>
1616
</class>
17+
<class name="ur_controllers/URConfigurationController" type="ur_controllers::URConfigurationController" base_class_type="controller_interface::ControllerInterface">
18+
<description>
19+
Controller used to get and change the configuration of the robot
20+
</description>
21+
</class>
1722
</library>
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// Copyright 2024, Universal Robots A/S
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are met:
5+
//
6+
// * Redistributions of source code must retain the above copyright
7+
// notice, this list of conditions and the following disclaimer.
8+
//
9+
// * Redistributions in binary form must reproduce the above copyright
10+
// notice, this list of conditions and the following disclaimer in the
11+
// documentation and/or other materials provided with the distribution.
12+
//
13+
// * Neither the name of the {copyright_holder} nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
// POSSIBILITY OF SUCH DAMAGE.
28+
29+
//----------------------------------------------------------------------
30+
/*!\file
31+
*
32+
* \author Jacob Larsen [email protected]
33+
* \date 2024-07-11
34+
*
35+
*
36+
*
37+
*
38+
*/
39+
//----------------------------------------------------------------------
40+
41+
#ifndef UR_CONTROLLERS__UR_CONFIGURATION_CONTROLLER_HPP_
42+
#define UR_CONTROLLERS__UR_CONFIGURATION_CONTROLLER_HPP_
43+
44+
// TODO(fmauch): Currently, the realtime_box_best_effort doesn't include this
45+
#include <functional>
46+
#include <realtime_tools/realtime_box_best_effort.h> // NOLINT
47+
48+
#include <memory>
49+
50+
#include <controller_interface/controller_interface.hpp>
51+
52+
#include "ur_msgs/srv/get_robot_software_version.hpp"
53+
#include "ur_configuration_controller_parameters.hpp"
54+
55+
namespace ur_controllers
56+
{
57+
58+
// Struct to hold version information
59+
struct VersionInformation
60+
{
61+
uint32_t major = 0, minor = 0, build = 0, bugfix = 0;
62+
};
63+
64+
// Enum for indexing into state interfaces.
65+
enum StateInterfaces
66+
{
67+
ROBOT_VERSION_MAJOR = 0,
68+
ROBOT_VERSION_MINOR = 1,
69+
ROBOT_VERSION_BUILD = 2,
70+
ROBOT_VERSION_BUGFIX = 3,
71+
};
72+
73+
class URConfigurationController : public controller_interface::ControllerInterface
74+
{
75+
public:
76+
controller_interface::InterfaceConfiguration command_interface_configuration() const override;
77+
78+
controller_interface::InterfaceConfiguration state_interface_configuration() const override;
79+
80+
controller_interface::return_type update(const rclcpp::Time& time, const rclcpp::Duration& period) override;
81+
82+
CallbackReturn on_configure(const rclcpp_lifecycle::State& previous_state) override;
83+
84+
CallbackReturn on_activate(const rclcpp_lifecycle::State& previous_state) override;
85+
86+
CallbackReturn on_deactivate(const rclcpp_lifecycle::State& previous_state) override;
87+
88+
CallbackReturn on_init() override;
89+
90+
private:
91+
realtime_tools::RealtimeBoxBestEffort<std::shared_ptr<VersionInformation>> robot_software_version_{
92+
std::make_shared<VersionInformation>()
93+
};
94+
95+
rclcpp::Service<ur_msgs::srv::GetRobotSoftwareVersion>::SharedPtr get_robot_software_version_srv_;
96+
97+
bool getRobotSoftwareVersion(ur_msgs::srv::GetRobotSoftwareVersion::Request::SharedPtr req,
98+
ur_msgs::srv::GetRobotSoftwareVersion::Response::SharedPtr resp);
99+
100+
std::shared_ptr<ur_configuration_controller::ParamListener> param_listener_;
101+
ur_configuration_controller::Params params_;
102+
};
103+
} // namespace ur_controllers
104+
105+
#endif // UR_CONTROLLERS__UR_CONFIGURATION_CONTROLLER_HPP_
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright 2024, Universal Robots A/S
2+
//
3+
// Redistribution and use in source and binary forms, with or without
4+
// modification, are permitted provided that the following conditions are met:
5+
//
6+
// * Redistributions of source code must retain the above copyright
7+
// notice, this list of conditions and the following disclaimer.
8+
//
9+
// * Redistributions in binary form must reproduce the above copyright
10+
// notice, this list of conditions and the following disclaimer in the
11+
// documentation and/or other materials provided with the distribution.
12+
//
13+
// * Neither the name of the {copyright_holder} nor the names of its
14+
// contributors may be used to endorse or promote products derived from
15+
// this software without specific prior written permission.
16+
//
17+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
// POSSIBILITY OF SUCH DAMAGE.
28+
29+
//----------------------------------------------------------------------
30+
/*!\file
31+
*
32+
* \author Jacob Larsen [email protected]
33+
* \date 2024-07-11
34+
*
35+
*
36+
*
37+
*
38+
*/
39+
//----------------------------------------------------------------------
40+
41+
#include <ur_controllers/ur_configuration_controller.hpp>
42+
#include <realtime_tools/realtime_box.h>
43+
namespace ur_controllers
44+
{
45+
46+
controller_interface::CallbackReturn URConfigurationController::on_init()
47+
{
48+
return controller_interface::CallbackReturn::SUCCESS;
49+
}
50+
51+
controller_interface::CallbackReturn
52+
URConfigurationController::on_configure(const rclcpp_lifecycle::State& /* previous_state */)
53+
{
54+
param_listener_ = std::make_shared<ur_configuration_controller::ParamListener>(get_node());
55+
params_ = param_listener_->get_params();
56+
57+
get_robot_software_version_srv_ = get_node()->create_service<ur_msgs::srv::GetRobotSoftwareVersion>(
58+
"~/get_robot_software_version", std::bind(&URConfigurationController::getRobotSoftwareVersion, this,
59+
std::placeholders::_1, std::placeholders::_2));
60+
61+
return controller_interface::CallbackReturn::SUCCESS;
62+
}
63+
64+
controller_interface::InterfaceConfiguration URConfigurationController::command_interface_configuration() const
65+
{
66+
// No command interfaces currently
67+
controller_interface::InterfaceConfiguration config;
68+
config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
69+
70+
return config;
71+
}
72+
73+
controller_interface::InterfaceConfiguration URConfigurationController::state_interface_configuration() const
74+
{
75+
controller_interface::InterfaceConfiguration config;
76+
config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
77+
78+
const std::string tf_prefix = params_.tf_prefix;
79+
80+
config.names.emplace_back(tf_prefix + "get_robot_software_version/get_version_major");
81+
config.names.emplace_back(tf_prefix + "get_robot_software_version/get_version_minor");
82+
config.names.emplace_back(tf_prefix + "get_robot_software_version/get_version_build");
83+
config.names.emplace_back(tf_prefix + "get_robot_software_version/get_version_bugfix");
84+
85+
return config;
86+
}
87+
88+
controller_interface::return_type URConfigurationController::update(const rclcpp::Time& /* time */,
89+
const rclcpp::Duration& /* period */)
90+
{
91+
return controller_interface::return_type::OK;
92+
}
93+
94+
controller_interface::CallbackReturn
95+
URConfigurationController::on_activate(const rclcpp_lifecycle::State& /* previous_state */)
96+
{
97+
robot_software_version_.set([this](const std::shared_ptr<VersionInformation> ptr) {
98+
ptr->major = state_interfaces_[StateInterfaces::ROBOT_VERSION_MAJOR].get_value();
99+
ptr->minor = state_interfaces_[StateInterfaces::ROBOT_VERSION_MINOR].get_value();
100+
ptr->build = state_interfaces_[StateInterfaces::ROBOT_VERSION_BUILD].get_value();
101+
ptr->bugfix = state_interfaces_[StateInterfaces::ROBOT_VERSION_BUGFIX].get_value();
102+
});
103+
return controller_interface::CallbackReturn::SUCCESS;
104+
}
105+
106+
controller_interface::CallbackReturn
107+
URConfigurationController::on_deactivate(const rclcpp_lifecycle::State& /* previous_state */)
108+
{
109+
return controller_interface::CallbackReturn::SUCCESS;
110+
}
111+
112+
bool URConfigurationController::getRobotSoftwareVersion(
113+
ur_msgs::srv::GetRobotSoftwareVersion::Request::SharedPtr /*req*/,
114+
ur_msgs::srv::GetRobotSoftwareVersion::Response::SharedPtr resp)
115+
{
116+
std::shared_ptr<VersionInformation> temp;
117+
return robot_software_version_.tryGet([resp](const std::shared_ptr<VersionInformation> ptr) {
118+
resp->major = ptr->major;
119+
resp->minor = ptr->minor;
120+
resp->build = ptr->build;
121+
resp->bugfix = ptr->bugfix;
122+
});
123+
}
124+
} // namespace ur_controllers
125+
126+
#include "pluginlib/class_list_macros.hpp"
127+
128+
PLUGINLIB_EXPORT_CLASS(ur_controllers::URConfigurationController, controller_interface::ControllerInterface)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
ur_configuration_controller:
2+
tf_prefix: {
3+
type: string,
4+
default_value: "",
5+
description: "URDF prefix of the corresponding arm"
6+
}

ur_robot_driver/config/ur_controllers.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ controller_manager:
2424
forward_position_controller:
2525
type: position_controllers/JointGroupPositionController
2626

27+
ur_configuration_controller:
28+
type: ur_controllers/URConfigurationController
2729

2830
speed_scaling_state_broadcaster:
2931
ros__parameters:
@@ -34,6 +36,10 @@ io_and_status_controller:
3436
ros__parameters:
3537
tf_prefix: "$(var tf_prefix)"
3638

39+
ur_configuration_controller:
40+
ros__parameters:
41+
tf_prefix: "$(var tf_prefix)"
42+
3743
force_torque_sensor_broadcaster:
3844
ros__parameters:
3945
sensor_name: $(var tf_prefix)tcp_fts_sensor

ur_robot_driver/include/ur_robot_driver/hardware_interface.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ class URPositionHardwareInterface : public hardware_interface::SystemInterface
191191
bool initialized_;
192192
double system_interface_initialized_;
193193
bool async_thread_shutdown_;
194+
double get_robot_software_version_major_;
195+
double get_robot_software_version_minor_;
196+
double get_robot_software_version_bugfix_;
197+
double get_robot_software_version_build_;
194198

195199
// Passthrough trajectory controller interface values
196200
urcl::vector6d_t passthrough_trajectory_positions_;

ur_robot_driver/launch/ur_control.launch.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ def launch_setup(context):
130130
"force_torque_sensor_broadcaster",
131131
"joint_state_broadcaster",
132132
"speed_scaling_state_broadcaster",
133+
"ur_configuration_controller",
133134
]
134135
},
135136
],
@@ -165,6 +166,7 @@ def controller_spawner(controllers, active=True):
165166
"io_and_status_controller",
166167
"speed_scaling_state_broadcaster",
167168
"force_torque_sensor_broadcaster",
169+
"ur_configuration_controller",
168170
]
169171
controllers_inactive = [
170172
"scaled_joint_trajectory_controller",

ur_robot_driver/src/hardware_interface.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444

4545
#include "ur_client_library/exceptions.h"
4646
#include "ur_client_library/ur/tool_communication.h"
47+
#include "ur_client_library/ur/version_information.h"
4748

4849
#include "rclcpp/rclcpp.hpp"
4950
#include "hardware_interface/types/hardware_interface_type_values.hpp"
@@ -231,6 +232,18 @@ std::vector<hardware_interface::StateInterface> URPositionHardwareInterface::exp
231232
state_interfaces.emplace_back(
232233
hardware_interface::StateInterface(tf_prefix + "gpio", "program_running", &robot_program_running_copy_));
233234

235+
state_interfaces.emplace_back(hardware_interface::StateInterface(
236+
tf_prefix + "get_robot_software_version", "get_version_major", &get_robot_software_version_major_));
237+
238+
state_interfaces.emplace_back(hardware_interface::StateInterface(
239+
tf_prefix + "get_robot_software_version", "get_version_minor", &get_robot_software_version_minor_));
240+
241+
state_interfaces.emplace_back(hardware_interface::StateInterface(
242+
tf_prefix + "get_robot_software_version", "get_version_bugfix", &get_robot_software_version_bugfix_));
243+
244+
state_interfaces.emplace_back(hardware_interface::StateInterface(
245+
tf_prefix + "get_robot_software_version", "get_version_build", &get_robot_software_version_build_));
246+
234247
return state_interfaces;
235248
}
236249

@@ -463,6 +476,13 @@ URPositionHardwareInterface::on_configure(const rclcpp_lifecycle::State& previou
463476
"README.md] for details.");
464477
}
465478

479+
// Export version information to state interfaces
480+
urcl::VersionInformation version_info = ur_driver_->getVersion();
481+
get_robot_software_version_major_ = version_info.major;
482+
get_robot_software_version_minor_ = version_info.minor;
483+
get_robot_software_version_build_ = version_info.build;
484+
get_robot_software_version_bugfix_ = version_info.bugfix;
485+
466486
async_thread_ = std::make_shared<std::thread>(&URPositionHardwareInterface::asyncThread, this);
467487

468488
RCLCPP_INFO(rclcpp::get_logger("URPositionHardwareInterface"), "System successfully started!");

ur_robot_driver/test/robot_driver.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
ControllerManagerInterface,
5050
DashboardInterface,
5151
IoStatusInterface,
52+
ConfigurationInterface,
5253
generate_driver_test_description,
5354
)
5455

@@ -92,6 +93,7 @@ def init_robot(self):
9293
self._dashboard_interface = DashboardInterface(self.node)
9394
self._controller_manager_interface = ControllerManagerInterface(self.node)
9495
self._io_status_controller_interface = IoStatusInterface(self.node)
96+
self._configuration_controller_interface = ConfigurationInterface(self.node)
9597

9698
self._scaled_follow_joint_trajectory = ActionInterface(
9799
self.node,
@@ -108,6 +110,11 @@ def setUp(self):
108110
# Test functions
109111
#
110112

113+
def test_get_robot_software_version(self):
114+
self.assertNotEqual(
115+
self._configuration_controller_interface.get_robot_software_version().major, 0
116+
)
117+
111118
def test_start_scaled_jtc_controller(self):
112119
self.assertTrue(
113120
self._controller_manager_interface.switch_controller(

0 commit comments

Comments
 (0)