From 5bea0c45e47194596083e726e16db2e7a36df76c Mon Sep 17 00:00:00 2001
From: Chris Iverach-Brereton <59611394+civerachb-cpr@users.noreply.github.com>
Date: Mon, 13 Jan 2025 15:30:19 -0500
Subject: [PATCH] Add offboard sensors package (#17)
* Add the clearpath_offboard_sensors package, add launch file for offboard velodyne processing
* Add the image format conversion launch files previously in clearpath_sensors. Update dependencies
---
clearpath_desktop/package.xml | 1 +
clearpath_offboard_sensors/CMakeLists.txt | 8 ++
.../config/velodyne_lidar.yaml | 10 ++
.../launch/image_compressed_to_raw.launch.py | 71 +++++++++++++
.../launch/image_ffmpeg_to_raw.launch.py | 72 ++++++++++++++
.../launch/image_raw_to_compressed.launch.py | 71 +++++++++++++
.../launch/image_raw_to_ffmpeg.launch.py | 74 ++++++++++++++
.../launch/image_raw_to_theora.launch.py | 71 +++++++++++++
.../launch/image_theora_to_raw.launch.py | 71 +++++++++++++
.../launch/velodyne_pointcloud.launch.py | 99 +++++++++++++++++++
clearpath_offboard_sensors/package.xml | 20 ++++
11 files changed, 568 insertions(+)
create mode 100644 clearpath_offboard_sensors/CMakeLists.txt
create mode 100644 clearpath_offboard_sensors/config/velodyne_lidar.yaml
create mode 100644 clearpath_offboard_sensors/launch/image_compressed_to_raw.launch.py
create mode 100644 clearpath_offboard_sensors/launch/image_ffmpeg_to_raw.launch.py
create mode 100644 clearpath_offboard_sensors/launch/image_raw_to_compressed.launch.py
create mode 100644 clearpath_offboard_sensors/launch/image_raw_to_ffmpeg.launch.py
create mode 100644 clearpath_offboard_sensors/launch/image_raw_to_theora.launch.py
create mode 100644 clearpath_offboard_sensors/launch/image_theora_to_raw.launch.py
create mode 100644 clearpath_offboard_sensors/launch/velodyne_pointcloud.launch.py
create mode 100644 clearpath_offboard_sensors/package.xml
diff --git a/clearpath_desktop/package.xml b/clearpath_desktop/package.xml
index ff88109..154be94 100644
--- a/clearpath_desktop/package.xml
+++ b/clearpath_desktop/package.xml
@@ -12,6 +12,7 @@
ament_cmake
clearpath_config_live
+ clearpath_offboard_sensors
clearpath_platform_msgs
clearpath_viz
diff --git a/clearpath_offboard_sensors/CMakeLists.txt b/clearpath_offboard_sensors/CMakeLists.txt
new file mode 100644
index 0000000..d6ad201
--- /dev/null
+++ b/clearpath_offboard_sensors/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.5)
+project(clearpath_offboard_sensors)
+find_package(ament_cmake REQUIRED)
+
+install(DIRECTORY config launch
+ DESTINATION share/${PROJECT_NAME}
+)
+ament_package()
diff --git a/clearpath_offboard_sensors/config/velodyne_lidar.yaml b/clearpath_offboard_sensors/config/velodyne_lidar.yaml
new file mode 100644
index 0000000..b51c6a0
--- /dev/null
+++ b/clearpath_offboard_sensors/config/velodyne_lidar.yaml
@@ -0,0 +1,10 @@
+/**:
+ ros__parameters:
+ calibration: /opt/ros/jazzy/share/velodyne_pointcloud/params/VLP16db.yaml
+ max_range: 130.0
+ min_range: 0.9
+ organize_cloud: true
+ view_direction: 0.0
+ model: VLP16
+ fixed_frame: lidar3d_0_laser
+ target_frame: lidar3d_0_laser
\ No newline at end of file
diff --git a/clearpath_offboard_sensors/launch/image_compressed_to_raw.launch.py b/clearpath_offboard_sensors/launch/image_compressed_to_raw.launch.py
new file mode 100644
index 0000000..9e644a3
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/image_compressed_to_raw.launch.py
@@ -0,0 +1,71 @@
+# Software License Agreement (BSD)
+#
+# @author Roni Kreinin
+# @copyright (c) 2023, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+def generate_launch_description():
+ namespace = LaunchConfiguration('namespace')
+ in_compressed = LaunchConfiguration('in_compressed')
+ out_raw = LaunchConfiguration('out_raw')
+
+ arg_namespace = DeclareLaunchArgument(
+ 'namespace',
+ default_value=''
+ )
+
+ arg_in_compressed = DeclareLaunchArgument(
+ 'in_compressed',
+ default_value='compressed'
+ )
+
+ arg_out_raw = DeclareLaunchArgument(
+ 'out_raw',
+ default_value='image'
+ )
+
+ compressed_transport_node = Node(
+ name='image_compressed_to_raw',
+ namespace=namespace,
+ package='image_transport',
+ executable='republish',
+ remappings=[
+ ('in/compressed', in_compressed),
+ ('out', out_raw),
+ ],
+ arguments=['compressed', 'raw'],
+ )
+
+ ld = LaunchDescription()
+ ld.add_action(arg_namespace)
+ ld.add_action(arg_in_compressed)
+ ld.add_action(arg_out_raw)
+ ld.add_action(compressed_transport_node)
+ return ld
diff --git a/clearpath_offboard_sensors/launch/image_ffmpeg_to_raw.launch.py b/clearpath_offboard_sensors/launch/image_ffmpeg_to_raw.launch.py
new file mode 100644
index 0000000..32eb9b6
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/image_ffmpeg_to_raw.launch.py
@@ -0,0 +1,72 @@
+# Software License Agreement (BSD)
+#
+# @author Hilary Luo
+# @copyright (c) 2024, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+def generate_launch_description():
+ namespace = LaunchConfiguration('namespace')
+ in_ffmpeg = LaunchConfiguration('in_ffmpeg')
+ out_raw = LaunchConfiguration('out_raw')
+
+ arg_namespace = DeclareLaunchArgument(
+ 'namespace',
+ default_value=''
+ )
+
+ arg_in_ffmpeg = DeclareLaunchArgument(
+ 'in_ffmpeg',
+ default_value='ffmpeg'
+ )
+
+ arg_out_raw = DeclareLaunchArgument(
+ 'out_raw',
+ default_value='image'
+ )
+
+ ffmpeg_transport_node = Node(
+ name='image_ffmpeg_to_raw',
+ namespace=namespace,
+ package='image_transport',
+ executable='republish',
+ remappings=[
+ ('in/ffmpeg', in_ffmpeg),
+ ('out', out_raw),
+ ],
+ arguments=['ffmpeg', 'raw'],
+ )
+
+ ld = LaunchDescription()
+ ld.add_action(arg_namespace)
+ ld.add_action(arg_in_ffmpeg)
+ ld.add_action(arg_out_raw)
+ ld.add_action(ffmpeg_transport_node)
+ return ld
diff --git a/clearpath_offboard_sensors/launch/image_raw_to_compressed.launch.py b/clearpath_offboard_sensors/launch/image_raw_to_compressed.launch.py
new file mode 100644
index 0000000..f3bd0c1
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/image_raw_to_compressed.launch.py
@@ -0,0 +1,71 @@
+# Software License Agreement (BSD)
+#
+# @author Roni Kreinin
+# @copyright (c) 2023, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+def generate_launch_description():
+ namespace = LaunchConfiguration('namespace')
+ in_raw = LaunchConfiguration('in_raw')
+ out_compressed = LaunchConfiguration('out_compressed')
+
+ arg_namespace = DeclareLaunchArgument(
+ 'namespace',
+ default_value=''
+ )
+
+ arg_in_raw = DeclareLaunchArgument(
+ 'in_raw',
+ default_value='image'
+ )
+
+ arg_out_compressed = DeclareLaunchArgument(
+ 'out_compressed',
+ default_value='compressed'
+ )
+
+ compressed_transport_node = Node(
+ name='image_raw_to_compressed',
+ namespace=namespace,
+ package='image_transport',
+ executable='republish',
+ remappings=[
+ ('in', in_raw),
+ ('out/compressed', out_compressed),
+ ],
+ arguments=['raw', 'compressed'],
+ )
+
+ ld = LaunchDescription()
+ ld.add_action(arg_namespace)
+ ld.add_action(arg_in_raw)
+ ld.add_action(arg_out_compressed)
+ ld.add_action(compressed_transport_node)
+ return ld
diff --git a/clearpath_offboard_sensors/launch/image_raw_to_ffmpeg.launch.py b/clearpath_offboard_sensors/launch/image_raw_to_ffmpeg.launch.py
new file mode 100644
index 0000000..6e7687f
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/image_raw_to_ffmpeg.launch.py
@@ -0,0 +1,74 @@
+# Software License Agreement (BSD)
+#
+# @author Hilary Luo
+# @copyright (c) 2024, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+ARGUMENTS = [
+ DeclareLaunchArgument('namespace', default_value=''),
+ DeclareLaunchArgument('in_raw', default_value='image'),
+ DeclareLaunchArgument('out_ffmpeg', default_value='ffmpeg'),
+ DeclareLaunchArgument('encoding', default_value='libx264'),
+ DeclareLaunchArgument('qmax', default_value='40'),
+ DeclareLaunchArgument('preset', default_value='superfast'),
+ DeclareLaunchArgument('tune', default_value='zerolatency'),
+ DeclareLaunchArgument('bit_rate', default_value='1000000'),
+ DeclareLaunchArgument('gop_size', default_value='15'),
+]
+
+
+def generate_launch_description():
+ namespace = LaunchConfiguration('namespace')
+ in_raw = LaunchConfiguration('in_raw')
+ out_ffmpeg = LaunchConfiguration('out_ffmpeg')
+
+ ffmpeg_transport_node = Node(
+ name='image_raw_to_ffmpeg',
+ namespace=namespace,
+ package='image_transport',
+ executable='republish',
+ remappings=[
+ ('in', in_raw),
+ ('out/ffmpeg', out_ffmpeg),
+ ],
+ arguments=['raw', 'ffmpeg'],
+ parameters=[
+ {'ffmpeg_image_transport.encoding': LaunchConfiguration('encoding')},
+ {'ffmpeg_image_transport.qmax': LaunchConfiguration('qmax')},
+ {'ffmpeg_image_transport.preset': LaunchConfiguration('preset')},
+ {'ffmpeg_image_transport.tune': LaunchConfiguration('tune')},
+ {'ffmpeg_image_transport.bit_rate': LaunchConfiguration('bit_rate')},
+ {'ffmpeg_image_transport.gop_size': LaunchConfiguration('gop_size')}],
+ )
+
+ ld = LaunchDescription(ARGUMENTS)
+ ld.add_action(ffmpeg_transport_node)
+ return ld
diff --git a/clearpath_offboard_sensors/launch/image_raw_to_theora.launch.py b/clearpath_offboard_sensors/launch/image_raw_to_theora.launch.py
new file mode 100644
index 0000000..9c0a18d
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/image_raw_to_theora.launch.py
@@ -0,0 +1,71 @@
+# Software License Agreement (BSD)
+#
+# @author Roni Kreinin
+# @copyright (c) 2023, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+def generate_launch_description():
+ namespace = LaunchConfiguration('namespace')
+ in_raw = LaunchConfiguration('in_raw')
+ out_theora = LaunchConfiguration('out_theora')
+
+ arg_namespace = DeclareLaunchArgument(
+ 'namespace',
+ default_value=''
+ )
+
+ arg_in_raw = DeclareLaunchArgument(
+ 'in_raw',
+ default_value='image'
+ )
+
+ arg_out_theora = DeclareLaunchArgument(
+ 'out_theora',
+ default_value='theora'
+ )
+
+ theora_transport_node = Node(
+ name='image_raw_to_theora',
+ namespace=namespace,
+ package='image_transport',
+ executable='republish',
+ remappings=[
+ ('in', in_raw),
+ ('out/theora', out_theora),
+ ],
+ arguments=['raw', 'theora'],
+ )
+
+ ld = LaunchDescription()
+ ld.add_action(arg_namespace)
+ ld.add_action(arg_in_raw)
+ ld.add_action(arg_out_theora)
+ ld.add_action(theora_transport_node)
+ return ld
diff --git a/clearpath_offboard_sensors/launch/image_theora_to_raw.launch.py b/clearpath_offboard_sensors/launch/image_theora_to_raw.launch.py
new file mode 100644
index 0000000..dc181fb
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/image_theora_to_raw.launch.py
@@ -0,0 +1,71 @@
+# Software License Agreement (BSD)
+#
+# @author Roni Kreinin
+# @copyright (c) 2023, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration
+from launch_ros.actions import Node
+
+
+def generate_launch_description():
+ namespace = LaunchConfiguration('namespace')
+ in_theora = LaunchConfiguration('in_theora')
+ out_raw = LaunchConfiguration('out_raw')
+
+ arg_namespace = DeclareLaunchArgument(
+ 'namespace',
+ default_value=''
+ )
+
+ arg_in_theora = DeclareLaunchArgument(
+ 'in_theora',
+ default_value='theora'
+ )
+
+ arg_out_raw = DeclareLaunchArgument(
+ 'out_raw',
+ default_value='image'
+ )
+
+ theora_transport_node = Node(
+ name='image_theora_to_raw',
+ namespace=namespace,
+ package='image_transport',
+ executable='republish',
+ remappings=[
+ ('in/theora', in_theora),
+ ('out', out_raw),
+ ],
+ arguments=['theora', 'raw'],
+ )
+
+ ld = LaunchDescription()
+ ld.add_action(arg_namespace)
+ ld.add_action(arg_in_theora)
+ ld.add_action(arg_out_raw)
+ ld.add_action(theora_transport_node)
+ return ld
diff --git a/clearpath_offboard_sensors/launch/velodyne_pointcloud.launch.py b/clearpath_offboard_sensors/launch/velodyne_pointcloud.launch.py
new file mode 100644
index 0000000..88db0bd
--- /dev/null
+++ b/clearpath_offboard_sensors/launch/velodyne_pointcloud.launch.py
@@ -0,0 +1,99 @@
+# Software License Agreement (BSD)
+#
+# @author Chris Iverach-Brereton
+# @copyright (c) 2025, Clearpath Robotics, Inc., All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Clearpath Robotics nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+from launch import LaunchDescription
+from launch.actions import DeclareLaunchArgument
+from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
+
+from launch_ros.actions import Node
+from launch_ros.substitutions import FindPackageShare
+
+
+def local_hostname():
+ """
+ Get the local hostname as a valid ROS namespace
+
+ Replaces dashes with underscores, adds an 'a' prefix if the first character
+ is a number (an underscore would result in it being a hidden topic, so use a letter)
+ """
+ try:
+ with open('/etc/hostname', 'r') as hostname_file:
+ hostname = hostname_file.readline()
+
+ hostname = hostname.strip().lower().replace('-', '_')
+ if hostname[0].isdigit():
+ hostname = f'a{hostname}'
+ except Exception as err:
+ print(f'Failed to read hostname: {err}')
+ hostname = 'offboard_computer'
+ return hostname
+
+
+def generate_launch_description():
+
+ namespace = LaunchConfiguration('namespace')
+ offboard_namespace = LaunchConfiguration('offboard_namespace')
+ parameters = LaunchConfiguration('parameters')
+
+ arg_namespace = DeclareLaunchArgument(
+ 'namespace',
+ default_value='',
+ )
+
+ arg_offboard_namespace = DeclareLaunchArgument(
+ 'offboard_namespace',
+ default_value=local_hostname(),
+ )
+
+ arg_parameters = DeclareLaunchArgument(
+ 'parameters',
+ default_value=PathJoinSubstitution([
+ FindPackageShare('clearpath_offboard_sensors'),
+ 'config',
+ 'velodyne_lidar.yaml'
+ ]),
+ )
+
+ velodyne_pointcloud_node = Node(
+ package='velodyne_pointcloud',
+ executable='velodyne_transform_node',
+ namespace=(namespace, '/', offboard_namespace),
+ output='screen',
+ parameters=[parameters],
+ remappings=[
+ ('/diagnostics', 'diagnostics'),
+ ('velodyne_packets', (namespace, '/velodyne_packets')),
+ ('velodyne_points', 'points'),
+ ],
+ )
+
+ ld = LaunchDescription()
+ ld.add_action(arg_namespace)
+ ld.add_action(arg_offboard_namespace)
+ ld.add_action(arg_parameters)
+ ld.add_action(velodyne_pointcloud_node)
+ return ld
diff --git a/clearpath_offboard_sensors/package.xml b/clearpath_offboard_sensors/package.xml
new file mode 100644
index 0000000..162ccd6
--- /dev/null
+++ b/clearpath_offboard_sensors/package.xml
@@ -0,0 +1,20 @@
+
+
+ clearpath_offboard_sensors
+ 0.3.0
+ Launch files for decompressing and consuming high-bandwidth sensor data on offboard computers
+
+ Chris Iverach-Brereton
+
+ BSD
+
+ ament_cmake
+
+ image_transport
+ image_transport_plugins
+ velodyne_pointcloud
+
+
+ ament_cmake
+
+