Skip to content

Instantly share code, notes, and snippets.

@MarcoDotIO
Created April 16, 2026 08:50
Show Gist options
  • Select an option

  • Save MarcoDotIO/851d3f64a431e43f154fa23f81d586ef to your computer and use it in GitHub Desktop.

Select an option

Save MarcoDotIO/851d3f64a431e43f154fa23f81d586ef to your computer and use it in GitHub Desktop.
ROSClaw Installation Script
#!/usr/bin/env bash
set -euo pipefail
log() {
printf '[install_rosclaw] %s\n' "$*"
}
fail() {
printf '[install_rosclaw] %s\n' "$*" >&2
exit 1
}
source_setup() {
local setup_file=$1
set +u
# shellcheck disable=SC1090
source "${setup_file}"
set -u
}
ensure_git_checkout() {
local repo_url=$1
local repo_ref=$2
local checkout_dir=$3
if [[ -d "${checkout_dir}/.git" || -f "${checkout_dir}/.git" ]]; then
log "Using existing checkout ${checkout_dir}"
return 0
fi
if [[ -e "${checkout_dir}" ]]; then
fail "Path exists but is not a git checkout: ${checkout_dir}"
fi
log "Cloning ${repo_url} (${repo_ref}) into ${checkout_dir}"
git clone --branch "${repo_ref}" --single-branch "${repo_url}" "${checkout_dir}"
}
ensure_rosdep_ready() {
if [[ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]]; then
log "Initializing rosdep"
sudo rosdep init
fi
log "Updating rosdep indexes"
rosdep update
}
ensure_openclaw_on_path() {
if command -v openclaw >/dev/null 2>&1; then
return 0
fi
if command -v npm >/dev/null 2>&1; then
export PATH="$(npm prefix -g)/bin:${PATH}"
hash -r
fi
command -v openclaw >/dev/null 2>&1
}
install_ros2_repo_if_needed() {
if dpkg -s ros2-apt-source >/dev/null 2>&1; then
return 0
fi
log "Installing ROS 2 apt source package"
export ROS_APT_SOURCE_VERSION
ROS_APT_SOURCE_VERSION=$(
curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest \
| grep -F '"tag_name"' \
| awk -F'"' '{print $4}'
)
curl -L -o /tmp/ros2-apt-source.deb \
"https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
sudo dpkg -i /tmp/ros2-apt-source.deb
}
OS_CODENAME=$(. /etc/os-release && echo "${UBUNTU_CODENAME:-}")
if [[ "${OS_CODENAME}" != "noble" ]]; then
fail "This script is intended for Ubuntu 24.04 (noble)."
fi
DEV_ROOT=${DEV_ROOT:-"${HOME}/dev"}
ROS_DISTRO=${ROS_DISTRO:-jazzy}
EXAMPLE_REPO=${EXAMPLE_REPO:-https://github.com/ROSClaw/rosclaw-example-turtlebot}
EXAMPLE_REF=${EXAMPLE_REF:-main}
PLUGIN_REPO=${PLUGIN_REPO:-https://github.com/ROSClaw/rosclaw-plugin}
PLUGIN_REF=${PLUGIN_REF:-main}
ROSCLAW_ROS2_REPO=${ROSCLAW_ROS2_REPO:-https://github.com/ROSClaw/rosclaw-ros2.git}
ROSCLAW_ROS2_REF=${ROSCLAW_ROS2_REF:-main}
ROSCLAW_AUTONOMY_REPO=${ROSCLAW_AUTONOMY_REPO:-https://github.com/ROSClaw/rosclaw-ros2-autonomy.git}
ROSCLAW_AUTONOMY_REF=${ROSCLAW_AUTONOMY_REF:-main}
AWS_WORLD_REPO=${AWS_WORLD_REPO:-https://github.com/aws-robotics/aws-robomaker-small-house-world.git}
AWS_WORLD_REF=${AWS_WORLD_REF:-ros2}
INSTALL_OPENCLAW=${INSTALL_OPENCLAW:-1}
INSTALL_PLUGIN=${INSTALL_PLUGIN:-1}
BUILD_WORKSPACE=${BUILD_WORKSPACE:-1}
BUILD_PARALLEL_WORKERS=${BUILD_PARALLEL_WORKERS:-}
log "Installing base packages"
sudo apt update
sudo apt install -y \
software-properties-common \
curl \
ca-certificates \
git \
gnupg \
lsb-release \
build-essential \
python3-rosdep \
python3-colcon-common-extensions \
python3-vcstool \
ros-dev-tools
log "Ensuring ROS 2 repository is configured"
sudo add-apt-repository universe -y
install_ros2_repo_if_needed
log "Installing ROS 2 Jazzy + Gazebo Harmonic + rosbridge"
sudo apt update
sudo apt install -y \
ros-jazzy-desktop \
ros-jazzy-ros-gz \
ros-jazzy-rosbridge-server
if ! grep -Fq "source /opt/ros/jazzy/setup.bash" "${HOME}/.bashrc"; then
echo "source /opt/ros/jazzy/setup.bash" >> "${HOME}/.bashrc"
fi
source_setup "/opt/ros/${ROS_DISTRO}/setup.bash"
ensure_rosdep_ready
if [[ "${INSTALL_OPENCLAW}" == "1" ]]; then
if ! ensure_openclaw_on_path; then
log "Installing OpenClaw (onboarding skipped)"
curl -fsSL https://openclaw.ai/install.sh | bash -s -- --no-onboard
ensure_openclaw_on_path || fail "OpenClaw installed but is not on PATH"
fi
fi
mkdir -p "${DEV_ROOT}"
EXAMPLE_DIR="${DEV_ROOT}/rosclaw-example-turtlebot"
PLUGIN_DIR="${DEV_ROOT}/rosclaw-plugin"
GAZEBO_WS="${EXAMPLE_DIR}/simulations/gazebo"
GAZEBO_SRC="${GAZEBO_WS}/src"
ensure_git_checkout "${EXAMPLE_REPO}" "${EXAMPLE_REF}" "${EXAMPLE_DIR}"
ensure_git_checkout "${PLUGIN_REPO}" "${PLUGIN_REF}" "${PLUGIN_DIR}"
log "Updating example submodules"
git -C "${EXAMPLE_DIR}" submodule update --init --recursive
mkdir -p "${GAZEBO_SRC}"
ensure_git_checkout "${ROSCLAW_ROS2_REPO}" "${ROSCLAW_ROS2_REF}" "${GAZEBO_SRC}/rosclaw-ros2"
ensure_git_checkout "${ROSCLAW_AUTONOMY_REPO}" "${ROSCLAW_AUTONOMY_REF}" "${GAZEBO_SRC}/rosclaw-ros2-autonomy"
ensure_git_checkout "${AWS_WORLD_REPO}" "${AWS_WORLD_REF}" "${GAZEBO_SRC}/aws-robomaker-small-house-world"
if [[ "${INSTALL_PLUGIN}" == "1" ]] && ensure_openclaw_on_path; then
log "Installing OpenClaw plugin"
openclaw plugins install "${PLUGIN_DIR}" || true
openclaw gateway restart || true
fi
log "Installing ROS package dependencies with rosdep"
(
cd "${GAZEBO_WS}"
rosdep install \
--from-paths src \
--ignore-src \
--rosdistro "${ROS_DISTRO}" \
-r -y \
--skip-keys ament_python
)
if [[ "${BUILD_WORKSPACE}" == "1" ]]; then
log "Building Gazebo workspace"
colcon_args=(
build
--base-paths src
--packages-up-to rosclaw_bringup rosclaw_autonomy rosclaw_small_house_gazebo
--cmake-args -DPython3_EXECUTABLE=/usr/bin/python3
)
if [[ -n "${BUILD_PARALLEL_WORKERS}" ]]; then
colcon_args+=(--parallel-workers "${BUILD_PARALLEL_WORKERS}")
fi
(
cd "${GAZEBO_WS}"
colcon "${colcon_args[@]}"
)
fi
log "Install complete"
log "Next:"
log " cd ${GAZEBO_WS}"
log " ./launch_small_house.sh"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment