Skip to content

Commit e7f1e41

Browse files
committed
srdf_publisher_node
1 parent 47ce660 commit e7f1e41

File tree

5 files changed

+197
-0
lines changed

5 files changed

+197
-0
lines changed

moveit_ros/planning/CMakeLists.txt

+10
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ find_package(moveit_msgs REQUIRED)
1616
find_package(moveit_ros_occupancy_map_monitor REQUIRED)
1717
find_package(pluginlib REQUIRED)
1818
find_package(rclcpp REQUIRED)
19+
find_package(rclcpp_components REQUIRED)
1920
find_package(srdfdom REQUIRED)
21+
find_package(std_msgs REQUIRED)
2022
find_package(tf2 REQUIRED)
2123
find_package(tf2_eigen REQUIRED)
2224
find_package(tf2_geometry_msgs REQUIRED)
@@ -59,6 +61,7 @@ set(THIS_PACKAGE_LIBRARIES
5961
moveit_robot_model_loader
6062
moveit_trajectory_execution_manager
6163
planning_pipeline_parameters
64+
srdf_publisher_node
6265
)
6366

6467
set(THIS_PACKAGE_INCLUDE_DEPENDS
@@ -70,7 +73,9 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS
7073
moveit_ros_occupancy_map_monitor
7174
pluginlib
7275
rclcpp
76+
rclcpp_components
7377
srdfdom
78+
std_msgs
7479
tf2
7580
tf2_eigen
7681
tf2_geometry_msgs
@@ -97,6 +102,7 @@ add_subdirectory(planning_response_adapter_plugins)
97102
add_subdirectory(planning_scene_monitor)
98103
add_subdirectory(rdf_loader)
99104
add_subdirectory(robot_model_loader)
105+
add_subdirectory(srdf_publisher_node)
100106
add_subdirectory(trajectory_execution_manager)
101107

102108
install(
@@ -111,6 +117,10 @@ install(
111117
ament_export_targets(moveit_ros_planningTargets HAS_LIBRARY_TARGET)
112118
ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS})
113119

120+
rclcpp_components_register_node(srdf_publisher_node
121+
PLUGIN "moveit_ros_planning::SrdfPublisher"
122+
EXECUTABLE srdf_publisher)
123+
114124
pluginlib_export_plugin_description_file(moveit_core "default_request_adapters_plugin_description.xml")
115125
pluginlib_export_plugin_description_file(moveit_core "default_response_adapters_plugin_description.xml")
116126
if(BUILD_TESTING)

moveit_ros/planning/package.xml

+2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@
3434
<depend>moveit_msgs</depend>
3535
<depend>moveit_ros_occupancy_map_monitor</depend>
3636
<depend>rclcpp_action</depend>
37+
<depend>rclcpp_components</depend>
3738
<depend>rclcpp</depend>
3839
<depend>srdfdom</depend>
40+
<depend>std_msgs</depend>
3941
<depend>tf2_eigen</depend>
4042
<depend>tf2_geometry_msgs</depend>
4143
<depend>tf2_msgs</depend>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
add_library(srdf_publisher_node SHARED src/srdf_publisher_node.cpp)
2+
ament_target_dependencies(srdf_publisher_node PUBLIC
3+
std_msgs
4+
rclcpp
5+
rclcpp_components
6+
)
7+
8+
if(BUILD_TESTING)
9+
find_package(launch_testing_ament_cmake)
10+
11+
add_launch_test(test/srdf_publisher_test.py
12+
TARGET test-srdf_publisher
13+
)
14+
endif()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include <rclcpp/rclcpp.hpp>
2+
#include <std_msgs/msg/string.hpp>
3+
4+
#include <string>
5+
6+
namespace moveit_ros_planning
7+
{
8+
9+
class SrdfPublisher : public rclcpp::Node
10+
{
11+
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr srdf_publisher_;
12+
rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr on_set_parameters_handle_;
13+
14+
public:
15+
SrdfPublisher(const rclcpp::NodeOptions& options) : rclcpp::Node("srdf_publisher", options)
16+
{
17+
srdf_publisher_ = this->create_publisher<std_msgs::msg::String>("robot_description_semantic",
18+
rclcpp::QoS(1).transient_local().reliable());
19+
on_set_parameters_handle_ =
20+
this->add_on_set_parameters_callback([this](const std::vector<rclcpp::Parameter>& parameters) {
21+
for (auto const& parameter : parameters)
22+
{
23+
if (parameter.get_name() == "robot_description_semantic")
24+
{
25+
std_msgs::msg::String msg;
26+
msg.data = parameter.get_value<std::string>();
27+
srdf_publisher_->publish(msg);
28+
}
29+
}
30+
31+
rcl_interfaces::msg::SetParametersResult result;
32+
result.successful = true;
33+
return result;
34+
});
35+
36+
rcl_interfaces::msg::ParameterDescriptor descriptor;
37+
descriptor.type = rcl_interfaces::msg::ParameterType::PARAMETER_STRING;
38+
descriptor.description = "Semantic Robot Description Format";
39+
this->declare_parameter("robot_description_semantic", rclcpp::ParameterType::PARAMETER_STRING, descriptor);
40+
}
41+
};
42+
43+
} // namespace moveit_ros_planning
44+
45+
#include "rclcpp_components/register_node_macro.hpp"
46+
RCLCPP_COMPONENTS_REGISTER_NODE(moveit_ros_planning::SrdfPublisher)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Software License Agreement (BSD License)
2+
#
3+
# Copyright (c) 2024, PickNik Robotics Inc.
4+
# All rights reserved.
5+
#
6+
# Redistribution and use in source and binary forms, with or without
7+
# modification, are permitted provided that the following conditions
8+
# are met:
9+
#
10+
# # Redistributions of source code must retain the above copyright
11+
# notice, this list of conditions and the following disclaimer.
12+
# # Redistributions in binary form must reproduce the above
13+
# copyright notice, this list of conditions and the following
14+
# disclaimer in the documentation and/or other materials provided
15+
# with the distribution.
16+
# # Neither the name of Willow Garage nor the names of its
17+
# contributors may be used to endorse or promote products derived
18+
# from this software without specific prior written permission.
19+
#
20+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23+
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24+
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30+
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31+
# POSSIBILITY OF SUCH DAMAGE.
32+
33+
# Author: Tyler Weaver
34+
35+
import unittest
36+
from threading import Event
37+
from threading import Thread
38+
39+
import launch
40+
import launch_ros
41+
import launch_testing
42+
import rclpy
43+
from rclpy.node import Node
44+
from rclpy.qos import (
45+
QoSProfile,
46+
QoSReliabilityPolicy,
47+
QoSDurabilityPolicy,
48+
)
49+
from std_msgs.msg import String
50+
51+
import pytest
52+
53+
54+
@pytest.mark.launch_test
55+
def generate_test_description():
56+
# dut: device under test
57+
srdf_publisher = launch_ros.actions.Node(
58+
package="moveit_ros_planning",
59+
parameters=[{"robot_description_semantic": "test value"}],
60+
executable="srdf_publisher",
61+
output="screen",
62+
)
63+
64+
return launch.LaunchDescription(
65+
[
66+
srdf_publisher,
67+
# Start tests right away - no need to wait for anything
68+
launch_testing.actions.ReadyToTest(),
69+
]
70+
), {"srdf_publisher": srdf_publisher}
71+
72+
73+
class SrdfObserverNode(Node):
74+
def __init__(self, name="srdf_observer_node"):
75+
super().__init__(name)
76+
self.msg_event_object = Event()
77+
self.srdf = ""
78+
79+
def start_subscriber(self):
80+
# Create a subscriber
81+
self.subscription = self.create_subscription(
82+
String,
83+
"robot_description_semantic",
84+
self.subscriber_callback,
85+
qos_profile=QoSProfile(
86+
reliability=QoSReliabilityPolicy.RELIABLE,
87+
durability=QoSDurabilityPolicy.TRANSIENT_LOCAL,
88+
depth=1,
89+
),
90+
)
91+
92+
# Add a spin thread
93+
self.ros_spin_thread = Thread(
94+
target=lambda node: rclpy.spin(node), args=(self,)
95+
)
96+
self.ros_spin_thread.start()
97+
98+
def subscriber_callback(self, msg):
99+
self.srdf = msg.data
100+
self.msg_event_object.set()
101+
102+
103+
# These tests will run concurrently with the dut process. After all these tests are done,
104+
# the launch system will shut down the processes that it started up
105+
class TestFixture(unittest.TestCase):
106+
def test_rosout_msgs_published(self, proc_output):
107+
rclpy.init()
108+
try:
109+
node = SrdfObserverNode()
110+
node.start_subscriber()
111+
msgs_received_flag = node.msg_event_object.wait(timeout=5.0)
112+
assert (
113+
msgs_received_flag
114+
), "Did not receive message on `/robot_description_semantic`!"
115+
assert node.srdf == "test value"
116+
finally:
117+
rclpy.shutdown()
118+
119+
120+
@launch_testing.post_shutdown_test()
121+
class TestProcessOutput(unittest.TestCase):
122+
def test_exit_code(self, proc_info):
123+
# Check that all processes in the launch (in this case, there's just one) exit
124+
# with code 0
125+
launch_testing.asserts.assertExitCodes(proc_info)

0 commit comments

Comments
 (0)