Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,54 @@ You can then download and run the script:
```bash
bash <(curl https://raw.githubusercontent.com/3LawsRobotics/3laws/master/install_ros2.sh)
```
## Docker runtime environment

A sample Docker project is provided to assist users who prefer to install and execute Supervisor within a controlled environment. The project is not designed to meet any production-grade requirements, but rather to provide a starting point for further development.

From the root directory of this project, run `./docker/build_docker.bash <ROS_DISTRO>` to create the runtime Docker image. Replace `<ROS_DISTRO>` with either `humble` or `jazzy`. When building is complete, run `./docker/run_docker.bash <ROS_DISTRO>` to start the container.

The start script creates a docker managed volume mounted at `~/.3laws`. The volume is used to store Supervisor configurations so that all savings and progresses persists across restarts of the container.

In alternative to manually starting the container via the provided script, it is possible to call the script directly from a ROS 2 launch file:

```python
import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import ExecuteProcess


def generate_launch_description():
DOCKER_RUN_SCRIPT = os.path.join(
<path/to/3laws/docker>,
"run_docker.bash",
)

launchdesc = LaunchDescription(
[
ExecuteProcess(
cmd=[DOCKER_RUN_SCRIPT],
shell=True,
output="screen",
name="lll_supervisor_docker",
)
]
)

return launchdesc

```


IMPORTANT: When running the container for the first time, the Supervisor node will fail as no configuration file exists yet. Configure Supervisor through the Control Panel and restart the container.

When running the provided container, a `rosbridge_websocket` node and 3Laws Control Panel are started by the `entrypoint.sh` in the background inside dedicated `screen` sessions. At this point, you can follow the configuration steps described in the [Official Documentation](https://docs.3laws.io/en/latest/).

Once the Supervisor configuration is complete, you can start the Supervisor from within the container via
```bash
ros2 launch lll_supervisor supervisor.launch.py
```

## Repo maintainer

Expand Down
31 changes: 31 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
ARG ROS_DISTRO=humble
ARG BASE_IMAGE=ros:$ROS_DISTRO-ros-core
FROM $BASE_IMAGE

## Sup options
ARG ASSET_ID
ARG ASSET_NAME

## Install some packages
RUN apt-get update && \
apt-get install -y --no-install-recommends \
sudo \
software-properties-common \
screen \
vim \
ros-$ROS_DISTRO-rosbridge-server

## Get Supervisor
ENV GH_REPO="https://api.github.com/repos/3LawsRobotics/3laws"

## Install Supervisor
WORKDIR /tmp
ARG CURL_ARGS="-LJO#"
ARG GH_ASSET="$GH_REPO/releases/assets/$ASSET_ID"
RUN curl $CURL_ARGS -s -H 'Accept: application/octet-stream' "$GH_ASSET"
RUN sudo apt install -f ./"$ASSET_NAME" -y --no-install-recommends

## Add entrypoint
WORKDIR /
COPY entrypoint.sh /root/entrypoint.sh
ENTRYPOINT ["/root/entrypoint.sh"]
34 changes: 34 additions & 0 deletions docker/build_docker.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/bash

DOCKER_IMAGE_NAME="lll-supervisor-runtime"

# Get ROS_DISTRO from first argument, error if not provided
if [ -z "$1" ]; then
echo "Usage: $0 <ROS_DISTRO>. Specify jazzy|humble"
exit 1
fi

# Check if provided ROS_DISTRO is either "jazzy" or "humble"
if [ "$1" != "jazzy" ] && [ "$1" != "humble" ]; then
echo "Error - supported ROS_DISTRO values are: jazzy|humble"
exit 1
fi
TAG=$1

GH_REPO="https://api.github.com/repos/3LawsRobotics/3laws/releases/latest"
PACKAGE_NAME="lll-supervisor-full-${TAG}"
REGEX_QUERY="${PACKAGE_NAME}_[0-9]\+\.[0-9]\+\.[0-9]\+-[0-9]\+_amd64_ubuntu[0-9]\+.[0-9]\+"

# Read asset tags.
RESPONSE=$(curl -s -H "application/vnd.github+json" $GH_REPO)
ASSET_NAME=$(echo "$RESPONSE" | grep -o "name.:.\+${REGEX_QUERY}.deb" | cut -d ":" -f2- | cut -d "\"" -f2-)
ASSET_ID=$(echo "$RESPONSE" | grep -C3 "name.:.\+$REGEX_QUERY" | grep -w id | tr : = | tr -cd '[[:alnum:]]=' | cut -d'=' -f2-)

echo "Building Docker image $DOCKER_IMAGE_NAME:$TAG with asset $ASSET_NAME (id: $ASSET_ID)"

docker build --rm \
--build-arg ROS_DISTRO="$TAG" \
--build-arg ASSET_ID="$ASSET_ID" \
--build-arg ASSET_NAME="$ASSET_NAME" \
-t "$DOCKER_IMAGE_NAME:$TAG" \
-f "$(pwd)/Dockerfile" .
9 changes: 9 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

set -e # Exit immediately if a command exits with a non-zero status

screen -dmS lll_rosbridge bash -lc "source /opt/ros/$ROS_DISTRO/setup.bash && exec ros2 launch rosbridge_server rosbridge_websocket_launch.xml port:=9091"

screen -dmS lll_control_panel /opt/3laws/control_panel/control-panel-backend 8000 /opt/3laws/control_panel/build/

source /opt/ros/humble/setup.bash && exec "$@"
35 changes: 35 additions & 0 deletions docker/run_docker.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash

set -e # Exit on error, print commands, and treat unset variables as an error

TAG="$1"
IMAGE_NAME="lll-supervisor-runtime"

# Get all tags for the image
tags=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep "^${IMAGE_NAME}:" | cut -d: -f2)

# Check if TAG exists in tags
if echo "$tags" | grep -q "^${TAG}$"; then
IMAGE_TAG=$TAG
else
echo "Selected tag '$TAG' not found. Available tags are:"
echo "$tags"
exit 1
fi

DOCKER_HOME=/
DOCKER_LLL_CONFIG_DIR="$DOCKER_HOME/.3laws/config"
IMAGE_NAME="lll-supervisor-runtime"

# Check if Docker image exists
if ! docker image inspect $IMAGE_NAME:$IMAGE_TAG >/dev/null 2>&1; then
echo "Docker image $IMAGE_NAME:$IMAGE_TAG not found. Run build_docker.bash first to create image."
exit 1
fi

docker volume create lll_supervisor_config
docker run --privileged --rm -it \
--name lll-supervisor \
--net=host \
-v lll_supervisor_config:/$DOCKER_LLL_CONFIG_DIR/ \
"$IMAGE_NAME":"$IMAGE_TAG" bash