sick_scan_xd_subscriber.py
Go to the documentation of this file.
1 # Subscribe to sick_scan_xd pointcloud and laserscan messages and save to json-file
2 
3 import json
4 import numpy as np
5 import threading
6 from collections import namedtuple
7 from sick_scan_xd_simu_report import SickScanXdMsgStatus
8 
9 Jitter = namedtuple("Jitter", "angle_deg, angle_rad, range, velocity, acceleration, intensity") # declaration of a jitter for comparison for pointcloud, laserscan and imu data (const values)
10 jitter = Jitter(angle_deg = 0.1, angle_rad = np.deg2rad(0.1), range = 0.001, velocity = 0.1, acceleration = 0.1, intensity = 0.1) # tolerated jitter for comparison for pointcloud, laserscan and imu data
11 
12 ros1_found = False
13 ros2_found = False
14 try:
15  import rospy
16  from sensor_msgs.msg import PointCloud2, PointField, LaserScan, Imu
17  ros1_found = True
18 except ModuleNotFoundError as exc:
19  ros1_found = False
20 
21 try:
22  import rclpy
23  from rclpy.node import Node
24  from sensor_msgs.msg import PointCloud2, PointField, LaserScan, Imu
25  ros2_found = True
26 except ModuleNotFoundError as exc:
27  ros2_found = False
28 
29 if not ros2_found:
30  class Node:
31  pass
32 
33 def ros_init(os_name = "linux", ros_version = "noetic", node_name = "sick_scan_xd_subscriber"):
34  """
35  ros initialization, delegates to ros initialization function depending on system and ros version
36  """
37  if ros1_found and ros_version == "noetic":
38  rospy.init_node(node_name)
39  elif ros2_found and (ros_version == "humble" or ros_version == "foxy"):
40  rclpy.init()
41  elif ros_version == "none":
42  pass
43  else:
44  print(f"## ERROR sick_scan_xd_subscriber.ros_init(): ros version {ros_version} not found or not supported")
45 
46 class NumpyJsonEncoder(json.JSONEncoder):
47  """
48  Extension of json encoder to support numpy types, thanks to https://stackoverflow.com/questions/26646362/numpy-array-is-not-json-serializable
49  and https://www.geeksforgeeks.org/fix-type-error-numpy-array-is-not-json-serializable/
50  """
51  def default(self, obj):
52  if isinstance(obj, np.integer):
53  return int(obj)
54  elif isinstance(obj, np.floating):
55  return float(obj)
56  elif isinstance(obj, np.ndarray):
57  return obj.tolist()
58  return json.JSONEncoder.default(self, obj)
59 
61  """
62  Subset of a PointCloud2 message. Used to verify received PointCloud2 messages against reference (groundtruth) values
63  """
64  def __init__(self, msg = None):
65  """
66  Initializing constructor
67  """
68  self.frame_id = msg.header.frame_id if msg is not None else ""
69  self.width = msg.width if msg is not None else 0
70  self.height = msg.height if msg is not None else 0
71  self.point_step = msg.point_step if msg is not None else 0
72  self.row_step = msg.row_step if msg is not None else 0
73  self.fields = msg.fields if msg is not None else []
74  self.data = msg.data if msg is not None else []
75  def to_dictionary(self):
76  """
77  Converts and returns all member variables to a serializable dictionary
78  """
79  fields = []
80  for field in self.fields:
81  fields.append({"name": field.name, "offset": field.offset, "datatype": field.datatype, "count": field.count})
82  hex_data_str = "".join("{:02x}".format(x) for x in self.data)
83  return {
84  "frame_id": self.frame_id,
85  "width": self.width,
86  "height": self.height,
87  "point_step": self.point_step,
88  "row_step": self.row_step,
89  "fields": fields,
90  "data": hex_data_str,
91  }
92  def identical_messages(self, reference_msg, received_msg):
93  """
94  Returns True, if reference_msg and received_msg are identical except for the sequence counter and small floating point differences.
95  """
96  return (reference_msg["frame_id"] == received_msg["frame_id"]) and \
97  (reference_msg["width"] == received_msg["width"]) and \
98  (reference_msg["height"] == received_msg["height"]) and \
99  (reference_msg["point_step"] == received_msg["point_step"]) and \
100  (reference_msg["row_step"] == received_msg["row_step"]) and \
101  (self.identical_fields(reference_msg["fields"], received_msg["fields"])) and \
102  (self.identical_pointclouds(reference_msg["data"], received_msg["data"], reference_msg["width"], reference_msg["height"], reference_msg["point_step"], reference_msg["row_step"], reference_msg["fields"]))
103  def identical_fields(self, reference_fields, received_fields):
104  """
105  Returns True, if reference_fields and received_fields are identical
106  """
107  if (len(reference_fields) != len(received_fields)):
108  return False
109  for field_idx in range(len(reference_fields)):
110  if reference_fields[field_idx]["name"] != received_fields[field_idx]["name"] or \
111  reference_fields[field_idx]["offset"] != received_fields[field_idx]["offset"] or \
112  reference_fields[field_idx]["datatype"] != received_fields[field_idx]["datatype"] or \
113  reference_fields[field_idx]["count"] != received_fields[field_idx]["count"]:
114  return False
115  return True
116  def convert_pointcloud_field_datatype(self, field_datatype):
117  field_element_size = 0
118  field_element_dtype = 0
119  if field_datatype == 1: # compare INT8
120  field_element_size = 1
121  field_element_dtype = np.int8
122  elif field_datatype == 2: # compare UINT8
123  field_element_size = 1
124  field_element_dtype = np.uint8
125  elif field_datatype == 3: # compare INT16
126  field_element_size = 2
127  field_element_dtype = np.int16
128  elif field_datatype == 4: # compare UINT16
129  field_element_size = 2
130  field_element_dtype = np.uint16
131  elif field_datatype == 5: # compare INT32
132  field_element_size = 4
133  field_element_dtype = np.int32
134  elif field_datatype == 6: # compare UINT32
135  field_element_size = 4
136  field_element_dtype = np.uint32
137  elif field_datatype == 7: # compare FLOAT32
138  field_element_size = 4
139  field_element_dtype = np.float32
140  elif field_datatype == 8: # compare FLOAT64
141  field_element_size = 8
142  field_element_dtype = np.float64
143  return field_element_dtype, field_element_size
144  def identical_pointclouds(self, reference_pointcloud_hex, received_pointcloud_hex, pointcloud_width, pointcloud_height, pointcloud_point_step, pointcloud_row_step, field_description):
145  if len(reference_pointcloud_hex) != len(received_pointcloud_hex):
146  return False
147  # Cache field element datatypes
148  fields_element_size = []
149  fields_element_dtype = []
150  fields_element_jitter = []
151  for field_idx in range(len(field_description)):
152  field_element_dtype, field_element_size = self.convert_pointcloud_field_datatype(field_description[field_idx]["datatype"])
153  field_element_jitter = jitter.range
154  if field_element_size <= 0:
155  print(f"## ERROR RefPointcloudMsg.identical_pointclouds: unexpected field: count={field_description[field_idx]['count']}, datatype={field_description[field_idx]['datatype']}")
156  return False
157  fields_element_size.append(field_element_size)
158  fields_element_dtype.append(field_element_dtype)
159  fields_element_jitter.append(field_element_jitter)
160  # Convert messages to bytes
161  ref_pc_bytes = bytes.fromhex(reference_pointcloud_hex)
162  msg_pc_bytes = bytes.fromhex(received_pointcloud_hex)
163  for row in range(pointcloud_height):
164  for col in range(pointcloud_width):
165  for field_idx in range(len(field_description)):
166  field_start_idx = row * pointcloud_row_step + col * pointcloud_point_step + field_description[field_idx]["offset"]
167  field_end_idx = field_start_idx + fields_element_size[field_idx]
168  ref_field = np.frombuffer(ref_pc_bytes[field_start_idx:field_end_idx], dtype=fields_element_dtype[field_idx])
169  msg_field = np.frombuffer(msg_pc_bytes[field_start_idx:field_end_idx], dtype=fields_element_dtype[field_idx])
170  element_delta = np.abs(ref_field-msg_field)
171  if np.max(element_delta) > fields_element_jitter[field_idx]:
172  return False
173  return True
174 
176  """
177  Subset of a LaserScan message. Used to verify received LaserScan messages against reference (groundtruth) values
178  """
179  def __init__(self, msg = None):
180  """
181  Initializing constructor
182  """
183  self.frame_id = msg.header.frame_id if msg is not None else ""
184  self.angle_min = msg.angle_min if msg is not None else 0
185  self.angle_max = msg.angle_max if msg is not None else 0
186  self.angle_increment = msg.angle_increment if msg is not None else 0
187  self.ranges = msg.ranges if msg is not None else []
188  self.intensities = msg.intensities if msg is not None else []
189  def to_dictionary(self):
190  """
191  Converts and returns all member variables to a serializable dictionary
192  """
193  ranges_bytes = np.float32(self.ranges).tobytes()
194  ranges_hex_str = "".join("{:02x}".format(x) for x in ranges_bytes)
195  intensities_bytes = np.float32(self.intensities).tobytes()
196  intensities_hex_str = "".join("{:02x}".format(x) for x in intensities_bytes)
197  return {
198  "frame_id": self.frame_id,
199  "angle_min": self.angle_min,
200  "angle_max": self.angle_max,
201  "angle_increment": self.angle_increment,
202  "ranges": ranges_hex_str,
203  "intensities": intensities_hex_str,
204  }
205  def identical_floats_from_hex(self, floats_hex_ref, floats_hex_msg, epsilon):
206  floats_ref_bytes = bytes.fromhex(floats_hex_ref)
207  floats_msg_bytes = bytes.fromhex(floats_hex_msg)
208  floats_ref = np.frombuffer(floats_ref_bytes, dtype=np.float32)
209  floats_msg = np.frombuffer(floats_msg_bytes, dtype=np.float32)
210  if len(floats_ref) != len(floats_msg):
211  return False
212  floats_diff = np.max(np.abs(floats_ref - floats_msg))
213  return floats_diff <= epsilon
214  def identical_messages(self, reference_msg, received_msg):
215  """
216  Returns True, if reference_msg and received_msg are identical except for the sequence counter and small floating point differences.
217  """
218  return (reference_msg["frame_id"] == received_msg["frame_id"]) and \
219  (np.abs(reference_msg["angle_min"] - received_msg["angle_min"]) < jitter.angle_rad) and \
220  (np.abs(reference_msg["angle_max"] - received_msg["angle_max"]) < jitter.angle_rad) and \
221  (np.abs(reference_msg["angle_increment"] - received_msg["angle_increment"]) < jitter.angle_rad) and \
222  (self.identical_floats_from_hex(reference_msg["ranges"], received_msg["ranges"], jitter.range)) and \
223  (self.identical_floats_from_hex(reference_msg["intensities"], received_msg["intensities"], jitter.intensity))
224 
225 class RefImuMsg:
226  """
227  Subset of a IMU message. Used to verify received IMU messages against reference (groundtruth) values
228  """
229  def __init__(self, msg = None):
230  """
231  Initializing constructor
232  """
233  self.frame_id = msg.header.frame_id if msg is not None else ""
234  self.orientation = msg.orientation if msg is not None else []
235  self.orientation_covariance = msg.orientation_covariance if msg is not None else []
236  self.angular_velocity = msg.angular_velocity if msg is not None else []
237  self.angular_velocity_covariance = msg.angular_velocity_covariance if msg is not None else []
238  self.linear_acceleration = msg.linear_acceleration if msg is not None else []
239  self.linear_acceleration_covariance = msg.linear_acceleration_covariance if msg is not None else []
240  def to_dictionary(self):
241  """
242  Converts and returns all member variables to a serializable dictionary
243  """
244  return {
245  "frame_id": self.frame_id,
246  "orientation": [ self.orientation.x, self.orientation.y, self.orientation.z, self.orientation.w ],
247  "orientation_covariance": self.orientation_covariance,
248  "angular_velocity": [ self.angular_velocity.x, self.angular_velocity.y, self.angular_velocity.z ],
249  "angular_velocity_covariance": self.angular_velocity_covariance,
250  "linear_acceleration": [ self.linear_acceleration.x, self.linear_acceleration.y, self.linear_acceleration.z ],
251  "linear_acceleration_covariance": self.linear_acceleration_covariance,
252  }
253  def identical_messages(self, reference_msg, received_msg):
254  """
255  Returns True, if reference_msg and received_msg are identical except for the sequence counter and small floating point differences.
256  """
257  return (reference_msg["frame_id"] == received_msg["frame_id"]) and \
258  (np.linalg.norm(np.float32(reference_msg["orientation"]) - np.float32(received_msg["orientation"])) < jitter.angle_rad) and \
259  (np.linalg.norm(np.float32(reference_msg["orientation_covariance"]) - np.float32(received_msg["orientation_covariance"])) < jitter.angle_rad**2) and \
260  (np.linalg.norm(np.float32(reference_msg["angular_velocity"]) - np.float32(received_msg["angular_velocity"])) < jitter.velocity) and \
261  (np.linalg.norm(np.float32(reference_msg["angular_velocity_covariance"]) - np.float32(received_msg["angular_velocity_covariance"])) < jitter.velocity**2) and \
262  (np.linalg.norm(np.float32(reference_msg["linear_acceleration"]) - np.float32(received_msg["linear_acceleration"])) < jitter.acceleration) and \
263  (np.linalg.norm(np.float32(reference_msg["linear_acceleration_covariance"]) - np.float32(received_msg["linear_acceleration_covariance"])) < jitter.acceleration**2)
264 
266 
267  def __init__(self, os_name = "linux", ros_version = "noetic", pointcloud_subscriber_topic = "", laserscan_subscriber_topic = "", imu_subscriber_topic = ""):
268  if ros2_found and (ros_version == "humble" or ros_version == "foxy"):
269  subscriber_name = "sick_scan_xd_{}_{}_{}".format(pointcloud_subscriber_topic, laserscan_subscriber_topic, imu_subscriber_topic).replace("/","_")
270  super().__init__(subscriber_name)
272  self.subscriber = None
274  if len(pointcloud_subscriber_topic) > 0:
275  self.create_subscriber(os_name, ros_version, topic=pointcloud_subscriber_topic, msg_type=PointCloud2, fct_callback=self.pointcloud_listener_callback, msg_queue_size=16*12*3) # max. queue size for multiScan: 16 layer, 12 segments, 3 echos
276  elif len(laserscan_subscriber_topic) > 0:
277  self.create_subscriber(os_name, ros_version, topic=laserscan_subscriber_topic, msg_type=LaserScan, fct_callback=self.laserscan_listener_callback, msg_queue_size=16*12*3) # max. queue size for multiScan: 16 layer, 12 segments, 3 echos
278  elif len(imu_subscriber_topic) > 0:
279  self.create_subscriber(os_name, ros_version, topic=imu_subscriber_topic, msg_type=Imu, fct_callback=self.imu_listener_callback, msg_queue_size=16*12*3) # max. queue size for multiScan: 16 layer, 12 segments, 3 echos
280 
281  def create_subscriber(self, os_name, ros_version, topic, msg_type, fct_callback, msg_queue_size):
282  self.subscriber_topic = topic
283  if ros1_found and ros_version == "noetic":
284  self.subscriber = rospy.Subscriber(self.subscriber_topic, msg_type, callback=fct_callback, queue_size=msg_queue_size)
285  elif ros2_found and (ros_version == "humble" or ros_version == "foxy"):
286  self.subscriber = self.create_subscription(msg_type, self.subscriber_topic, callback=fct_callback, qos_profile=msg_queue_size)
287  else:
288  print(f"## ERROR SickScanXdSubscriber.create_subscriber(): ros version {ros_version} not found or not supported")
289  if self.subscriber is None:
290  print(f"## ERROR SickScanXdSubscriber: failed to create subscriber for messages on topic \"{self.subscriber_topic}\"")
291  else:
292  print(f"SickScanXdSubscriber: subscribed to {msg_type} messages on topic \"{self.subscriber_topic}\"")
293 
295  # print(f"SickScanXdSubscriber.pointcloud_listener_callback: PointCloud2 message = {msg}")
297  # print(f"SickScanXdSubscriber: {len(self.messages_received)} PointCloud2 messages received")
298 
300  # print(f"SickScanXdSubscriber.laserscan_listener_callback: LaserScan message = {msg}")
302  # print(f"SickScanXdSubscriber: {len(self.messages_received)} LaserScan messages received")
303 
304  def imu_listener_callback(self, msg):
305  # print(f"SickScanXdSubscriber.imu_listener_callback: Imu message = {msg}")
307  # print(f"SickScanXdSubscriber: {len(self.messages_received)} Imu messages received")
308 
309  def export_dictionary(self, dict):
310  if len(self.messages_received) > 0:
311  dict[self.subscriber_topic] = []
312  for msg in self.messages_received:
313  dict[self.subscriber_topic].append(msg.to_dictionary())
314 
316 
317  def __init__(self, config, run_ros_init):
318  self.ros_version = config.ros_version
319  self.ros_node = None
320  self.ros_spin_executor = None
321  self.ros_spin_thread = None
324  self.imu_subscriber = []
326  self.reference_messages_jsonfile = f"{config.log_folder}/{config.reference_messages_jsonfile}"
327  if run_ros_init:
328  ros_init(os_name = config.os_name, ros_version = config.ros_version, node_name = "sick_scan_xd_simu")
329  for topic in config.sick_scan_xd_pointcloud_topics:
330  self.pointcloud_subscriber.append(SickScanXdSubscriber(os_name = config.os_name, ros_version = config.ros_version, pointcloud_subscriber_topic = topic))
331  for topic in config.sick_scan_xd_laserscan_topics:
332  self.laserscan_subscriber.append(SickScanXdSubscriber(os_name = config.os_name, ros_version = config.ros_version, laserscan_subscriber_topic = topic))
333  for topic in config.sick_scan_xd_imu_topics:
334  self.imu_subscriber.append(SickScanXdSubscriber(os_name = config.os_name, ros_version = config.ros_version, imu_subscriber_topic = topic))
335  if run_ros_init and ros2_found and (config.ros_version == "humble" or config.ros_version == "foxy"):
336  # see https://answers.ros.org/question/377848/spinning-multiple-nodes-across-multiple-threads/
337  self.ros_spin_executor = rclpy.executors.MultiThreadedExecutor()
338  for node in self.pointcloud_subscriber:
339  self.ros_spin_executor.add_node(node)
340  for node in self.laserscan_subscriber:
341  self.ros_spin_executor.add_node(node)
342  for node in self.imu_subscriber:
343  self.ros_spin_executor.add_node(node)
344  self.ros_spin_thread = threading.Thread(target=self.ros_spin_executor.spin, daemon=True)
345  self.ros_spin_thread.start()
346 
348  self.messages_received["RefLaserscanMsg"] = {}
349  self.messages_received["RefPointcloudMsg"] = {}
350  self.messages_received["RefImuMsg"] = {}
351  num_messages = 0
352  for subscriber in self.laserscan_subscriber:
353  subscriber.export_dictionary(self.messages_received["RefLaserscanMsg"])
354  num_messages += len(subscriber.messages_received)
355  for subscriber in self.pointcloud_subscriber:
356  subscriber.export_dictionary(self.messages_received["RefPointcloudMsg"])
357  num_messages += len(subscriber.messages_received)
358  for subscriber in self.imu_subscriber:
359  subscriber.export_dictionary(self.messages_received["RefImuMsg"])
360  num_messages += len(subscriber.messages_received)
361  return num_messages, self.messages_received
362 
364  num_messages, messages = self.export_received_messages()
365  if num_messages > 0:
366  try:
367  with open(jsonfile, "w") as file_stream:
368  json.dump(messages, file_stream, indent=2, cls=NumpyJsonEncoder)
369  print(f"SickScanXdMonitor: {num_messages} messages exported to file \"{jsonfile}\"")
370  except Exception as exc:
371  print(f"## ERROR in SickScanXdMonitor.export_received_messages_to_jsonfile(\"{jsonfile}\"): exception {exc}")
372  else:
373  print(f"## ERROR SickScanXdMonitor.export_received_messages(): no messages received, file \"{jsonfile}\" not written")
374 
376  # with open(jsonfile, "r") as file_stream:
377  # print(file_stream.read())
378  try:
379  with open(jsonfile, "r") as file_stream:
380  self.messages_received = json.load(file_stream)
381  print(f"SickScanXdMonitor: messages imported from file \"{jsonfile}\"")
382  except Exception as exc:
383  print(f"## ERROR in SickScanXdMonitor.import_received_messages_from_jsonfile(\"{jsonfile}\"): exception {exc}")
384 
385  def verify_messages(self, report):
386  try:
387  received_messages = self.messages_received
388  reference_messages = {}
389  with open(self.reference_messages_jsonfile, "r") as file_stream:
390  reference_messages = json.load(file_stream)
391  converter = { "RefLaserscanMsg": RefLaserscanMsg(), "RefPointcloudMsg": RefPointcloudMsg(), "RefImuMsg": RefImuMsg() }
392  num_messages_verified = 0
393  for msg_type in reference_messages.keys():
394  if self.ros_version == "none" and msg_type == "RefLaserscanMsg":
395  continue # laserscan messages are not exported via API, i.e. verify laserscan messages only under ROS
396  for topic in reference_messages[msg_type].keys():
397  if self.ros_version == "none" and topic == "/cloud_all_fields_fullframe":
398  continue # only polar and cartesian pointcloud messages are exported via API # TODO: exclude topics from config
399  #if self.ros_version == "none" and msg_type == "RefImuMsg":
400  # continue # TODO !!!
401  for ref_msg in reference_messages[msg_type][topic]:
402  if topic not in received_messages[msg_type] or not self.find_message(ref_msg, received_messages[msg_type][topic], converter[msg_type]):
403  ref_msg_frame_id = ref_msg["frame_id"]
404  self.print_message(report, SickScanXdMsgStatus.ERROR, f"## ERROR in SickScanXdMonitor.verify_messages(): reference message not found in received messages (msg type: {msg_type}, topic: {topic}, frame_id: {ref_msg_frame_id}), test failed")
405  return False
406  num_messages_verified = num_messages_verified + 1
407  self.print_message(report, SickScanXdMsgStatus.INFO, f"SickScanXdMonitor.verify_messages(): {num_messages_verified} reference messages verified.")
408  # print(f"SickScanXdMonitor.verify_messages(): received_messages = {received_messages}")
409  # print(f"SickScanXdMonitor.verify_messages(): reference_messages = {reference_messages}")
410  # with open("verify_messages_received.json", "w") as file_stream:
411  # json.dump(received_messages, file_stream, indent=2, cls=NumpyJsonEncoder)
412  # with open("verify_messages_reference.json", "w") as file_stream:
413  # json.dump(reference_messages, file_stream, indent=2, cls=NumpyJsonEncoder)
414  except Exception as exc:
415  self.print_message(report, SickScanXdMsgStatus.ERROR, f"## ERROR in SickScanXdMonitor.verify_messages(): exception {exc}")
416  return False
417  return True
418 
419  def print_message(self, report, msg_status, message):
420  report.append_message(msg_status, message)
421  print(message)
422 
423  def find_message(self, reference_msg, received_messages, converter):
424  for received_message in received_messages:
425  if converter.identical_messages(reference_msg, received_message):
426  return True
427  return False
428 
429 if __name__ == '__main__':
430  ros_init()
431  sick_scan_xd_subscriber = SickScanXdSubscriber(os_name = "linux", ros_version = "noetic", pointcloud_subscriber_topic = "cloud_all_fields_fullframe")
432  if ros1_found:
433  while not rospy.is_shutdown():
434  rospy.sleep(0.1)
435  else:
436  print("## ERROR sick_scan_xd_subscriber: expected ros version not found or not supported")
sick_scan_xd_subscriber.RefLaserscanMsg.angle_increment
angle_increment
Definition: sick_scan_xd_subscriber.py:186
sick_scan_xd_subscriber.NumpyJsonEncoder.default
def default(self, obj)
Definition: sick_scan_xd_subscriber.py:51
sick_scan_xd_subscriber.RefLaserscanMsg.frame_id
frame_id
Definition: sick_scan_xd_subscriber.py:183
sick_scan_xd_subscriber.RefPointcloudMsg.identical_pointclouds
def identical_pointclouds(self, reference_pointcloud_hex, received_pointcloud_hex, pointcloud_width, pointcloud_height, pointcloud_point_step, pointcloud_row_step, field_description)
Definition: sick_scan_xd_subscriber.py:144
sick_scan_xd_subscriber.RefImuMsg.angular_velocity
angular_velocity
Definition: sick_scan_xd_subscriber.py:236
sick_scan_xd_subscriber.SickScanXdSubscriber.export_dictionary
def export_dictionary(self, dict)
Definition: sick_scan_xd_subscriber.py:309
sick_scan_xd_subscriber.SickScanXdMonitor.print_message
def print_message(self, report, msg_status, message)
Definition: sick_scan_xd_subscriber.py:419
sick_scan_xd_subscriber.RefPointcloudMsg.row_step
row_step
Definition: sick_scan_xd_subscriber.py:72
sick_scan_xd_subscriber.SickScanXdMonitor.messages_received
messages_received
Definition: sick_scan_xd_subscriber.py:325
sick_scan_xd_subscriber.Node
Definition: sick_scan_xd_subscriber.py:30
roswrap::console::print
ROSCONSOLE_DECL void print(FilterBase *filter, void *logger, Level level, const char *file, int line, const char *function, const char *fmt,...) ROSCONSOLE_PRINTF_ATTRIBUTE(7
Don't call this directly. Use the ROS_LOG() macro instead.
sick_scan_xd_subscriber.SickScanXdSubscriber.laserscan_listener_callback
def laserscan_listener_callback(self, msg)
Definition: sick_scan_xd_subscriber.py:299
sick_scan_xd_subscriber.RefPointcloudMsg.width
width
Definition: sick_scan_xd_subscriber.py:69
sick_scan_xd_subscriber.SickScanXdMonitor.ros_version
ros_version
Definition: sick_scan_xd_subscriber.py:318
sick_scan_xd_subscriber.RefImuMsg.orientation
orientation
Definition: sick_scan_xd_subscriber.py:234
sick_scan_xd_subscriber.RefPointcloudMsg
Definition: sick_scan_xd_subscriber.py:60
sick_scan_xd_subscriber.SickScanXdMonitor.ros_spin_thread
ros_spin_thread
Definition: sick_scan_xd_subscriber.py:321
sick_scan_xd_subscriber.RefImuMsg.orientation_covariance
orientation_covariance
Definition: sick_scan_xd_subscriber.py:235
sick_scan_xd_subscriber.RefImuMsg.to_dictionary
def to_dictionary(self)
Definition: sick_scan_xd_subscriber.py:240
sick_scan_xd_subscriber.SickScanXdMonitor.pointcloud_subscriber
pointcloud_subscriber
Definition: sick_scan_xd_subscriber.py:323
sick_scan_xd_subscriber.SickScanXdSubscriber.subscriber_topic
subscriber_topic
Definition: sick_scan_xd_subscriber.py:271
sick_scan_xd_subscriber.RefLaserscanMsg.identical_floats_from_hex
def identical_floats_from_hex(self, floats_hex_ref, floats_hex_msg, epsilon)
Definition: sick_scan_xd_subscriber.py:205
sick_scan_xd_subscriber.RefLaserscanMsg.intensities
intensities
Definition: sick_scan_xd_subscriber.py:188
sick_scan_xd_subscriber.SickScanXdSubscriber.create_subscriber
def create_subscriber(self, os_name, ros_version, topic, msg_type, fct_callback, msg_queue_size)
Definition: sick_scan_xd_subscriber.py:281
sick_scan_xd_subscriber.RefImuMsg.identical_messages
def identical_messages(self, reference_msg, received_msg)
Definition: sick_scan_xd_subscriber.py:253
sick_scan_xd_subscriber.SickScanXdMonitor.import_received_messages_from_jsonfile
def import_received_messages_from_jsonfile(self, jsonfile)
Definition: sick_scan_xd_subscriber.py:375
sick_scan_xd_subscriber.RefPointcloudMsg.to_dictionary
def to_dictionary(self)
Definition: sick_scan_xd_subscriber.py:75
sick_scan_xd_subscriber.SickScanXdSubscriber.pointcloud_listener_callback
def pointcloud_listener_callback(self, msg)
Definition: sick_scan_xd_subscriber.py:294
sick_scan_xd_subscriber.RefPointcloudMsg.identical_fields
def identical_fields(self, reference_fields, received_fields)
Definition: sick_scan_xd_subscriber.py:103
sick_scan_xd_subscriber.RefLaserscanMsg.angle_min
angle_min
Definition: sick_scan_xd_subscriber.py:184
sick_scan_xd_subscriber.SickScanXdMonitor.export_received_messages_to_jsonfile
def export_received_messages_to_jsonfile(self, jsonfile)
Definition: sick_scan_xd_subscriber.py:363
sick_scan_xd_subscriber.RefImuMsg.linear_acceleration
linear_acceleration
Definition: sick_scan_xd_subscriber.py:238
sick_scan_xd_subscriber.RefLaserscanMsg.ranges
ranges
Definition: sick_scan_xd_subscriber.py:187
sick_scan_xd_subscriber.SickScanXdMonitor.export_received_messages
def export_received_messages(self)
Definition: sick_scan_xd_subscriber.py:347
sick_scan_xd_subscriber.RefLaserscanMsg.identical_messages
def identical_messages(self, reference_msg, received_msg)
Definition: sick_scan_xd_subscriber.py:214
sick_scan_xd_subscriber.SickScanXdSubscriber
Definition: sick_scan_xd_subscriber.py:265
sick_scan_xd_subscriber.RefPointcloudMsg.data
data
Definition: sick_scan_xd_subscriber.py:74
sick_scan_xd_subscriber.SickScanXdSubscriber.messages_received
messages_received
Definition: sick_scan_xd_subscriber.py:273
sick_scan_xd_subscriber.RefImuMsg
Definition: sick_scan_xd_subscriber.py:225
sick_scan_xd_subscriber.SickScanXdMonitor.ros_spin_executor
ros_spin_executor
Definition: sick_scan_xd_subscriber.py:320
sick_scan_xd_subscriber.SickScanXdMonitor.__init__
def __init__(self, config, run_ros_init)
Definition: sick_scan_xd_subscriber.py:317
sick_scan_xd_subscriber.SickScanXdSubscriber.imu_listener_callback
def imu_listener_callback(self, msg)
Definition: sick_scan_xd_subscriber.py:304
sick_scan_xd_subscriber.RefPointcloudMsg.convert_pointcloud_field_datatype
def convert_pointcloud_field_datatype(self, field_datatype)
Definition: sick_scan_xd_subscriber.py:116
sick_scan_xd_subscriber.SickScanXdSubscriber.__init__
def __init__(self, os_name="linux", ros_version="noetic", pointcloud_subscriber_topic="", laserscan_subscriber_topic="", imu_subscriber_topic="")
Definition: sick_scan_xd_subscriber.py:267
sick_scan_xd_subscriber.SickScanXdMonitor
Definition: sick_scan_xd_subscriber.py:315
sick_scan_xd_subscriber.RefLaserscanMsg.__init__
def __init__(self, msg=None)
Definition: sick_scan_xd_subscriber.py:179
sick_scan_xd_subscriber.RefPointcloudMsg.point_step
point_step
Definition: sick_scan_xd_subscriber.py:71
sick_scan_xd_subscriber.SickScanXdMonitor.imu_subscriber
imu_subscriber
Definition: sick_scan_xd_subscriber.py:324
sick_scan_xd_subscriber.SickScanXdSubscriber.subscriber
subscriber
Definition: sick_scan_xd_subscriber.py:272
sick_scan_xd_subscriber.SickScanXdMonitor.ros_node
ros_node
Definition: sick_scan_xd_subscriber.py:319
sick_scan_xd_subscriber.SickScanXdMonitor.find_message
def find_message(self, reference_msg, received_messages, converter)
Definition: sick_scan_xd_subscriber.py:423
sick_scan_xd_subscriber.RefImuMsg.linear_acceleration_covariance
linear_acceleration_covariance
Definition: sick_scan_xd_subscriber.py:239
sick_scan_xd_subscriber.RefPointcloudMsg.fields
fields
Definition: sick_scan_xd_subscriber.py:73
sick_scan_xd_subscriber.SickScanXdMonitor.verify_messages
def verify_messages(self, report)
Definition: sick_scan_xd_subscriber.py:385
sick_scan_xd_subscriber.RefLaserscanMsg
Definition: sick_scan_xd_subscriber.py:175
sick_scan_xd_subscriber.RefPointcloudMsg.__init__
def __init__(self, msg=None)
Definition: sick_scan_xd_subscriber.py:64
sick_scan_xd_subscriber.ros_init
def ros_init(os_name="linux", ros_version="noetic", node_name="sick_scan_xd_subscriber")
Definition: sick_scan_xd_subscriber.py:33
roswrap::names::append
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
Append one name to another.
sick_scan_xd_subscriber.Jitter
Jitter
Definition: sick_scan_xd_subscriber.py:9
sick_scan_xd_subscriber.RefPointcloudMsg.identical_messages
def identical_messages(self, reference_msg, received_msg)
Definition: sick_scan_xd_subscriber.py:92
sick_scan_xd_subscriber.RefImuMsg.angular_velocity_covariance
angular_velocity_covariance
Definition: sick_scan_xd_subscriber.py:237
sick_scan_xd_subscriber.RefPointcloudMsg.frame_id
frame_id
Definition: sick_scan_xd_subscriber.py:68
sick_scan_xd_subscriber.SickScanXdMonitor.laserscan_subscriber
laserscan_subscriber
Definition: sick_scan_xd_subscriber.py:322
sick_scan_xd_subscriber.RefPointcloudMsg.height
height
Definition: sick_scan_xd_subscriber.py:70
sick_scan_xd_subscriber.RefImuMsg.__init__
def __init__(self, msg=None)
Definition: sick_scan_xd_subscriber.py:229
roswrap::start
ROSCPP_DECL void start()
Actually starts the internals of the node (spins up threads, starts the network polling and xmlrpc lo...
sick_scan_xd_subscriber.RefLaserscanMsg.to_dictionary
def to_dictionary(self)
Definition: sick_scan_xd_subscriber.py:189
sick_scan_xd_subscriber.RefImuMsg.frame_id
frame_id
Definition: sick_scan_xd_subscriber.py:233
sick_scan_xd_subscriber.SickScanXdMonitor.reference_messages_jsonfile
reference_messages_jsonfile
Definition: sick_scan_xd_subscriber.py:326
sick_scan_xd_subscriber.NumpyJsonEncoder
Definition: sick_scan_xd_subscriber.py:46
sick_scan_xd_subscriber.RefLaserscanMsg.angle_max
angle_max
Definition: sick_scan_xd_subscriber.py:185


sick_scan_xd
Author(s): Michael Lehning , Jochen Sprickerhof , Martin Günther
autogenerated on Fri Oct 25 2024 02:47:11