Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
8abf87b
:heavy_plus_sign: Added verified docker compose for both e2e monolith…
cardboardcode Sep 3, 2026
f65bf33
:hammer: Optimised Dockerfile.base build along with localised depende…
cardboardcode Sep 3, 2026
4092d38
:hammer: Included newline in docker-compose.headless.override.yml.
cardboardcode Sep 4, 2026
0c6bbd6
:hammer: Re-instated apt-get update in Dockerfile.base just before ro…
cardboardcode Sep 4, 2026
a91555f
:fire: Removed dependency installation of rmw cyclone and zenoh to ke…
cardboardcode Sep 4, 2026
884caa1
:hammer: Modified cloned_multi_tb3_simulation_launch.py to allow for …
cardboardcode Sep 6, 2026
c6e264e
:hammer: Added .dockerignore in project root for docker build optimiz…
cardboardcode Sep 8, 2026
528b6c8
:heavy_plus_sign: Re-added rmw-zenoh-cpp depedency within Dockerfile.…
cardboardcode Sep 8, 2026
f8e0a9a
:hammer: Abstracted Gazebo simulation into its own docker containe/se…
cardboardcode Sep 8, 2026
74706fb
:hammer: Updated headless override .yml file to be coherent with main…
cardboardcode Sep 8, 2026
fe7b0d1
:fire: Removed accidental additions of dev script files.
cardboardcode Sep 8, 2026
7dbef24
:hammer: Added verified zenoh-based docker compose override under doc…
cardboardcode Sep 8, 2026
ded0762
:blue_book: Add documentation header to Dockerfile.base
cardboardcode Sep 20, 2026
80273c7
Merge branch 'main' into cardboardcode/feat/e2e_test_env
cardboardcode Sep 20, 2026
82d233a
:hammer: Allow building of all next_gen_prototypes, rather than a sel…
cardboardcode Sep 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.md
.github/*
discourse/*
docker/*
scripts/*
LICENSE
34 changes: 25 additions & 9 deletions docker/Dockerfile.base
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# Base image for next_gen_prototype docker compose
# Purpose: reproducible ROS 2 Jazzy + Rust dev/test with prebuilt underlay workspace
# Components built in underlay /nav2_traffic_ws:
# sp_demo_nav2_bringup, rmf_nav2_traffic, rmf_path_server_demo,
# rmf_path_server_test
# Used by docker/docker-compose.yml services: gazebo_server, robot0_nav2_sim,
# robot1_nav2_sim, next_gen_prototype
# Overrides:
# docker-compose.headless.override.yml β†’ no RViz
# docker-compose.zenoh.override.yml β†’ RMW Zenoh
FROM ros:jazzy-ros-base

# Disable interactive prompts during package installation
Expand All @@ -13,11 +23,11 @@ RUN apt-get update && apt-get upgrade -y && \
clang \
libclang-dev \
build-essential \
ros-${ROS_DISTRO}-rmw-zenoh-cpp \
python3-colcon-common-extensions \
python3-colcon-cargo\
libssl-dev \
pkg-config \
&& rm -rf /var/lib/apt/lists/*
pkg-config

# Install colcon extensions for Rust
RUN pip3 install --no-cache-dir --break-system-packages colcon-ros-cargo
Expand All @@ -30,7 +40,6 @@ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no
cargo install cargo-ament-build && \
chmod -R a+rwX /usr/local/cargo /usr/local/rustup


# Initialize Underlay Workspace
WORKDIR /opt/ros2_rust_ws

Expand All @@ -42,15 +51,22 @@ RUN apt-get update && \
rosdep init || true && \
rosdep update && \
rosdep install --from-paths /tmp/next_gen_prototype --ignore-src -yr --skip-keys="rclrs ament_cargo ament_python" && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /tmp/next_gen_prototype
rm -rf /var/lib/apt/lists/*

WORKDIR /nav2_traffic_ws

# Build the Underlay Workspace
#RUN /bin/bash -c "source /opt/ros/jazzy/setup.bash && \
# colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release"
RUN mkdir src && mv /tmp/next_gen_prototype /nav2_traffic_ws/src/next_gen_prototype
RUN ls /nav2_traffic_ws/src/next_gen_prototype
RUN /bin/bash -c "source /opt/ros/${ROS_DISTRO}/setup.bash && \
colcon build \
--cmake-args -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS=\"-w\" \
-DCMAKE_C_FLAGS=\"-w\""
RUN rm -rf build/ log/ src/

# Provide automatic sourcing entrypoint configuration inside ~/.bashrc
RUN echo "source /opt/ros/jazzy/setup.bash" >> /root/.bashrc
#echo "source /opt/ros2_rust_ws/install/setup.bash" >> /root/.bashrc
RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> /root/.bashrc
RUN echo "source /nav2_traffic_ws/install/setup.bash" >> /root/.bashrc

CMD ["/bin/bash"]
23 changes: 23 additions & 0 deletions docker/docker-compose.headless.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
services:
robot0_nav2_sim:
command:
- bash
- -c
- >
source /nav2_traffic_ws/install/setup.bash &&
ros2 launch sp_demo_nav2_bringup
cloned_multi_tb3_simulation_launch.py
robots:='robot0={x: 0.0, y: 5.0, yaw: 0.0};'
use_rviz:=False
use_simulator:=False
robot1_nav2_sim:
command:
- bash
- -c
- >
source /nav2_traffic_ws/install/setup.bash &&
ros2 launch sp_demo_nav2_bringup
cloned_multi_tb3_simulation_launch.py
robots:='robot1={x: 3.0, y: 5.0, yaw: 0.0};'
use_rviz:=False
use_simulator:=False
115 changes: 115 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
x-ros2-base: &ros2-base
image: ros2_rust_base:jazzy
build:
context: ..
dockerfile: docker/Dockerfile.base

services:

gazebo_server:
<<: *ros2-base

container_name: gazebo_server
restart: no

networks:
- ros2_net

environment:
GZ_PARTITION: sim

command:
- bash
- -c
- >
source /nav2_traffic_ws/install/setup.bash &&
ros2 launch sp_demo_nav2_bringup
cloned_multi_tb3_simulation_launch.py
use_simulator:=True

robot0_nav2_sim:
<<: *ros2-base

container_name: robot0_nav2_sim
restart: no

networks:
- ros2_net

environment:
DISPLAY: ${DISPLAY:-}
WAYLAND_DISPLAY: ${WAYLAND_DISPLAY:-}
XDG_RUNTIME_DIR: ${XDG_RUNTIME_DIR:-/tmp/runtime-root}
QT_X11_NO_MITSHM: "1"
GZ_PARTITION: sim

volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:rw
- ${XDG_RUNTIME_DIR:-/tmp}:/tmp/host-runtime:rw

command:
- bash
- -c
- >
source /nav2_traffic_ws/install/setup.bash &&
ros2 launch sp_demo_nav2_bringup
cloned_multi_tb3_simulation_launch.py
robots:='robot0={x: 0.0, y: 5.0, yaw: 0.0};'
use_rviz:=True
use_simulator:=False


robot1_nav2_sim:
<<: *ros2-base

container_name: robot1_nav2_sim
restart: no

networks:
- ros2_net

environment:
DISPLAY: ${DISPLAY:-}
WAYLAND_DISPLAY: ${WAYLAND_DISPLAY:-}
XDG_RUNTIME_DIR: ${XDG_RUNTIME_DIR:-/tmp/runtime-root}
QT_X11_NO_MITSHM: "1"
GZ_PARTITION: sim

volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:rw
- ${XDG_RUNTIME_DIR:-/tmp}:/tmp/host-runtime:rw

command:
- bash
- -c
- >
source /nav2_traffic_ws/install/setup.bash &&
ros2 launch sp_demo_nav2_bringup
cloned_multi_tb3_simulation_launch.py
robots:='robot1={x: 3.0, y: 5.0, yaw: 0.0};'
use_rviz:=True
use_simulator:=False


next_gen_prototype:
<<: *ros2-base

container_name: next_gen_prototype
restart: no

networks:
- ros2_net

command:
- bash
- -c
- >
source /nav2_traffic_ws/install/setup.bash &&
ros2 launch rmf_path_server_demo
demo_nav2.launch.py
robots:='robot0 robot1'


networks:
ros2_net:
driver: bridge
46 changes: 46 additions & 0 deletions docker/docker-compose.zenoh.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
services:

gazebo_server:
environment:
RMW_IMPLEMENTATION: rmw_zenoh_cpp
ZENOH_CONFIG_OVERRIDE: 'mode="client";connect/endpoints=["tcp/zenoh_router:7447"]'
depends_on:
- zenoh_router

robot0_nav2_sim:
environment:
RMW_IMPLEMENTATION: rmw_zenoh_cpp
ZENOH_CONFIG_OVERRIDE: 'mode="client";connect/endpoints=["tcp/zenoh_router:7447"]'
depends_on:
- gazebo_server
- zenoh_router

robot1_nav2_sim:
environment:
RMW_IMPLEMENTATION: rmw_zenoh_cpp
ZENOH_CONFIG_OVERRIDE: 'mode="client";connect/endpoints=["tcp/zenoh_router:7447"]'
depends_on:
- gazebo_server
- zenoh_router

next_gen_prototype:
environment:
RMW_IMPLEMENTATION: rmw_zenoh_cpp
ZENOH_CONFIG_OVERRIDE: 'mode="client";connect/endpoints=["tcp/zenoh_router:7447"]'
depends_on:
- robot0_nav2_sim
- robot1_nav2_sim
- zenoh_router

zenoh_router:
image: eclipse/zenoh:latest
container_name: zenoh_router
restart: no

networks:
- ros2_net

command:
- --listen
- tcp/0.0.0.0:7447

Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
LogInfo,
OpaqueFunction,
RegisterEventHandler,
SetEnvironmentVariable,
)
from launch.conditions import IfCondition, UnlessCondition
from launch.event_handlers import OnShutdown
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration, TextSubstitution
from launch.substitutions import LaunchConfiguration, PythonExpression, TextSubstitution
from launch_ros.actions import Node
from nav2_common.launch import ParseMultiRobotPose

Expand Down Expand Up @@ -122,19 +123,53 @@ def generate_launch_description():
description='Start each robot stack after its transforms are ready.',
)

declare_use_simulator_cmd = DeclareLaunchArgument(
'use_simulator',
default_value='True',
description='Whether to start the Gazebo simulation server',
)

declare_start_gazebo_cmd = DeclareLaunchArgument(
'start_gazebo',
default_value=LaunchConfiguration('use_simulator'),
description='Alias for use_simulator: whether to start the Gazebo simulation server',
)

start_sim = PythonExpression([
"str('", LaunchConfiguration('use_simulator'), "').lower() in ('true', '1') and ",
"str('", LaunchConfiguration('start_gazebo'), "').lower() in ('true', '1')"
])

has_clock = LaunchConfiguration('has_clock')
declare_has_clock_cmd = DeclareLaunchArgument(
'has_clock',
default_value=start_sim,
description='Whether to bridge the simulation clock to /clock (defaults to true if starting simulator)',
)

declare_gz_partition_cmd = DeclareLaunchArgument(
'gz_partition',
default_value=os.environ.get('GZ_PARTITION', 'sim'),
description='Gazebo Transport partition name',
)

# Start Gazebo with plugin providing the robot spawning service
world_sdf = tempfile.mktemp(prefix='nav2_', suffix='.sdf')
world_sdf_xacro = ExecuteProcess(
condition=IfCondition(start_sim),
cmd=['xacro', '-o', world_sdf, ['headless:=', 'False'], world])
start_gazebo_cmd = ExecuteProcess(
condition=IfCondition(start_sim),
cmd=['gz', 'sim', '-r', '-s', world_sdf],
output='screen',
)

remove_temp_sdf_file = RegisterEventHandler(event_handler=OnShutdown(
on_shutdown=[
OpaqueFunction(function=lambda _: os.remove(world_sdf))
]))
remove_temp_sdf_file = RegisterEventHandler(
condition=IfCondition(start_sim),
event_handler=OnShutdown(
on_shutdown=[
OpaqueFunction(function=lambda _: os.path.exists(world_sdf) and os.remove(world_sdf))
]))

robots_list = ParseMultiRobotPose('robots').value()

Expand Down Expand Up @@ -183,13 +218,12 @@ def make_group(robot_autostart, condition, ready_node=None):
'headless': 'False',
'use_robot_state_pub': use_robot_state_pub,
'use_navigation': use_navigation,
'clock_topic': TextSubstitution(
text=(
'/clock'
if robot_index == 0
else f'/{namespace}/clock'
)
),
'clock_topic': PythonExpression([
"'/clock' if (str('",
has_clock,
"').lower() in ('true', '1') and ",
f"{robot_index} == 0) else '/{namespace}/clock'",
]),
'x_pose': TextSubstitution(text=str(init_pose['x'])),
'y_pose': TextSubstitution(text=str(init_pose['y'])),
'z_pose': TextSubstitution(text=str(init_pose['z'])),
Expand Down Expand Up @@ -244,6 +278,11 @@ def make_group(robot_autostart, condition, ready_node=None):
ld.add_action(declare_use_robot_state_pub_cmd)
ld.add_action(declare_use_navigation_cmd)
ld.add_action(declare_staged_startup_cmd)
ld.add_action(declare_use_simulator_cmd)
ld.add_action(declare_start_gazebo_cmd)
ld.add_action(declare_has_clock_cmd)
ld.add_action(declare_gz_partition_cmd)
ld.add_action(SetEnvironmentVariable('GZ_PARTITION', LaunchConfiguration('gz_partition')))

# initial localization node
for robot_name in robots_list:
Expand Down
Loading