1515"""Camera device."""
1616
1717from 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
1822from rclpy .time import Time
1923from rclpy .qos import DurabilityPolicy , HistoryPolicy , QoSProfile , QoSReliabilityPolicy , qos_profile_sensor_data
2024from .sensor_device import SensorDevice
25+ from webots_ros2_core .math .quaternions import axangle2quat
2126
2227
2328class 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 ()
0 commit comments