Skip to content

Commit bbcf97c

Browse files
Ouster sensor integration (#314)
* Add required ros installs for ouster integration * Change tactic, install ouster ros package instead * Create Ouster OS1 URDF XACRO, model works, confirmed when replacing path at the spot of the velodyne urdf load in robot.py * Start adding the Ouster lidar as option to the files, but a launch file is not created yet * Ouster Lidar works in simulation, nr of channels lowered since the simulation could not handle 128 channels ('Extrapolation Error looking up target frame') * Update documentation, hardware information still needs to be filled in * Add ouster and velodyne tests * Add missing license lines * Fix license for OS1 DAE file * Add nav2 test for panther+ouster lidar * Move Ouster section above Velodyne section Signed-off-by: Rosalie <[email protected]> * Change the general 'lidar' name to 'velodyne' specifically since we now have multiple lidar options Signed-off-by: Rosalie <[email protected]> * Rename test_panther_nav2 file to contain velodyne name Signed-off-by: Rosalie <[email protected]> * Change naming. Signed-off-by: Jelmer de Wolde <[email protected]> --------- Signed-off-by: Rosalie <[email protected]> Signed-off-by: Jelmer de Wolde <[email protected]> Co-authored-by: Jelmer de Wolde <[email protected]>
1 parent 602d475 commit bbcf97c

File tree

17 files changed

+684
-16
lines changed

17 files changed

+684
-16
lines changed

dockerfiles/install_scripts/core_packages.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ apt install -y \
2424
ros-$ROS_DISTRO-moveit-visual-tools \
2525
ros-$ROS_DISTRO-navigation2 \
2626
ros-$ROS_DISTRO-nav2-bringup \
27+
ros-$ROS_DISTRO-ouster-ros \
2728
ros-$ROS_DISTRO-plotjuggler-ros \
2829
ros-$ROS_DISTRO-realsense2-camera \
2930
ros-$ROS_DISTRO-realsense2-description \

docs/content/platforms.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,21 +116,32 @@ A ZED camera can be launched in simulation by creating a configuration with an *
116116

117117
A ZED camera can be used by connecting it to the host device via USB. To allow non-root users to access the camera, UDEV rules must be installed on the host machine. The required script can be found [here](https://gist.github.com/adujardin/2d5ce8f000fc6a7bd40bee2709749ff8).
118118

119+
## Ouster
120+
121+
![Ouster](../img/ouster/ouster_os1.png)
122+
123+
### Simulation Ouster
124+
125+
An Ouster lidar can be launched in simulation by creating a configuration with a *Lidar* of type *Ouster*.
126+
127+
### Hardware Ouster
128+
129+
*TODO: update when sensor has arrived.*
130+
119131
## Velodyne
120132

121133
![Velodyne](../img/velodyne/velodyne.png)
122134

123135
### Simulation Velodyne
124136

125-
A Velodyne lidar can be launched in simulation by creating a configuration with an *Lidar* of type *velodyne*.
137+
A Velodyne lidar can be launched in simulation by creating a configuration with a *Lidar* of type *velodyne*.
126138

127139
### Hardware Velodyne
128140

129141
When using the Velodyne lidar, make sure that the IP-address of the host device (where the velodyne node is running) is set correctly in the settings. One can edit the settings of the velodyne using a web interface on it's IP-adress.
130142

131143
| ![Velodyne settings](../img/velodyne/velodyne_settings.png) | ![Teltonika settings](../img/teltonika/teltonika_settings.png) |
132144
|-------------------------------------------------------------|----------------------------------------------------------------|
133-
| velodyne settings | teltonika settings |
134145

135146
## Teltonika GPS
136147

docs/img/ouster/ouster_os1.png

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SPDX-FileCopyrightText: Alliander N. V.
2+
3+
SPDX-License-Identifier: Apache-2.0

ros2_ws/src/rcdt_launch/launch/robots.launch.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
"",
2323
"axis",
2424
"gps",
25-
"lidar",
25+
"ouster",
26+
"velodyne",
2627
"realsense",
2728
"zed",
2829
"franka",
@@ -34,9 +35,11 @@
3435
"panther_gps",
3536
"panther_realsense",
3637
"panther_zed",
37-
"panther_lidar",
38+
"panther_velodyne",
39+
"panther_ouster",
3840
"mm",
39-
"mm_lidar",
41+
"mm_velodyne",
42+
"mm_ouster",
4043
"panther_and_franka",
4144
],
4245
)
@@ -71,7 +74,9 @@ def launch_setup(context: LaunchContext) -> list: # noqa: PLR0912, PLR0915
7174
Platform("axis", [0, 0, 0])
7275
case "gps":
7376
GPS("nmea", [0, 0, 0.5], ip_address="10.15.20.202")
74-
case "lidar":
77+
case "ouster":
78+
Lidar("ouster", [0, 0, 0.5])
79+
case "velodyne":
7580
Lidar("velodyne", [0, 0, 0.5])
7681
case "realsense":
7782
Camera("realsense", [0, 0, 0.5])
@@ -106,16 +111,23 @@ def launch_setup(context: LaunchContext) -> list: # noqa: PLR0912, PLR0915
106111
case "panther_zed":
107112
panther = Vehicle("panther", [0, 0, 0.2])
108113
Camera("zed", [0, 0, 0.5], parent=panther)
109-
case "panther_lidar":
114+
case "panther_velodyne":
110115
panther = Vehicle("panther", [0, 0, 0.2], navigation=True)
111116
Lidar("velodyne", [0.13, -0.13, 0.35], parent=panther)
117+
case "panther_ouster":
118+
panther = Vehicle("panther", [0, 0, 0.2], navigation=True)
119+
Lidar("ouster", [0.13, -0.13, 0.35], parent=panther)
112120
case "mm":
113121
panther = Vehicle("panther", [0, 0, 0.2])
114122
Arm("franka", [0, 0, 0.14], gripper=True, parent=panther, moveit=True)
115-
case "mm_lidar":
123+
case "mm_velodyne":
116124
panther = Vehicle("panther", [0, 0, 0.2], navigation=True)
117125
Arm("franka", [0, 0, 0.14], gripper=True, parent=panther, moveit=True)
118126
Lidar("velodyne", [0.13, -0.13, 0.35], parent=panther)
127+
case "mm_ouster":
128+
panther = Vehicle("panther", [0, 0, 0.2], navigation=True)
129+
Arm("franka", [0, 0, 0.14], gripper=True, parent=panther, moveit=True)
130+
Lidar("ouster", [0.13, -0.13, 0.35], parent=panther)
119131
case "panther_and_franka":
120132
Vehicle("panther", [0, -0.5, 0.2])
121133
Arm("franka", [0, 0.5, 0])

ros2_ws/src/rcdt_launch/rcdt_launch/robot.py

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,16 @@ def order_platforms() -> None:
9090
Raises:
9191
ValueError: If an unknown platform is encountered.
9292
"""
93-
order = ["panther", "franka", "velodyne", "realsense", "zed", "nmea", "axis"]
93+
order = [
94+
"panther",
95+
"franka",
96+
"velodyne",
97+
"ouster",
98+
"realsense",
99+
"zed",
100+
"nmea",
101+
"axis",
102+
]
94103

95104
for platform in Platform.platforms:
96105
if platform.platform not in order:
@@ -296,7 +305,14 @@ def create_map_links() -> list[Node]:
296305
def __init__( # noqa: PLR0913
297306
self,
298307
platform: Literal[
299-
"panther", "franka", "velodyne", "realsense", "zed", "nmea", "axis"
308+
"panther",
309+
"franka",
310+
"velodyne",
311+
"ouster",
312+
"realsense",
313+
"zed",
314+
"nmea",
315+
"axis",
300316
],
301317
position: list,
302318
orientation: list | None = None,
@@ -307,7 +323,7 @@ def __init__( # noqa: PLR0913
307323
"""Initialize a robot instance.
308324
309325
Args:
310-
platform (Literal["panther", "franka", "velodyne", "realsense", "zed", "nmea", "axis"]): The platform type of the robot.
326+
platform (Literal["panther", "franka", "velodyne", "ouster", "realsense", "zed", "nmea", "axis"]): The platform type of the robot.
311327
position (list): The initial position of the robot.
312328
orientation (list | None): The initial orientation of the robot.
313329
namespace (str | None): The namespace of the robot. If None, a unique namespace will be generated.
@@ -400,6 +416,10 @@ def xacro_path(self) -> str: # noqa: PLR0911
400416
return get_file_path(
401417
"rcdt_sensors", ["urdf"], "rcdt_velodyne.urdf.xacro"
402418
)
419+
case "ouster":
420+
return get_file_path(
421+
"rcdt_sensors", ["urdf"], "rcdt_os1_128.urdf.xacro"
422+
)
403423
case "realsense":
404424
return get_file_path(
405425
"rcdt_sensors", ["urdf"], "rcdt_realsense_d435.urdf.xacro"
@@ -432,6 +452,8 @@ def base_link(self) -> str: # noqa: PLR0911
432452
return "fr3_link0"
433453
case "velodyne":
434454
return "base_link"
455+
case "ouster":
456+
return "base_link"
435457
case "realsense":
436458
return "base_link"
437459
case "zed":
@@ -685,7 +707,7 @@ class Lidar(Platform):
685707

686708
def __init__( # noqa: PLR0913
687709
self,
688-
platform: Literal["velodyne"],
710+
platform: Literal["velodyne", "ouster"],
689711
position: list,
690712
orientation: list | None = None,
691713
namespace: str | None = None,
@@ -695,7 +717,7 @@ def __init__( # noqa: PLR0913
695717
"""Initialize the Lidar platform.
696718
697719
Args:
698-
platform (Literal["velodyne"]): The platform type.
720+
platform (Literal["velodyne", "ouster"]): The platform type.
699721
position (list): The position of the lidar.
700722
orientation (list | None): The initial orientation of the lidar.
701723
namespace (str | None): The namespace of the lidar.
@@ -723,7 +745,10 @@ def create_launch_description(self) -> list[RegisteredLaunchDescription]:
723745
list[RegisteredLaunchDescription]: The launch description for the platform.
724746
"""
725747
launch_descriptions = []
726-
launch_descriptions.append(self.create_velodyne_launch())
748+
if self.platform == "velodyne":
749+
launch_descriptions.append(self.create_velodyne_launch())
750+
if self.platform == "ouster":
751+
launch_descriptions.append(self.create_ouster_launch())
727752
return launch_descriptions
728753

729754
def create_velodyne_launch(self) -> RegisteredLaunchDescription:
@@ -746,6 +771,26 @@ def create_velodyne_launch(self) -> RegisteredLaunchDescription:
746771
},
747772
)
748773

774+
def create_ouster_launch(self) -> RegisteredLaunchDescription:
775+
"""Create the Ouster launch description.
776+
777+
Returns:
778+
RegisteredLaunchDescription: The launch description for Ouster.
779+
"""
780+
if self.parent:
781+
target_frame = f"{self.parent.namespace}/{self.parent.base_link}"
782+
else:
783+
target_frame = f"{self.namespace}/base_link"
784+
785+
return RegisteredLaunchDescription(
786+
get_file_path("rcdt_sensors", ["launch"], "ouster.launch.py"),
787+
launch_arguments={
788+
"simulation": str(Platform.simulation),
789+
"namespace": self.namespace,
790+
"target_frame": target_frame,
791+
},
792+
)
793+
749794

750795
class Arm(Platform):
751796
"""Extension on Platform with arm specific functionalities."""

ros2_ws/src/rcdt_sensors/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ install(
2323

2424
# Shared folders:
2525
install(
26-
DIRECTORY launch urdf config
26+
DIRECTORY launch urdf config meshes
2727
DESTINATION share/${PROJECT_NAME}
2828
)
2929

@@ -32,4 +32,5 @@ if(BUILD_TESTING)
3232
ament_lint_auto_find_test_dependencies()
3333
endif()
3434

35+
ament_environment_hooks("${CMAKE_CURRENT_SOURCE_DIR}/env-hooks/${PROJECT_NAME}.sh.in")
3536
ament_package()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-FileCopyrightText: Alliander N. V.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
ament_prepend_unique_value GZ_SIM_RESOURCE_PATH "@CMAKE_INSTALL_PREFIX@/share"
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# SPDX-FileCopyrightText: Alliander N. V.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
6+
from launch import LaunchContext, LaunchDescription
7+
from launch.actions import OpaqueFunction
8+
from launch_ros.actions import Node
9+
from rcdt_utilities.launch_utils import LaunchArgument
10+
from rcdt_utilities.register import Register
11+
12+
use_sim_arg = LaunchArgument("simulation", True, [True, False])
13+
namespace_arg = LaunchArgument("namespace", "ouster")
14+
target_frame_arg = LaunchArgument("target_frame", "")
15+
16+
17+
def launch_setup(context: LaunchContext) -> list:
18+
"""Setup the launch description for the Ouster lidar.
19+
20+
Args:
21+
context (LaunchContext): The launch context.
22+
23+
Returns:
24+
list: A list of actions to be executed.
25+
"""
26+
# Simulation-only setup
27+
namespace = namespace_arg.string_value(context)
28+
target_frame = target_frame_arg.string_value(context)
29+
30+
pointcloud_to_laserscan_node = Node(
31+
package="pointcloud_to_laserscan",
32+
executable="pointcloud_to_laserscan_node",
33+
remappings=[
34+
("cloud_in", f"/{namespace}/scan/points"),
35+
("scan", f"/{namespace}/scan"),
36+
],
37+
parameters=[
38+
{
39+
"target_frame": target_frame,
40+
"min_height": 0.1,
41+
"max_height": 2.0,
42+
"range_min": 0.05,
43+
"range_max": 90.0,
44+
}
45+
],
46+
namespace=namespace,
47+
)
48+
49+
return [
50+
Register.on_start(pointcloud_to_laserscan_node, context),
51+
]
52+
53+
54+
def generate_launch_description() -> LaunchDescription:
55+
"""Generate the launch description for the realsense camera.
56+
57+
Returns:
58+
LaunchDescription: The launch description for the realsense camera.
59+
"""
60+
return LaunchDescription(
61+
[
62+
use_sim_arg.declaration,
63+
namespace_arg.declaration,
64+
OpaqueFunction(function=launch_setup),
65+
]
66+
)

ros2_ws/src/rcdt_sensors/launch/velodyne.launch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616

1717
def launch_setup(context: LaunchContext) -> list:
18-
"""Setup the launch description for the realsense camera.
18+
"""Setup the launch description for the Velodyne lidar.
1919
2020
Args:
2121
context (LaunchContext): The launch context.

0 commit comments

Comments
 (0)