Setup
DC 2.0 ships as published container images by default — podman compose or podman run, no ROS 2 toolchain to install locally. It is also an ordinary ROS 2 workspace if
you'd rather build natively: rosdep install, colcon build, done — no forked shipper
to compile, no Go toolchain, nothing needs root.
Containerized
The default, recommended way to run DC — nothing to build, nothing but Podman required.
Quick run
No build needed — the published :jazzy images run the all-in-one shape (every ROS
node, the Bridge and the Shipper in one dc-ros container) directly against a local
Postgres, with RustFS available alongside it for a files/S3 Destination. Isolated
network by default — dc-ros reaches the stores by container name, not the host's
network — so the commands below run from deploy/robot/.
podman compose, all three containers, one command — the fastest path if you don't
need to watch each container's own output separately:
podman compose -f compose.aio.yaml -f compose.isolated-network.yaml -f compose.local-destinations.yaml up
podman run, one step at a time — same three containers, split so each command
can be run and checked before the next, in its own terminal:
-
Network and volumes:
podman network create dc_robot_net podman volume create dc_robot_pgdata podman volume create dc_robot_rustfs_data podman volume create dc_robot_aio_buffer -
Postgres, pinned by digest — bump deliberately, check https://hub.docker.com/_/postgres/tags?name=13 for a newer one:
# PostgreSQL 13.23 podman run --rm -it --network dc_robot_net --name dc_robot_postgres \ -e POSTGRES_USER=dc -e POSTGRES_PASSWORD=password -e POSTGRES_DB=dc \ -p 5432:5432 -v dc_robot_pgdata:/var/lib/postgresql/data \ docker.io/library/postgres@sha256:4689940c683801b4ab839ab3b0a0a3555a5fe425371422310944e89eca7d8068Wait for
database system is ready to accept connectionsbefore moving on. -
RustFS, pinned by digest (matches
compose.local-destinations.yaml— bump deliberately, check https://hub.docker.com/r/rustfs/rustfs/tags for the new one):# RustFS v1.0.0-beta.11 podman run --rm -it --network dc_robot_net --name dc_robot_rustfs \ -p 9000:9000 -v dc_robot_rustfs_data:/data \ docker.io/rustfs/rustfs@sha256:84ce557a0245a06a9aae5516f55ee0f007fca78d41df356f419306fdc0cb168c -
dc-ros— on the isolated network,127.0.0.1no longer reaches Postgres, so this needs a params override pointed at the hostnamepostgresinstead of the image's own baked-in127.0.0.1default:podman run --rm -it --network dc_robot_net --name dc_robot_aio \ -v dc_robot_aio_buffer:/root/.dc/buffer \ -v "$(pwd)/params/aio_params_local.yaml:/opt/dc/dc_params.yaml:ro" \ ghcr.io/minipada/ros2_data_collection/dc-ros:jazzy \ dc_params_file:=/opt/dc/dc_params.yaml -
Check Records are landing, from a fourth terminal:
psql -h 127.0.0.1 -U dc -d dc -c 'select * from dc order by date desc limit 5;'Password
password.
See
deploy/robot/README.md
for the three-container split topology, the host-network variant, and trying it against
a real store before fleet rollout.
Building the workspace image
The repository builds a full workspace image with Podman — the same one CI uses:
IMAGE_TAG=dc-workspace:local ./tools/e2e/scripts/build.sh
tools/e2e/scripts/test.sh runs colcon test against that image, and
tools/e2e/scripts/run.sh drives the zero-loss end-to-end harness. See
tools/e2e/README.md.
Deployment renderings and a local Kubernetes loop
deploy/robot/ describes the three-container robot tier (dc-ros, vector,
dc-uploader — see Deployment modes)
as Compose, Podman Quadlet and Kubernetes manifests, for whichever a site already runs. For
iterating on the Kubernetes rendering itself, a loop of plain podman build,
k3d and kubectl commands brings up a disposable local cluster in
seconds — no wrapper script, no registry, just the commands themselves. See
deploy/robot/README.md
for the full command sequence and what each step is for.
k3d's default CNI does not enforce NetworkPolicy, so it cannot validate the fleet's
network-isolation claims. It is the fast inner loop only, deliberately not the
production-parity check.
Native
For developing DC itself, or wherever containers aren't an option.
Requirements
- ROS 2 Jazzy (
ros-jazzy-ros-baseor larger), on Ubuntu 24.04 or a Debian equivalent colcon,rosdep,git,vcstool(python3-vcstool), a C++17 compiler- x86-64 or aarch64 — the architectures
vector_vendorhas a pinned Vector binary for
Build
-
Clone into a workspace:
mkdir -p ~/ws/src && cd ~/ws/src git clone https://github.com/minipada/ros2_data_collection.git -
Pull in
vector_vendorandaws_sdk_vendor(both their own repos — see ADR-0002's amendment and ADR-0012), register DC's local rosdep rules (two header-only C++ libraries upstream rosdistro has no key for), then resolve dependencies:cd ~/ws vcs import src < src/ros2_data_collection/ros2_data_collection.repos echo "yaml file://$PWD/src/ros2_data_collection/rosdep/dc.yaml" \ | sudo tee /etc/ros/rosdep/sources.list.d/10-dc.list rosdep update rosdep install --from-paths src --ignore-src -r -y -
Build:
source /opt/ros/jazzy/setup.bash colcon build
That is the whole install. colcon build also runs vector_vendor, which fetches a
pinned, checksummed Vector release tarball live — the external
Shipper the Bridge supervises at runtime
(ADR-0002) — and aws_sdk_vendor, which
fetches and builds the AWS SDK for C++ (core + s3) dc_uploader uses
(ADR-0014) live from github.com/aws/aws-sdk-cpp
at a pinned tag; both steps need network access
(ADR-0002,
ADR-0012), and aws_sdk_vendor's takes
several minutes the first time.
Python dependencies
Only some Measurement plugins (camera inspection, QR code detection) need Python
packages beyond what ROS 2 installs. rosdep covers the ones with rosdistro keys; for
the rest, uv installs pyproject.toml's pins into a
project virtualenv:
uv sync --no-dev # drop --no-dev to add the tooling and the demo dashboard's packages
Run
source install/setup.bash
ros2 launch dc_bringup dc_bringup.launch.py
The default parameters file (dc_bringup/params/dc_params.yaml) collects uptime and
writes it to a local PostgreSQL Destination. To run your own:
ros2 launch dc_bringup dc_bringup.launch.py dc_params_file:=/path/to/my_params.yaml
See Configuration examples for configurations you can copy, and Destinations for the full Bridge configuration contract.
Useful launch arguments
| Argument | Default | Description |
|---|---|---|
dc_params_file | dc_params.yaml | Parameters file for every DC node |
group_node | False | Start the Group node (needed by any group_server config) |
namespace | "" | Top-level namespace |
log_level | info | Log level for the DC nodes |
autostart | True | Let the lifecycle manager configure and activate the nodes |
use_sim_time | False | Use simulation (Gazebo) clock — set True against a simulator, or TF lookups run on the wall clock while the sim publishes on its own clock and drift into "extrapolation" errors |
run_uploader | True | Launch dc_uploader (ADR-0014) from this process. Set False when it runs in its own container instead (the three-container split) |
What starts, in what order
dc_bringup.launch.py brings the pipeline up deterministically
(ADR-0006): the Bridge
and its Shipper first, then a readiness gate, and only then the collection nodes. If the
Shipper never becomes ready, the launch shuts down loudly instead of collecting data
nowhere. Data Pipeline describes this in full.
Advanced build options
Point the build at a Vector binary you already have instead of downloading one:
colcon build --cmake-args -Dvector_path=/usr/bin/vector
The VECTOR_PATH environment variable does the same thing.
Infrastructure
DC delivers to systems you run yourself. tools/infrastructure/docker/ has compose
files that bring up PostgreSQL and RustFS (S3-compatible object storage) preconfigured
for the demos; see Infrastructure setup.
Issues
If you run into problems building DC, search the issue tracker on GitHub and feel free to open a ticket.