From ce93585dba45834ba74a40dcfa3439081d18f91c Mon Sep 17 00:00:00 2001 From: oliverkania <oliver.kania@rwth-aachen.de> Date: Tue, 29 Apr 2025 18:43:33 +0200 Subject: [PATCH] added node for tof reading --- my_robot_package/tof_pico_node.py | 74 +++++++++++++++++++++++++++++++ setup.py | 1 + 2 files changed, 75 insertions(+) create mode 100644 my_robot_package/tof_pico_node.py diff --git a/my_robot_package/tof_pico_node.py b/my_robot_package/tof_pico_node.py new file mode 100644 index 0000000..651c9e3 --- /dev/null +++ b/my_robot_package/tof_pico_node.py @@ -0,0 +1,74 @@ +import rclpy +from rclpy.node import Node +from sensor_msgs.msg import PointCloud2, PointField +from std_msgs.msg import Header +import sensor_msgs_py.point_cloud2 as pc2 +import serial +import math +import struct + +class VL53PicoPointCloud(Node): + def __init__(self): + super().__init__('vl53_pico_pointcloud') + self.publisher = self.create_publisher(PointCloud2, 'vl53_pointcloud', 10) + self.ser = serial.Serial('/dev/ttyACM0', 115200, timeout=1) + self.timer = self.create_timer(0.1, self.read_and_publish) + + def read_and_publish(self): + line = self.ser.readline().decode().strip() + try: + values = list(map(float, line.split(','))) + if len(values) != 64: + return + + # Convert to meters and filter invalid + distances_m = [ + d / 10.0 # eigentlich /1000 für m anstatt mm + for d in values + ] + + points = [] + fov_deg = 60.0 + step_angle = math.radians(fov_deg / 8) # 8 rows & columns + row_offset = -math.radians(fov_deg / 2) + step_angle / 2 + col_offset = -math.radians(fov_deg / 2) + step_angle / 2 + + for row in range(8): + for col in range(8): + idx = row * 8 + col + d = distances_m[idx] + if math.isnan(d): + continue + + theta = col_offset + col * step_angle + phi = row_offset + row * step_angle + + # Convert spherical to Cartesian (approximation for RViz) + x = d * math.cos(phi) * math.sin(theta) + y = d * math.sin(phi) + z = d * math.cos(phi) * math.cos(theta) + + points.append((x, y, z)) + + header = Header() + header.stamp = self.get_clock().now().to_msg() + header.frame_id = 'vl53_frame' + + fields = [ + PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1), + PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1), + PointField(name='z', offset=8, datatype=PointField.FLOAT32, count=1) + ] + + cloud = pc2.create_cloud(header, fields, points) + self.publisher.publish(cloud) + + except Exception as e: + self.get_logger().warn(f"Failed to parse or publish: {e}") + +def main(args=None): + rclpy.init(args=args) + node = VL53PicoPointCloud() + rclpy.spin(node) + node.destroy_node() + rclpy.shutdown() diff --git a/setup.py b/setup.py index 3183c99..8f8fdb0 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,7 @@ setup( entry_points={ 'console_scripts': [ 'joint_reader = my_robot_package.joint_reader:main', + 'tof_pico_node = my_robot_package.tof_pico_node:main', ], }, ) -- GitLab