From cef7b92e4573fbd8d3652f396fe24c5840c588f6 Mon Sep 17 00:00:00 2001 From: Rafal Gorecki <126687345+rafal-gorecki@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:30:07 +0100 Subject: [PATCH] Jazzy docker (#125) * Add hardware and sim Docker * Fix hardware docker * Fixes * Fixes * Simulation gz_gui fixes + use TwistStamped * Use packages-up-to --- .github/workflows/tests.yaml | 97 +++++++++++++------------ README.md | 4 +- docker/.env | 3 +- docker/Dockerfile | 29 -------- docker/Dockerfile.hardware | 35 +++++++++ docker/Dockerfile.simulation | 36 +++++++++ docker/compose.hardware.yaml | 22 ++++++ docker/compose.simulation.yaml | 32 ++++++++ docker/compose.yaml | 19 ----- docker/justfile | 14 ++-- rosbot/package.xml | 4 +- rosbot/rosbot_simulation.repos | 2 +- rosbot_gazebo/config/gz_remappings.yaml | 26 +++---- rosbot_gazebo/package.xml | 3 - 14 files changed, 199 insertions(+), 127 deletions(-) delete mode 100644 docker/Dockerfile create mode 100644 docker/Dockerfile.hardware create mode 100644 docker/Dockerfile.simulation create mode 100644 docker/compose.hardware.yaml create mode 100644 docker/compose.simulation.yaml delete mode 100644 docker/compose.yaml diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index e826c2ac..a6323506 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -1,55 +1,56 @@ --- -name: Run Tests + name: Run Tests -on: - workflow_call: - workflow_dispatch: + on: + workflow_call: + workflow_dispatch: -jobs: - black: - name: Black - runs-on: ubuntu-24.04 - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Black - uses: psf/black@23.11.0 - with: - options: --line-length=99 + jobs: + black: + name: Black + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Black + uses: psf/black@23.11.0 + with: + options: --line-length=99 - industrial_ci: - name: Industrial CI - runs-on: ubuntu-24.04 - timeout-minutes: 30 - strategy: - fail-fast: false - matrix: - ROS_DISTRO: [jazzy] - steps: - - name: Checkout - uses: actions/checkout@v3 + industrial_ci: + name: Industrial CI + runs-on: ubuntu-24.04 + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + ROS_DISTRO: [jazzy] + steps: + - name: Checkout + uses: actions/checkout@v3 - - name: Setup ROS2 Workspace and Clone Repositories - run: | - mkdir -p src - find . -maxdepth 1 -not -name src -not -name . -exec mv {} src/ \; - python3 -m pip install -U vcstool - vcs import src < src/rosbot/rosbot_hardware.repos - vcs import src < src/rosbot/rosbot_simulation.repos - cp -r src/ros2_controllers/imu_sensor_broadcaster src/ - rm -rf src/ros2_controllers + - name: Setup ROS2 Workspace and Clone Repositories + run: | + mkdir -p src + find . -maxdepth 1 -not -name src -not -name . -exec mv {} src/ \; + python3 -m pip install -U vcstool + vcs import src < src/rosbot/rosbot_hardware.repos + vcs import src < src/rosbot/rosbot_simulation.repos + cp -r src/ros2_controllers/imu_sensor_broadcaster src/ + rm -rf src/ros2_controllers - # Package micro_ros_msgs does not have industrial ci and tests does not pass. - # For more information see https://github.com/micro-ROS/micro_ros_msgs/issues/7 - - name: Leave only ROSbot tests - shell: bash - run: | - sed '/if(BUILD_TESTING)/,/endif()/d' src/imu_sensor_broadcaster/CMakeLists.txt -i - sed '/if(BUILD_TESTING)/,/endif()/d' src/micro_ros_msgs/CMakeLists.txt -i + # Package micro_ros_msgs does not have industrial ci and tests does not pass. + # For more information see https://github.com/micro-ROS/micro_ros_msgs/issues/7 + - name: Leave only ROSbot tests + shell: bash + run: | + sed '/if(BUILD_TESTING)/,/endif()/d' src/imu_sensor_broadcaster/CMakeLists.txt -i + sed '/if(BUILD_TESTING)/,/endif()/d' src/micro_ros_msgs/CMakeLists.txt -i - - name: Running ROS Industrial CI - uses: ros-industrial/industrial_ci@master - env: - ROS_DISTRO: ${{matrix.ROS_DISTRO}} - DOCKER_IMAGE: ros:${{matrix.ROS_DISTRO}}-ros-base - IMMEDIATE_TEST_OUTPUT: true + - name: Running ROS Industrial CI + uses: ros-industrial/industrial_ci@master + env: + PIP_BREAK_SYSTEM_PACKAGES: 1 + ROS_DISTRO: ${{matrix.ROS_DISTRO}} + DOCKER_IMAGE: ros:${{matrix.ROS_DISTRO}}-ros-base + IMMEDIATE_TEST_OUTPUT: true diff --git a/README.md b/README.md index 676fd890..b6a697b9 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ rm -r src/rosbot_ros/rosbot_gazebo sudo rosdep init rosdep update --rosdistro $ROS_DISTRO rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y -colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release +colcon build --symlink-install --packages-up-to rosbot --cmake-args -DCMAKE_BUILD_TYPE=Release ``` Flash firmware: @@ -106,7 +106,7 @@ cp -r src/ros2_controllers/imu_sensor_broadcaster src && rm -rf src/ros2_control sudo rosdep init rosdep update --rosdistro $ROS_DISTRO rosdep install -i --from-path src --rosdistro $ROS_DISTRO -y -colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release +colcon build --symlink-install --packages-up-to rosbot --cmake-args -DCMAKE_BUILD_TYPE=Release ``` Running: diff --git a/docker/.env b/docker/.env index 9a9566ef..05b532ca 100644 --- a/docker/.env +++ b/docker/.env @@ -1,2 +1 @@ -SERIAL_PORT=/dev/ttyUSB0 -ROS_NAMESPACE=robot1 +ROBOT_NAMESPACE=rosbot diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index ddcc16e1..00000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -ARG ROS_DISTRO=jazzy - -FROM husarnet/ros:${ROS_DISTRO}-ros-base - -SHELL ["/bin/bash", "-c"] - -WORKDIR /ros2_ws - -COPY . src/ - -RUN apt-get update && apt-get install -y \ - python3-pip \ - stm32flash \ - ros-${ROS_DISTRO}-teleop-twist-keyboard - -RUN vcs import src < src/rosbot/rosbot_hardware.repos && \ - rm -r src/rosbot_gazebo - -# Create a script to install runtime dependencies for final image -RUN apt update && \ - rosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} --reinstall --simulate -y --dependency-types exec >> /rosdep_install.sh && \ - chmod +x /rosdep_install.sh - -RUN apt update && \ - rosdep install --from-paths src --ignore-src --rosdistro=${ROS_DISTRO} -y && \ - source /opt/ros/$ROS_DISTRO/setup.bash && \ - colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release && \ - echo $(cat /ros2_ws/src/rosbot/package.xml | grep '' | sed -r 's/.*([0-9]+.[0-9]+.[0-9]+)<\/version>/\1/g') >> /version.txt && \ - rm -rf build log src diff --git a/docker/Dockerfile.hardware b/docker/Dockerfile.hardware new file mode 100644 index 00000000..374032e6 --- /dev/null +++ b/docker/Dockerfile.hardware @@ -0,0 +1,35 @@ +ARG ROS_DISTRO=jazzy + +FROM husarnet/ros:${ROS_DISTRO}-ros-core + +WORKDIR /ros2_ws + +ENV HUSARION_ROS_BUILD_TYPE=hardware +ENV PIP_BREAK_SYSTEM_PACKAGES=1 + +COPY .. src/rosbot_ros + +RUN apt-get update && apt-get install -y \ + python3-pip \ + ros-dev-tools \ + stm32flash \ + ros-${ROS_DISTRO}-teleop-twist-keyboard && \ + # Setup workspace + vcs import src < src/rosbot_ros/rosbot/rosbot_hardware.repos && \ + rm -r src/rosbot_ros/rosbot_gazebo && \ + # Install dependencies + rosdep init && \ + rosdep update --rosdistro $ROS_DISTRO && \ + rosdep install --from-paths src -y -i && \ + # Build + source /opt/ros/$ROS_DISTRO/setup.bash && \ + colcon build --symlink-install --packages-up-to rosbot --cmake-args -DCMAKE_BUILD_TYPE=Release && \ + # Get version + echo $(cat /ros2_ws/src/rosbot/package.xml | grep '' | sed -r 's/.*([0-9]+.[0-9]+.[0-9]+)<\/version>/\1/g') >> /version.txt && \ + # Size optimization + export SUDO_FORCE_REMOVE=yes && \ + apt-get remove -y \ + ros-dev-tools && \ + apt-get autoremove -y && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* diff --git a/docker/Dockerfile.simulation b/docker/Dockerfile.simulation new file mode 100644 index 00000000..37985f12 --- /dev/null +++ b/docker/Dockerfile.simulation @@ -0,0 +1,36 @@ +ARG ROS_DISTRO=jazzy + +FROM husarnet/ros:${ROS_DISTRO}-ros-core + +WORKDIR /ros2_ws + +ENV HUSARION_ROS_BUILD_TYPE=simulation +ENV PIP_BREAK_SYSTEM_PACKAGES=1 + +COPY .. src/rosbot_ros + +RUN apt-get update && apt-get install -y \ + python3-pip \ + ros-dev-tools \ + stm32flash \ + ros-${ROS_DISTRO}-teleop-twist-keyboard && \ + # Setup workspace + vcs import src < src/rosbot_ros/rosbot/rosbot_hardware.repos && \ + vcs import src < src/rosbot_ros/rosbot/rosbot_simulation.repos && \ + rm -rf src/ros2_controllers && \ + # Install dependencies + rosdep init && \ + rosdep update --rosdistro $ROS_DISTRO && \ + rosdep install --from-paths src -y -i && \ + # Build + source /opt/ros/$ROS_DISTRO/setup.bash && \ + colcon build --symlink-install --packages-up-to rosbot --cmake-args -DCMAKE_BUILD_TYPE=Release && \ + # Get version + echo $(cat /ros2_ws/src/rosbot/package.xml | grep '' | sed -r 's/.*([0-9]+.[0-9]+.[0-9]+)<\/version>/\1/g') >> /version.txt && \ + # Size optimization + export SUDO_FORCE_REMOVE=yes && \ + apt-get remove -y \ + ros-dev-tools && \ + apt-get autoremove -y && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/docker/compose.hardware.yaml b/docker/compose.hardware.yaml new file mode 100644 index 00000000..3ebcf58e --- /dev/null +++ b/docker/compose.hardware.yaml @@ -0,0 +1,22 @@ +# Quick Start +# +# 1. Run `docker compose -f compose.hardware.yaml up` on the ROSbot +# 2. Open a shell inside a docker container `docker compose -f compose.hardware.yaml exec -it rosbot bash` +# 3. Run `ros2 run teleop_twist_keyboard teleop_twist_keyboard` inside the container + +services: + rosbot: + build: + context: .. + dockerfile: docker/Dockerfile.hardware + network_mode: host + ipc: host + restart: unless-stopped + devices: + - ${SERIAL_PORT:-/dev/ttyUSB0} + - /dev/bus/usb/ # FTDI + command: > + ros2 launch rosbot_bringup combined.launch.py + mecanum:=${MECANUM:-False} + namespace:=${ROBOT_NAMESPACE:-rosbot} + serial_port:=${SERIAL_PORT:-/dev/ttyUSB0} diff --git a/docker/compose.simulation.yaml b/docker/compose.simulation.yaml new file mode 100644 index 00000000..9194cda1 --- /dev/null +++ b/docker/compose.simulation.yaml @@ -0,0 +1,32 @@ +# Quick Start +# +# 1. Run `xhost +local:docker && docker compose -f compose.simulation.yaml up` on the laptop +# (optionally you can chang `gpu-config` -> `cpu config`). +# 2. Open a shell inside a docker container `docker compose -f compose.simulation.yaml exec -it rosbot bash` +# 3. Run `ros2 run teleop_twist_keyboard teleop_twist_keyboard` inside the container + +x-gpu-config: + &gpu-config + runtime: nvidia + environment: + - DISPLAY=${DISPLAY:?err} + - NVIDIA_VISIBLE_DEVICES=all + - NVIDIA_DRIVER_CAPABILITIES=all + +x-cpu-config: + &cpu-config + environment: + - DISPLAY=${DISPLAY:?err} + +services: + rosbot: + build: + context: .. + dockerfile: docker/Dockerfile.simulation + network_mode: host + ipc: host + <<: [ *gpu-config] + command: > + ros2 launch rosbot_gazebo simulation.launch.py + mecanum:=${MECANUM:-False} + namespace:=${ROBOT_NAMESPACE:-rosbot} diff --git a/docker/compose.yaml b/docker/compose.yaml deleted file mode 100644 index fb9aaf96..00000000 --- a/docker/compose.yaml +++ /dev/null @@ -1,19 +0,0 @@ -services: - rosbot: - build: - context: .. - dockerfile: docker/Dockerfile - network_mode: host - ipc: host - devices: - - ${SERIAL_PORT:?err} - - /dev/bus/usb/ # FTDI - # environment: - # - ROS_NAMESPACE - # command: tail -f /dev/null - command: > - ros2 launch rosbot_bringup combined.launch.py - mecanum:=${MECANUM:-False} - serial_port:=$SERIAL_PORT - serial_baudrate:=576000 - # namespace:=${ROS_NAMESPACE:-rosbot} diff --git a/docker/justfile b/docker/justfile index 50fbe34d..0e6f5ef4 100644 --- a/docker/justfile +++ b/docker/justfile @@ -13,7 +13,7 @@ alias teleop := run-teleop-docker # run teleop_twist_keybaord (inside rviz2 container) run-teleop-docker: _run-as-user #!/bin/bash - docker compose exec rosbot /bin/bash -c "/ros_entrypoint.sh ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -r __ns:=/${ROS_NAMESPACE}" + docker compose exec rosbot /bin/bash -c "/ros_entrypoint.sh ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -r __ns:=/${ROBOT_NAMESPACE}" flash-firmware: _install-yq _run-as-user #!/bin/bash @@ -29,9 +29,9 @@ flash-firmware: _install-yq _run-as-user gpio_chip=/dev/gpiochip4 serial_port=/dev/ttyS4 else - echo "Probably user laptop" + echo "Probably user computer" gpio_chip=/dev/bus/usb - serial_port=$SERIAL_PORT + serial_port=/dev/ttyUSB0 enable_usb="--usb" fi @@ -42,13 +42,13 @@ flash-firmware: _install-yq _run-as-user docker-rosbot \ ros2 run rosbot_utils flash_firmware ${enable_usb} -run: +run_hardware: #/bin/bash - docker compose up + docker compose -f compose.hardware.yaml up -build: +build_hardware: #/bin/bash - docker compose build + docker compose -f compose.hardware.yaml build _run-as-root: #!/bin/bash diff --git a/rosbot/package.xml b/rosbot/package.xml index 6ad78787..b39ffd53 100644 --- a/rosbot/package.xml +++ b/rosbot/package.xml @@ -20,10 +20,8 @@ rosbot_bringup rosbot_controller rosbot_description - - rosbot_utils - rosbot_gazebo + rosbot_utils ament_cmake diff --git a/rosbot/rosbot_simulation.repos b/rosbot/rosbot_simulation.repos index ee822f11..f6bb17bb 100644 --- a/rosbot/rosbot_simulation.repos +++ b/rosbot/rosbot_simulation.repos @@ -2,7 +2,7 @@ repositories: husarion_gz_worlds: type: git url: https://github.com/husarion/husarion_gz_worlds - version: c0ff83a476f6e0bc250c763a806bf1769a00f515 + version: 7237a7d67a476a480a74ccd3a510b76a581288c3 ros2_controllers: # Bug: There is no nice way to change `sensor_name` imu_bradcaster param when spawning multiple robots -> ros2_control refer only to single imu entity type: git url: https://github.com/husarion/ros2_controllers/ diff --git a/rosbot_gazebo/config/gz_remappings.yaml b/rosbot_gazebo/config/gz_remappings.yaml index 25bb71a7..ab6feff0 100644 --- a/rosbot_gazebo/config/gz_remappings.yaml +++ b/rosbot_gazebo/config/gz_remappings.yaml @@ -1,61 +1,61 @@ --- - topic_name: /clock ros_type_name: rosgraph_msgs/msg/Clock - gz_type_name: ignition.msgs.Clock + gz_type_name: gz.msgs.Clock direction: GZ_TO_ROS - topic_name: /cmd_vel - ros_type_name: geometry_msgs/msg/Twist - gz_type_name: ignition.msgs.Twist + ros_type_name: geometry_msgs/msg/TwistStamped + gz_type_name: gz.msgs.Twist direction: GZ_TO_ROS - topic_name: /scan ros_type_name: sensor_msgs/msg/LaserScan - gz_type_name: ignition.msgs.LaserScan + gz_type_name: gz.msgs.LaserScan direction: GZ_TO_ROS - topic_name: /camera/color/camera_info ros_type_name: sensor_msgs/msg/CameraInfo - gz_type_name: ignition.msgs.CameraInfo + gz_type_name: gz.msgs.CameraInfo direction: GZ_TO_ROS - topic_name: /camera/color/image_raw ros_type_name: sensor_msgs/msg/Image - gz_type_name: ignition.msgs.Image + gz_type_name: gz.msgs.Image direction: GZ_TO_ROS - topic_name: /camera/depth/camera_info ros_type_name: sensor_msgs/msg/CameraInfo - gz_type_name: ignition.msgs.CameraInfo + gz_type_name: gz.msgs.CameraInfo direction: GZ_TO_ROS - topic_name: /camera/depth/image_raw ros_type_name: sensor_msgs/msg/Image - gz_type_name: ignition.msgs.Image + gz_type_name: gz.msgs.Image direction: GZ_TO_ROS - ros_topic_name: /camera/depth/points gz_topic_name: /camera/depth/image_raw/points ros_type_name: sensor_msgs/msg/PointCloud2 - gz_type_name: ignition.msgs.PointCloudPacked + gz_type_name: gz.msgs.PointCloudPacked direction: GZ_TO_ROS - topic_name: /range/fl ros_type_name: sensor_msgs/msg/LaserScan - gz_type_name: ignition.msgs.LaserScan + gz_type_name: gz.msgs.LaserScan direction: GZ_TO_ROS - topic_name: /range/fr ros_type_name: sensor_msgs/msg/LaserScan - gz_type_name: ignition.msgs.LaserScan + gz_type_name: gz.msgs.LaserScan direction: GZ_TO_ROS - topic_name: /range/rl ros_type_name: sensor_msgs/msg/LaserScan - gz_type_name: ignition.msgs.LaserScan + gz_type_name: gz.msgs.LaserScan direction: GZ_TO_ROS - topic_name: /range/rr ros_type_name: sensor_msgs/msg/LaserScan - gz_type_name: ignition.msgs.LaserScan + gz_type_name: gz.msgs.LaserScan direction: GZ_TO_ROS diff --git a/rosbot_gazebo/package.xml b/rosbot_gazebo/package.xml index 05997650..7c396066 100644 --- a/rosbot_gazebo/package.xml +++ b/rosbot_gazebo/package.xml @@ -24,9 +24,6 @@ husarion_gz_worlds ros_gz_sim - ros_gz_bridge gz_ros2_control nav2_common