NiclaRosPublisher.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
3 import struct
4 import rospy
5 from sensor_msgs.msg import CompressedImage, Image, CameraInfo
6 from sensor_msgs.msg import Range
7 from sensor_msgs.msg import Imu
8 from std_msgs.msg import String
9 from audio_common_msgs.msg import AudioData, AudioDataStamped, AudioInfo
10 from cv_bridge import CvBridge, CvBridgeError
11 import cv2
12 
13 from nicla_vision_ros import NiclaReceiverUDP, NiclaReceiverTCP
14 
15 
17 
18  def __init__(self) -> None:
19 
20  # used for some header, be sure to use the same name here and
21  # in the urdf for proper rviz visualization
22  nicla_name = rospy.get_param("~nicla_name", "nicla")
23 
24  # server address and port (the address of the machine running
25  # this code, any available port)
26  ip = rospy.get_param("~receiver_ip")
27  port = rospy.get_param("~receiver_port", "8002")
28  connection_type = rospy.get_param("~connection_type", "udp")
29 
30  self.enable_range = rospy.get_param("~enable_range", True)
31  self.enable_camera_raw = rospy.get_param("~enable_camera_raw", True)
32  self.enable_camera_compressed = rospy.get_param(
33  "~enable_camera_compressed", False
34  )
35  self.enable_audio = rospy.get_param("~enable_audio", True)
36  self.enable_audio_stamped = rospy.get_param(
37  "~enable_audio_stamped", False
38  )
39  self.enable_audio_recognition_vosk = rospy.get_param(
40  "~enable_audio_recognition_vosk", False
41  )
42  self.audio_recognition_model_path = rospy.get_param(
43  "~audio_recognition_model_path", ""
44  )
45  self.audio_recognition_grammar = rospy.get_param(
46  "~audio_recognition_grammar", ""
47  )
48  self.audio_recognition_listen_seconds = rospy.get_param(
49  "~audio_recognition_listen_seconds", 2
50  )
52  "~audio_recognition_wave_output_filename", ""
53  )
54  self.enable_imu = rospy.get_param("~enable_imu", True)
55 
56  if self.enable_range:
57  range_topic = nicla_name + "/tof"
58  self.range_pub = rospy.Publisher(range_topic, Range, queue_size=5)
59  self.range_msg = Range()
60  self.range_msg.header.frame_id = nicla_name + "_tof"
61  self.range_msg.radiation_type = Range.INFRARED
62  self.range_msg.min_range = 0
63  self.range_msg.max_range = 3.60
64  self.range_msg.field_of_view = (
65  0.471239 # 27degrees according to VL53L1X spec
66  )
67 
68  if self.enable_camera_raw:
69  # default topic name of image transport (which is not available in python so we do not use it)
70  self.image_raw_topic = nicla_name + "/camera/image_raw"
71  self.image_raw_msg = Image()
72  self.image_raw_msg.header.frame_id = nicla_name + "_camera"
73  self.image_raw_pub = rospy.Publisher(
74  self.image_raw_topic, Image, queue_size=5
75  )
76 
79  nicla_name + "/camera/image_raw/compressed"
80  )
81  self.image_compressed_msg = CompressedImage()
82  self.image_compressed_msg.header.frame_id = nicla_name + "_camera"
83  self.image_compressed_msg.format = "jpeg"
84  self.image_compressed_pub = rospy.Publisher(
85  self.image_compressed_topic, CompressedImage, queue_size=5
86  )
87 
89 
90  self.cv_bridge = CvBridge()
91 
92  camera_info_topic = nicla_name + "/camera/camera_info"
93  self.camera_info_msg = CameraInfo()
94  self.camera_info_msg.header.frame_id = nicla_name + "_camera"
95  self.camera_info_msg.height = 240
96  self.camera_info_msg.width = 320
97  self.camera_info_msg.distortion_model = "plumb_rob"
98  self.camera_info_msg.K = [
99  416.650528,
100  0.000000,
101  166.124514,
102  0.000000,
103  419.404643,
104  104.410543,
105  0.000000,
106  0.000000,
107  1.000000,
108  ]
109  self.camera_info_msg.D = [
110  0.176808,
111  -0.590488,
112  -0.008412,
113  0.015473,
114  0.000000,
115  ]
116  self.camera_info_msg.P = [
117  421.373566,
118  0.000000,
119  168.731782,
120  0.000000,
121  0.000000,
122  426.438812,
123  102.665989,
124  0.000000,
125  0.000000,
126  0.000000,
127  1.000000,
128  0.000000,
129  ]
130  self.camera_info_pub = rospy.Publisher(
131  camera_info_topic, CameraInfo, queue_size=5
132  )
133 
134  if self.enable_audio:
135  audio_topic = nicla_name + "/audio"
136  self.audio_msg = AudioData()
137  self.audio_pub = rospy.Publisher(
138  audio_topic, AudioData, queue_size=10
139  )
140 
141  if self.enable_audio_stamped:
142  audio_stamped_topic = nicla_name + "/audio_stamped"
143  self.audio_stamped_msg = AudioDataStamped()
144  self.audio_stamped_pub = rospy.Publisher(
145  audio_stamped_topic, AudioDataStamped, queue_size=10
146  )
147 
148  if self.enable_audio or self.enable_audio_stamped:
149  audio_info_topic = nicla_name + "/audio_info"
150  self.audio_info_msg = AudioInfo()
151  self.audio_info_msg.channels = 1
152  self.audio_info_msg.sample_rate = 16000
153  self.audio_info_msg.sample_format = "S16LE"
154  self.audio_info_msg.bitrate = 0
155  self.audio_info_msg.coding_format = "raw"
156  self.audio_info_pub = rospy.Publisher(
157  audio_info_topic, AudioInfo, queue_size=1
158  )
159 
160  if self.enable_imu:
161  imu_topic = nicla_name + "/imu"
162  self.imu_msg = Imu()
163  self.imu_msg.header.frame_id = nicla_name + "_imu"
164  self.imu_msg.orientation.x = 0
165  self.imu_msg.orientation.y = 0
166  self.imu_msg.orientation.z = 0
167  self.imu_msg.orientation.w = 1
168  self.imu_pub = rospy.Publisher(imu_topic, Imu, queue_size=5)
169 
170  if connection_type == "udp":
172  ip,
173  port,
174  enable_range=self.enable_range,
175  enable_image=self.enable_camera_raw
176  or self.enable_camera_compressed,
177  enable_audio=self.enable_audio or self.enable_audio_stamped,
178  enable_imu=self.enable_imu,
179  )
180  elif connection_type == "tcp":
182  ip,
183  port,
184  enable_range=self.enable_range,
185  enable_image=self.enable_camera_raw
186  or self.enable_camera_compressed,
187  enable_audio=self.enable_audio or self.enable_audio_stamped,
188  enable_imu=self.enable_imu,
189  )
190 
191  else:
192  rospy.logerr("Connection type ", connection_type, " not known")
193  raise Exception("Connection type not known")
194 
196  if not self.audio_recognition_model_path:
197  rospy.logerr(
198  "Path for VOSK recognizer model is an empty string! Please provide 'audio_recognition_model_path' arg"
199  )
200  exit()
201 
202  from nicla_vision_ros import SpeechRecognizer
203 
209  )
210  self.speech_recognizer_pub = rospy.Publisher(
211  nicla_name + "/audio_recognized", String, queue_size=10
212  )
213 
214  self.nicla_receiver_server.serve()
215 
216  def run(self):
217 
218  if self.enable_range and (
219  (range := self.nicla_receiver_server.get_range()) is not None
220  ):
221 
222  self.range_msg.header.stamp = rospy.Time.from_sec(range[0])
223  self.range_msg.range = int.from_bytes(range[1], "little") / 1000
224  self.range_pub.publish(self.range_msg)
225 
226  # PUBLISH IMAGE
228 
229  if (image := self.nicla_receiver_server.get_image()) is not None:
230 
231  # Publish info
232  self.camera_info_msg.header.stamp = rospy.Time.from_sec(
233  image[0]
234  )
235  self.camera_info_pub.publish(self.camera_info_msg)
236 
237  img_raw = image[1]
238 
239  # PUBLISH COMPRESSED
240  if self.enable_camera_compressed:
241  self.image_compressed_msg.header.stamp = (
242  rospy.Time.from_sec(image[0])
243  )
244 
245  try:
246  self.image_compressed_msg.data = (
247  self.cv_bridge.cv2_to_compressed_imgmsg(
248  img_raw, dst_format="jpg"
249  ).data
250  )
251  except CvBridgeError as e:
252  rospy.logerr(e)
253 
254  self.image_compressed_pub.publish(
256  )
257 
258  # PUBLISH IMG RAW
259  if self.enable_camera_raw:
260 
261  self.image_raw_msg.header.stamp = rospy.Time.from_sec(
262  image[0]
263  )
264  self.image_raw_msg.height = img_raw.shape[0]
265  self.image_raw_msg.width = img_raw.shape[1]
266  self.image_raw_msg.encoding = (
267  "bgr8" # Assuming OpenCV returns BGR format
268  )
269  self.image_raw_msg.is_bigendian = 0 # Not big endian
270  self.image_raw_msg.step = (
271  img_raw.shape[1] * 3
272  ) # Width * number of channels
273 
274  try:
275  self.image_raw_msg.data = self.cv_bridge.cv2_to_imgmsg(
276  img_raw, encoding="bgr8"
277  ).data
278  except CvBridgeError as e:
279  print(e)
280 
281  self.image_raw_pub.publish(self.image_raw_msg)
282 
283  # AUDIO DATA
284  if self.enable_audio or self.enable_audio_stamped:
285  self.audio_info_pub.publish(self.audio_info_msg)
286 
287  if (
288  self.enable_audio
289  or self.enable_audio_stamped
291  ):
292 
293  if (
294  audio_data := self.nicla_receiver_server.get_audio()
295  ) is not None:
296 
297  if self.enable_audio:
298  self.audio_msg.data = audio_data[1]
299  self.audio_pub.publish(self.audio_msg)
300 
301  if self.enable_audio_stamped:
302  self.audio_stamped_msg.header.stamp = rospy.Time.from_sec(
303  audio_data[0]
304  )
305  self.audio_stamped_msg.audio.data = audio_data[1]
306  self.audio_stamped_pub.publish(self.audio_stamped_msg)
307 
309  audio_recognized = self.speech_recognizer.process_audio(
310  audio_data[1]
311  )
312  if audio_recognized: # if not empty
313  self.speech_recognizer_pub.publish(audio_recognized)
314 
315 
316  if self.enable_imu and (
317  (imu := self.nicla_receiver_server.get_imu()) is not None
318  ):
319  self.imu_msg.header.stamp = rospy.Time.from_sec(imu[0])
320 
321  try:
322  acc_x, acc_y, acc_z, gyro_x, gyro_y, gyro_z = struct.unpack(
323  "<ffffff", imu[1]
324  ) # <: little endian
325  except Exception as e:
326  rospy.logerr("imu pack has ", len(imu[1]), " bytes")
327  raise e
328 
329  self.imu_msg.angular_velocity.x = 0.017453 * gyro_x
330  self.imu_msg.angular_velocity.y = 0.017453 * gyro_y
331  self.imu_msg.angular_velocity.z = 0.017453 * gyro_z
332  self.imu_msg.linear_acceleration.x = 9.80665 * acc_x
333  self.imu_msg.linear_acceleration.y = 9.80665 * acc_y
334  self.imu_msg.linear_acceleration.z = 9.80665 * acc_z
335  self.imu_pub.publish(self.imu_msg)
336 
337  def stop(self):
338  self.nicla_receiver_server.stop_serve()
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_recognition_wave_output_filename
audio_recognition_wave_output_filename
Definition: NiclaRosPublisher.py:51
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.range_msg
range_msg
Definition: NiclaRosPublisher.py:59
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_recognition_model_path
audio_recognition_model_path
Definition: NiclaRosPublisher.py:42
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.speech_recognizer_pub
speech_recognizer_pub
Definition: NiclaRosPublisher.py:210
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_imu
enable_imu
Definition: NiclaRosPublisher.py:54
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_pub
audio_pub
Definition: NiclaRosPublisher.py:137
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher
Definition: NiclaRosPublisher.py:16
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.camera_info_msg
camera_info_msg
Definition: NiclaRosPublisher.py:93
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.__init__
None __init__(self)
Definition: NiclaRosPublisher.py:18
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_audio_stamped
enable_audio_stamped
Definition: NiclaRosPublisher.py:36
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.nicla_receiver_server
nicla_receiver_server
Definition: NiclaRosPublisher.py:171
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_msg
audio_msg
Definition: NiclaRosPublisher.py:136
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.speech_recognizer
speech_recognizer
Definition: NiclaRosPublisher.py:204
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_camera_raw
enable_camera_raw
Definition: NiclaRosPublisher.py:31
nicla_vision_ros.SpeechRecognizer.SpeechRecognizer
Definition: SpeechRecognizer.py:9
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.camera_info_pub
camera_info_pub
Definition: NiclaRosPublisher.py:130
nicla_vision_ros.NiclaReceiverServer.NiclaReceiverTCP
Definition: NiclaReceiverServer.py:240
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.stop
def stop(self)
Definition: NiclaRosPublisher.py:337
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.image_raw_pub
image_raw_pub
Definition: NiclaRosPublisher.py:73
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.cv_bridge
cv_bridge
Definition: NiclaRosPublisher.py:90
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_recognition_listen_seconds
audio_recognition_listen_seconds
Definition: NiclaRosPublisher.py:48
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.range_pub
range_pub
Definition: NiclaRosPublisher.py:58
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_range
enable_range
Definition: NiclaRosPublisher.py:30
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.imu_msg
imu_msg
Definition: NiclaRosPublisher.py:162
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_stamped_msg
audio_stamped_msg
Definition: NiclaRosPublisher.py:143
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_audio_recognition_vosk
enable_audio_recognition_vosk
Definition: NiclaRosPublisher.py:39
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_info_pub
audio_info_pub
Definition: NiclaRosPublisher.py:156
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.image_compressed_msg
image_compressed_msg
Definition: NiclaRosPublisher.py:81
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_recognition_grammar
audio_recognition_grammar
Definition: NiclaRosPublisher.py:45
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.image_compressed_topic
image_compressed_topic
Definition: NiclaRosPublisher.py:78
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_info_msg
audio_info_msg
Definition: NiclaRosPublisher.py:150
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_audio
enable_audio
Definition: NiclaRosPublisher.py:35
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.image_raw_msg
image_raw_msg
Definition: NiclaRosPublisher.py:71
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.imu_pub
imu_pub
Definition: NiclaRosPublisher.py:168
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.run
def run(self)
Definition: NiclaRosPublisher.py:216
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.audio_stamped_pub
audio_stamped_pub
Definition: NiclaRosPublisher.py:144
nicla_vision_ros.NiclaReceiverServer.NiclaReceiverUDP
Definition: NiclaReceiverServer.py:144
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.image_compressed_pub
image_compressed_pub
Definition: NiclaRosPublisher.py:84
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.image_raw_topic
image_raw_topic
Definition: NiclaRosPublisher.py:70
nicla_vision_ros.NiclaRosPublisher.NiclaRosPublisher.enable_camera_compressed
enable_camera_compressed
Definition: NiclaRosPublisher.py:32


nicla_vision_ros
Author(s): Davide Torielli , Damiano Gasperini , Edoardo Del Bianco , Federico Rollo
autogenerated on Sat Nov 16 2024 03:38:18