Skip to content

Commit b2ee7d5

Browse files
authored
add recognition publisher and message (#200)
* add recognition publisher and message * fix checking both subscription count and publish
1 parent 076540a commit b2ee7d5

File tree

6 files changed

+126
-9
lines changed

6 files changed

+126
-9
lines changed

webots_ros2_core/package.xml

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

1414
<exec_depend>rclpy</exec_depend>
1515
<exec_depend>std_msgs</exec_depend>
16+
<exec_depend>vision_msgs</exec_depend>
1617
<exec_depend>builtin_interfaces</exec_depend>
1718
<exec_depend>webots_ros2_msgs</exec_depend>
1819
<exec_depend>python3-tk</exec_depend>

webots_ros2_core/webots_ros2_core/devices/camera_device.py

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@
1515
"""Camera device."""
1616

1717
from sensor_msgs.msg import Image, CameraInfo
18+
from vision_msgs.msg import Detection2D, Detection2DArray, ObjectHypothesisWithPose
19+
from geometry_msgs.msg import Point, Quaternion
20+
from std_msgs.msg import ColorRGBA
21+
from webots_ros2_msgs.msg import WbCameraRecognitionObject, WbCameraRecognitionObjects
1822
from rclpy.time import Time
1923
from rclpy.qos import DurabilityPolicy, HistoryPolicy, QoSProfile, QoSReliabilityPolicy, qos_profile_sensor_data
2024
from .sensor_device import SensorDevice
25+
from webots_ros2_core.math.quaternions import axangle2quat
2126

2227

2328
class CameraDevice(SensorDevice):
@@ -43,6 +48,8 @@ class CameraDevice(SensorDevice):
4348
def __init__(self, node, device_key, wb_device, params=None):
4449
super().__init__(node, device_key, wb_device, params)
4550
self._camera_info_publisher = None
51+
self._recognition_publisher = None
52+
self._recognition_webots_publisher = None
4653
self._image_publisher = None
4754

4855
# Create topics
@@ -62,18 +69,31 @@ def __init__(self, node, device_key, wb_device, params=None):
6269
history=HistoryPolicy.KEEP_LAST,
6370
)
6471
)
72+
if self._wb_device.hasRecognition():
73+
self._recognition_publisher = self._node.create_publisher(
74+
Detection2DArray,
75+
self._topic_name + '/recognitions',
76+
qos_profile_sensor_data
77+
)
78+
self._recognition_webots_publisher = self._node.create_publisher(
79+
WbCameraRecognitionObjects,
80+
self._topic_name + '/recognitions/webots',
81+
qos_profile_sensor_data
82+
)
6583

6684
# CameraInfo data
6785
self.__message_info = CameraInfo()
68-
self.__message_info.header.stamp = Time(seconds=self._node.robot.getTime()).to_msg()
86+
self.__message_info.header.stamp = Time(
87+
seconds=self._node.robot.getTime()).to_msg()
6988
self.__message_info.height = self._wb_device.getHeight()
7089
self.__message_info.width = self._wb_device.getWidth()
7190
self.__message_info.distortion_model = 'plumb_bob'
7291
focal_length = self._wb_device.getFocalLength()
7392
if focal_length == 0:
7493
focal_length = 570.34 # Identical to Orbbec Astra
7594
self.__message_info.d = [0.0, 0.0, 0.0, 0.0, 0.0]
76-
self.__message_info.r = [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
95+
self.__message_info.r = [
96+
1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
7797
self.__message_info.k = [
7898
focal_length, 0.0, self._wb_device.getWidth() / 2,
7999
0.0, focal_length, self._wb_device.getHeight() / 2,
@@ -87,7 +107,8 @@ def __init__(self, node, device_key, wb_device, params=None):
87107
self._camera_info_publisher.publish(self.__message_info)
88108

89109
# Load parameters
90-
camera_period_param = node.declare_parameter(wb_device.getName() + '_period', self._timestep)
110+
camera_period_param = node.declare_parameter(
111+
wb_device.getName() + '_period', self._timestep)
91112
self._camera_period = camera_period_param.value
92113

93114
def step(self):
@@ -119,7 +140,78 @@ def step(self):
119140
msg.encoding = 'bgra8'
120141
self._image_publisher.publish(msg)
121142

122-
self.__message_info.header.stamp = Time(seconds=self._node.robot.getTime()).to_msg()
143+
self.__message_info.header.stamp = Time(
144+
seconds=self._node.robot.getTime()).to_msg()
123145
self._camera_info_publisher.publish(self.__message_info)
146+
147+
if self._wb_device.hasRecognition() and (
148+
self._recognition_publisher.get_subscription_count() > 0 or
149+
self._recognition_webots_publisher.get_subscription_count() > 0):
150+
self._wb_device.recognitionEnable(self._timestep)
151+
objects = self._wb_device.getRecognitionObjects()
152+
153+
if objects is None:
154+
return
155+
156+
# Recognition data
157+
reco_msg = Detection2DArray()
158+
reco_msg_webots = WbCameraRecognitionObjects()
159+
reco_msg.header.stamp = stamp
160+
reco_msg_webots.header.stamp = stamp
161+
reco_msg.header.frame_id = self._frame_id
162+
reco_msg_webots.header.frame_id = self._frame_id
163+
for obj in objects:
164+
# Getting Object Info
165+
position = Point()
166+
orientation = Quaternion()
167+
position.x = obj.get_position()[0]
168+
position.y = obj.get_position()[1]
169+
position.z = obj.get_position()[2]
170+
axangle = obj.get_orientation()
171+
quat = axangle2quat(axangle[:-1], axangle[-1])
172+
orientation.w = quat[0]
173+
orientation.x = quat[1]
174+
orientation.y = quat[2]
175+
orientation.z = quat[3]
176+
obj_model = obj.get_model().decode('UTF-8')
177+
obj_center = [float(i)
178+
for i in obj.get_position_on_image()]
179+
obj_size = [float(i) for i in obj.get_size_on_image()]
180+
obj_id = obj.get_id()
181+
obj_colors = obj.get_colors()
182+
# Object Info -> Detection2D
183+
reco_obj = Detection2D()
184+
hyp = ObjectHypothesisWithPose()
185+
hyp.id = obj_model
186+
hyp.pose.pose.position = position
187+
hyp.pose.pose.orientation = orientation
188+
reco_obj.results.append(hyp)
189+
reco_obj.bbox.center.x = obj_center[0]
190+
reco_obj.bbox.center.y = obj_center[1]
191+
reco_obj.bbox.size_x = obj_size[0]
192+
reco_obj.bbox.size_y = obj_size[1]
193+
reco_msg.detections.append(reco_obj)
194+
195+
# Object Info -> WbCameraRecognitionObject
196+
reco_webots_obj = WbCameraRecognitionObject()
197+
reco_webots_obj.id = obj_id
198+
reco_webots_obj.model = obj_model
199+
reco_webots_obj.pose.pose.position = position
200+
reco_webots_obj.pose.pose.orientation = orientation
201+
reco_webots_obj.bbox.center.x = obj_center[0]
202+
reco_webots_obj.bbox.center.y = obj_center[1]
203+
reco_webots_obj.bbox.size_x = obj_size[0]
204+
reco_webots_obj.bbox.size_y = obj_size[1]
205+
for i in range(0, obj.get_number_of_colors()):
206+
color = ColorRGBA()
207+
color.r = obj_colors[3 * i]
208+
color.g = obj_colors[3 * i + 1]
209+
color.b = obj_colors[3 * i + 2]
210+
reco_webots_obj.colors.append(color)
211+
reco_msg_webots.objects.append(reco_webots_obj)
212+
self._recognition_webots_publisher.publish(reco_msg_webots)
213+
self._recognition_publisher.publish(reco_msg)
214+
else:
215+
self._wb_device.recognitionDisable()
124216
else:
125217
self._wb_device.disable()

webots_ros2_msgs/CMakeLists.txt

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,34 @@ endif()
1818
find_package(ament_cmake REQUIRED)
1919
find_package(builtin_interfaces REQUIRED)
2020
find_package(rosidl_default_generators REQUIRED)
21+
find_package(geometry_msgs REQUIRED)
22+
find_package(std_msgs REQUIRED)
23+
find_package(vision_msgs REQUIRED)
2124

25+
set(msg_files
26+
"msg/WbCameraRecognitionObject.msg"
27+
"msg/WbCameraRecognitionObjects.msg"
28+
)
2229
set(srv_files
2330
"srv/SetDifferentialWheelSpeed.srv"
2431
"srv/SetInt.srv"
2532
)
2633

34+
rosidl_generate_interfaces(${PROJECT_NAME}
35+
${msg_files} ${srv_files}
36+
DEPENDENCIES builtin_interfaces std_msgs geometry_msgs vision_msgs
37+
ADD_LINTER_TESTS
38+
)
39+
2740
if(BUILD_TESTING)
2841
find_package(ament_lint_auto REQUIRED)
2942
set(ament_cmake_copyright_FOUND TRUE)
3043
set(ament_cmake_cpplint_FOUND TRUE)
3144
ament_lint_auto_find_test_dependencies()
3245
endif()
3346

34-
rosidl_generate_interfaces(${PROJECT_NAME}
35-
${srv_files}
36-
DEPENDENCIES builtin_interfaces
37-
ADD_LINTER_TESTS
38-
)
47+
3948
ament_export_dependencies(rosidl_default_runtime)
49+
ament_export_include_directories(include)
50+
4051
ament_package()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int32 id
2+
geometry_msgs/PoseStamped pose
3+
vision_msgs/BoundingBox2D bbox
4+
std_msgs/ColorRGBA[] colors
5+
string model
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
std_msgs/Header header
2+
WbCameraRecognitionObject[] objects

webots_ros2_msgs/package.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@
1515
<buildtool_depend>rosidl_default_generators</buildtool_depend>
1616

1717
<build_depend>builtin_interfaces</build_depend>
18+
<build_depend>geometry_msgs</build_depend>
19+
<build_depend>std_msgs</build_depend>
20+
<build_depend>vision_msgs</build_depend>
1821

1922
<exec_depend>builtin_interfaces</exec_depend>
2023
<exec_depend>rosidl_default_runtime</exec_depend>
24+
<exec_depend>geometry_msgs</exec_depend>
25+
<exec_depend>std_msgs</exec_depend>
26+
<exec_depend>vision_msgs</exec_depend>
2127

2228
<test_depend>ament_lint_auto</test_depend>
2329
<test_depend>ament_lint_common</test_depend>

0 commit comments

Comments
 (0)