diff --git a/aloha_ws/docker/script/xsarm_amd64_install.sh b/aloha_ws/docker/script/xsarm_amd64_install.sh new file mode 100755 index 00000000..63d4204f --- /dev/null +++ b/aloha_ws/docker/script/xsarm_amd64_install.sh @@ -0,0 +1,496 @@ +#!/usr/bin/env bash + +# USAGE: ./xsarm_amd64_install.sh [-h][-d DISTRO][-p PATH][-n] +# +# Install the Interbotix X-Series Arms packages and their dependencies. + +OFF='\033[0m' +RED='\033[0;31m' +GRN='\033[0;32m' +BLU='\033[0;34m' + +BOLD=$(tput bold) +NORM=$(tput sgr0) + +ERR="${RED}${BOLD}" +RRE="${NORM}${OFF}" + +PROMPT="> " + +ALL_VALID_DISTROS=('melodic' 'noetic' 'galactic' 'humble' 'rolling') +ROS1_VALID_DISTROS=('melodic' 'noetic') +ROS2_VALID_DISTROS=('galactic' 'humble' 'rolling') + +BIONIC_VALID_DISTROS=('melodic') +FOCAL_VALID_DISTROS=('noetic' 'galactic') +JAMMY_VALID_DISTROS=('humble' 'rolling') + +NONINTERACTIVE=false +DISTRO_SET_FROM_CL=false +INSTALL_PATH=~/interbotix_ws +APRILTAG_WS=~/apriltag_ws + +_usage="${BOLD}USAGE: ./xsarm_amd64_install.sh [-h][-d DISTRO][-p PATH][-n]${NORM} + +Install the Interbotix X-Series Arms packages and their dependencies. + +Options: + + -h Display this help message and quit + + -d DISTRO Install the DISTRO ROS distro compatible with your Ubuntu version. See + 'https://github.com/Interbotix/.github/blob/main/SECURITY.md' for the list of + supported distributions. If not given, installs the ROS 1 distro compatible with + your Ubuntu version, or the stable ROS 2 distro if using Ubuntu 22.04 or later. + + -p PATH Sets the absolute install location for the Interbotix workspace. If not specified, + the Interbotix workspace directory will default to '~/interbotix_ws'. + + -n Install all packages and dependencies without prompting. This is useful if + you're running this script in a non-interactive terminal like when building a + Docker image. + +Examples: + + ./xsarm_amd64_install.sh ${BOLD}-h${NORM} + This will display this help message and quit. + + ./xsarm_amd64_install.sh + This will install just the ROS 1 distro compatible with your Ubuntu version, or the stable ROS 2 + distro if using Ubuntu 22.04 or later. It will prompt you to ask if you want to install certain + packages and dependencies. + + ./xsarm_amd64_install.sh ${BOLD}-d noetic${NORM} + This will install ROS 1 Noetic assuming that your Ubuntu version is compatible. + + ./xsarm_amd64_install.sh ${BOLD}-n${NORM} + Skip prompts and install all packages and dependencies. + + ./xsarm_amd64_install.sh ${BOLD}-d galactic${NORM} + Install ROS 2 Galactic assuming that your Ubuntu version is compatible. + + ./xsarm_amd64_install.sh ${BOLD}-d galactic -n${NORM} + Install ROS 2 Galactic and all packages and dependencies. + + ./xsarm_amd64_install.sh ${BOLD}-p ~/custom_ws${NORM} + Installs the Interbotix packages under the '~/custom_ws' path." + +function help() { + # print usage + cat << EOF +$_usage +EOF +} + +# https://stackoverflow.com/a/8574392/16179107 +function contains_element () { + # check if an element is in an array + local e match="$1" + shift + for e; do [[ "$e" == "$match" ]] && return 0; done + return 1 +} + +function failed() { + # Log error and quit with a failed exit code + echo -e "${ERR}[ERROR] $1${RRE}" + echo -e "${ERR}[ERROR] Interbotix Installation Failed!${RRE}" + exit 1 +} + +function validate_distro() { + # check if chosen distro is valid and set ROS major version + if contains_element "$ROS_DISTRO_TO_INSTALL" "${ALL_VALID_DISTROS[@]}"; then + if contains_element "$ROS_DISTRO_TO_INSTALL" "${ROS1_VALID_DISTROS[@]}"; then + # Supported ROS 1 distros + ROS_VERSION_TO_INSTALL=1 + elif contains_element "$ROS_DISTRO_TO_INSTALL" "${ROS2_VALID_DISTROS[@]}"; then + # Supported ROS 2 distros + ROS_VERSION_TO_INSTALL=2 + else + # For cases where it passes the first check but somehow fails the second check + failed "Something went wrong. ROS_DISTRO_TO_INSTALL=$ROS_DISTRO_TO_INSTALL." + fi + echo -e "${GRN}${BOLD}Chosen Version: ROS ${ROS_VERSION_TO_INSTALL} $ROS_DISTRO_TO_INSTALL${NORM}${OFF}" + return 0 + else + failed "'$ROS_DISTRO_TO_INSTALL' is not a valid ROS Distribution. Choose one of: '${ALL_VALID_DISTROS[*]}'" + fi +} + +function check_ubuntu_version() { + # check if the chosen distribution is compatible with the Ubuntu version + case $UBUNTU_VERSION in + + 18.04 ) + if contains_element "$ROS_DISTRO_TO_INSTALL" "${BIONIC_VALID_DISTROS[@]}"; then + PY_VERSION=2 + else + failed "Chosen ROS distribution '$ROS_DISTRO_TO_INSTALL' is not supported on Ubuntu ${UBUNTU_VERSION}." + fi + ;; + + 20.04 ) + if contains_element "$ROS_DISTRO_TO_INSTALL" "${FOCAL_VALID_DISTROS[@]}"; then + PY_VERSION=3 + else + failed "Chosen ROS distribution '$ROS_DISTRO_TO_INSTALL' is not supported on Ubuntu ${UBUNTU_VERSION}." + fi + ;; + + 22.04 ) + if contains_element "$ROS_DISTRO_TO_INSTALL" "${JAMMY_VALID_DISTROS[@]}"; then + PY_VERSION=3 + else + failed "Chosen ROS distribution '$ROS_DISTRO_TO_INSTALL' is not supported on Ubuntu ${UBUNTU_VERSION}." + fi + ;; + + *) + failed "Something went wrong. UBUNTU_VERSION='$UBUNTU_VERSION', should be 18.04, 20.04, or 22.04." + ;; + + esac +} + +function install_essential_packages() { + # Install necessary core packages + sudo apt-get install -yq curl git + if [ "$ROS_VERSION_TO_INSTALL" == 2 ]; then + sudo pip3 install transforms3d + fi + if [ $PY_VERSION == 2 ]; then + sudo apt-get install -yq python-pip + python -m pip install modern_robotics + elif [ $PY_VERSION == 3 ]; then + sudo apt-get install -yq python3-pip + python3 -m pip install modern_robotics + else + failed "Something went wrong. PY_VERSION='$PY_VERSION', should be 2 or 3." + fi +} + +function install_ros1() { + # Install ROS 1 + if [ "$(dpkg-query -W -f='${Status}' ros-"$ROS_DISTRO_TO_INSTALL"-desktop-full 2>/dev/null | grep -c "ok installed")" -eq 0 ]; then + echo -e "${GRN}Installing ROS 1 $ROS_DISTRO_TO_INSTALL desktop...${OFF}" + sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' + sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 + curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - + sudo apt-get update + sudo apt-get install -yq ros-"$ROS_DISTRO_TO_INSTALL"-desktop-full + if [ -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then + sudo rm /etc/ros/rosdep/sources.list.d/20-default.list + fi + echo "source /opt/ros/$ROS_DISTRO_TO_INSTALL/setup.bash" >> ~/.bashrc + if [ $PY_VERSION == 2 ]; then + sudo apt-get install -yq \ + python-rosdep \ + python-rosinstall \ + python-rosinstall-generator \ + python-wstool \ + build-essential + elif [ $PY_VERSION == 3 ]; then + sudo apt-get install -yq \ + python3-rosdep \ + python3-rosinstall \ + python3-rosinstall-generator \ + python3-wstool \ + build-essential + fi + sudo rosdep init + rosdep update --include-eol-distros + else + echo "ros-$ROS_DISTRO_TO_INSTALL-desktop-full is already installed!" + fi + source /opt/ros/"$ROS_DISTRO_TO_INSTALL"/setup.bash + + # Install Arm packages + if source /opt/ros/"$ROS_DISTRO_TO_INSTALL"/setup.bash 2>/dev/null && \ + source "$INSTALL_PATH"/devel/setup.bash 2>/dev/null && \ + rospack list | grep -q interbotix_; + then + echo "Interbotix Arm ROS packages already installed!" + else + cd "$INSTALL_PATH"/src + git clone -b "$ROS_DISTRO_TO_INSTALL" https://github.com/Interbotix/interbotix_ros_core.git + git clone -b "$ROS_DISTRO_TO_INSTALL" https://github.com/Interbotix/interbotix_ros_manipulators.git + git clone -b "$ROS_DISTRO_TO_INSTALL" https://github.com/Interbotix/interbotix_ros_toolboxes.git + rm \ + interbotix_ros_core/interbotix_ros_xseries/CATKIN_IGNORE \ + interbotix_ros_manipulators/interbotix_ros_xsarms/CATKIN_IGNORE \ + interbotix_ros_toolboxes/interbotix_xs_toolbox/CATKIN_IGNORE \ + interbotix_ros_toolboxes/interbotix_common_toolbox/interbotix_moveit_interface/CATKIN_IGNORE + if [ "$INSTALL_PERCEPTION" = true ]; then + rm \ + interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_perception/CATKIN_IGNORE \ + interbotix_ros_toolboxes/interbotix_perception_toolbox/CATKIN_IGNORE + fi + if [ "$INSTALL_MATLAB" = true ]; then + cd interbotix_ros_toolboxes + git submodule update --init third_party_libraries/ModernRobotics + cd "$INSTALL_PATH/src" + fi + cd interbotix_ros_core/interbotix_ros_xseries/interbotix_xs_sdk + sudo cp 99-interbotix-udev.rules /etc/udev/rules.d/ + sudo udevadm control --reload-rules && sudo udevadm trigger + cd "$INSTALL_PATH" + rosdep install --from-paths src --ignore-src -r -y + catkin_make + if catkin_make; then + echo -e "${GRN}${BOLD}Interbotix Arm ROS Packages built successfully!${NORM}${OFF}" + echo "source $INSTALL_PATH/devel/setup.bash" >> ~/.bashrc + source "$INSTALL_PATH"/devel/setup.bash + else + failed "Failed to build Interbotix Arm ROS Packages." + fi + fi +} + +function install_ros2() { + # Install ROS 2 + if [ "$(dpkg-query -W -f='${Status}' ros-"$ROS_DISTRO_TO_INSTALL"-desktop 2>/dev/null | grep -c "ok installed")" -eq 0 ]; then + echo -e "${GRN}Installing ROS 2 $ROS_DISTRO_TO_INSTALL desktop...${OFF}" + sudo apt-get install -yq \ + software-properties-common \ + gnupg + sudo add-apt-repository -y universe + sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo "$UBUNTU_CODENAME") main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null + sudo apt-get update + sudo apt-get install -yq ros-"$ROS_DISTRO_TO_INSTALL"-desktop + echo "source /opt/ros/$ROS_DISTRO_TO_INSTALL/setup.bash" >> ~/.bashrc + else + echo "ros-$ROS_DISTRO_TO_INSTALL-desktop-full is already installed!" + fi + source /opt/ros/"$ROS_DISTRO_TO_INSTALL"/setup.bash + + # Install rosdep and other necessary tools + sudo apt-get install -yq \ + python3-rosdep \ + python3-rosinstall \ + python3-rosinstall-generator \ + python3-wstool \ + build-essential \ + python3-colcon-common-extensions + + # Remove sources if they exist + if [ -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then + sudo rm /etc/ros/rosdep/sources.list.d/20-default.list + fi + + # Initialize rosdep sources + sudo rosdep init + + # Update local rosdep database, including EoL distros + rosdep update --include-eol-distros + + if [ "$INSTALL_PERCEPTION" = true ]; then + # Install apriltag ROS Wrapper, no official Apriltag ROS 2 package yet + if source /opt/ros/"$ROS_DISTRO_TO_INSTALL"/setup.bash 2>/dev/null && \ + source "$APRILTAG_WS"/install/setup.bash 2>/dev/null && \ + ros2 pkg list | grep -q apriltag_ros; + then + echo "Apriltag ROS Wrapper already installed!" + else + echo -e "${GRN}Installing Apriltag ROS Wrapper...${OFF}" + mkdir -p "$APRILTAG_WS"/src + cd "$APRILTAG_WS"/src + git clone -b ros2-port https://github.com/Interbotix/apriltag_ros.git + cd "$APRILTAG_WS" + rosdep install --from-paths src --ignore-src -r -y + # cmake-args flags disables warnings as errors unrelated to ROS + if colcon build --cmake-args -DCMAKE_CXX_FLAGS="-w"; then + echo -e "${GRN}${BOLD}Apriltag ROS Wrapper built successfully!${NORM}${OFF}" + echo "source $APRILTAG_WS/install/setup.bash" >> ~/.bashrc + source $APRILTAG_WS/install/setup.bash + else + failed "Failed to build Apriltag ROS Wrapper." + fi + fi + fi + + # Install Arm packages + if source /opt/ros/"$ROS_DISTRO_TO_INSTALL"/setup.bash 2>/dev/null && \ + source "$INSTALL_PATH"/install/setup.bash 2>/dev/null && \ + ros2 pkg list | grep -q interbotix_; + then + echo "Interbotix Arm ROS 2 packages already installed!" + else + echo -e "${GRN}Installing ROS 2 packages for the Interbotix Arm...${OFF}" + cd "$INSTALL_PATH"/src + git clone -b "$ROS_DISTRO_TO_INSTALL" https://github.com/Interbotix/interbotix_ros_core.git + git clone -b "$ROS_DISTRO_TO_INSTALL" https://github.com/Interbotix/interbotix_ros_manipulators.git + git clone -b "$ROS_DISTRO_TO_INSTALL" https://github.com/Interbotix/interbotix_ros_toolboxes.git + # TODO(lsinterbotix) remove below when moveit_visual_tools is available in apt repo + git clone -b ros2 https://github.com/ros-planning/moveit_visual_tools.git + if [ "$INSTALL_PERCEPTION" = true ]; then + rm \ + interbotix_ros_manipulators/interbotix_ros_xsarms/interbotix_xsarm_perception/COLCON_IGNORE \ + interbotix_ros_toolboxes/interbotix_perception_toolbox/COLCON_IGNORE + fi + rm \ + interbotix_ros_core/interbotix_ros_xseries/COLCON_IGNORE \ + interbotix_ros_toolboxes/interbotix_common_toolbox/interbotix_moveit_interface/COLCON_IGNORE \ + interbotix_ros_toolboxes/interbotix_common_toolbox/interbotix_moveit_interface_msgs/COLCON_IGNORE + cd interbotix_ros_core + git submodule update --init interbotix_ros_xseries/dynamixel_workbench_toolbox + git submodule update --init interbotix_ros_xseries/interbotix_xs_driver + cd "$INSTALL_PATH"/src + if [ "$INSTALL_MATLAB" = true ]; then + cd interbotix_ros_toolboxes + git submodule update --init third_party_libraries/ModernRobotics + cd "$INSTALL_PATH"/src + fi + cd interbotix_ros_core/interbotix_ros_xseries/interbotix_xs_sdk + sudo cp 99-interbotix-udev.rules /etc/udev/rules.d/ + sudo udevadm control --reload-rules && sudo udevadm trigger + cd "$INSTALL_PATH" + rosdep install --from-paths src --ignore-src -r -y + if colcon build; then + echo -e "${GRN}${BOLD}Interbotix Arm ROS 2 Packages built successfully!${NORM}${OFF}" + echo "source $INSTALL_PATH/install/setup.bash" >> ~/.bashrc + source "$INSTALL_PATH"/install/setup.bash + else + failed "Failed to build Interbotix Arm ROS 2 Packages." + fi + fi +} + +function setup_env_vars() { + # Set up Environment Variables + if [ -z "$ROS_IP" ]; then + echo -e "${GRN}Setting up Environment Variables...${OFF}" + echo "# Interbotix Configurations" >> ~/.bashrc + echo 'export ROS_IP=$(echo `hostname -I | cut -d" " -f1`)' >> ~/.bashrc + echo -e 'if [ -z "$ROS_IP" ]; then\n\texport ROS_IP=127.0.0.1\nfi' >> ~/.bashrc + else + echo "Environment variables already set!" + fi +} + +# parse command line arguments +while getopts 'hnd:p:' OPTION; +do + case "$OPTION" in + h) help && exit 0;; + n) NONINTERACTIVE=true;; + d) ROS_DISTRO_TO_INSTALL="$OPTARG" && DISTRO_SET_FROM_CL=true;; + p) INSTALL_PATH="$OPTARG";; + *) echo "Unknown argument $OPTION" && help && exit 0;; + esac +done + +shift "$((OPTIND -1))" + +if ! command -v lsb_release &> /dev/null; then + sudo apt-get update + sudo apt-get install -yq lsb-release +fi + +UBUNTU_VERSION="$(lsb_release -rs)" + +# set default ROS distro before reading clargs +if [ "$DISTRO_SET_FROM_CL" = false ]; then + if [ "$UBUNTU_VERSION" == "18.04" ]; then + ROS_DISTRO_TO_INSTALL="melodic" + elif [ "$UBUNTU_VERSION" == "20.04" ]; then + ROS_DISTRO_TO_INSTALL="noetic" + elif [ "$UBUNTU_VERSION" == "22.04" ]; then + ROS_DISTRO_TO_INSTALL="humble" + else + echo -e "${BOLD}${RED}Unsupported Ubuntu version: $UBUNTU_VERSION.${NORM}${OFF}" + failed "Interbotix Arm only works with Ubuntu 18.04 Bionic, 20.04 Focal, or 22.04 Jammy on your hardware." + fi +fi + +validate_distro +check_ubuntu_version + +if [ "$NONINTERACTIVE" = false ]; then + # prompt for perception packages + echo -e "${BLU}${BOLD}Install the Interbotix Perception packages? This will include the RealSense and AprilTag packages as dependencies.\n$PROMPT${NORM}${OFF}\c" + read -r resp + if [[ $resp == [yY] || $resp == [yY][eE][sS] ]]; then + INSTALL_PERCEPTION=true + else + INSTALL_PERCEPTION=false + fi + + echo -e "${BLU}${BOLD}Install the MATLAB-ROS API?\n$PROMPT${NORM}${OFF}\c" + read -r resp + if [[ $resp == [yY] || $resp == [yY][eE][sS] ]]; then + INSTALL_MATLAB=true + else + INSTALL_MATLAB=false + fi + + if [[ "$ROS_DISTRO_TO_INSTALL" == 'rolling' ]]; then + echo -e "${BLU}${BOLD}ROS 2 Rolling is not officially supported and full functionality is not guaranteed. Do you wish to continue anyways?\n$PROMPT${NORM}${OFF}\c" + read -r resp + if [[ $resp == [yY] || $resp == [yY][eE][sS] ]]; then + : + else + help && exit 0 + fi + fi + + echo -e "${BLU}${BOLD}INSTALLATION SUMMARY:" + echo -e "\tROS Distribution: ROS ${ROS_VERSION_TO_INSTALL} ${ROS_DISTRO_TO_INSTALL}" + echo -e "\tInstall Perception Modules: ${INSTALL_PERCEPTION}" + echo -e "\tInstall MATLAB Modules: ${INSTALL_MATLAB}" + echo -e "\tInstallation path: ${INSTALL_PATH}" + echo -e "\nIs this correct?\n${PROMPT}${NORM}${OFF}\c" + read -r resp + + if [[ $resp == [yY] || $resp == [yY][eE][sS] ]]; then + : + else + help && exit 0 + fi +else + INSTALL_PERCEPTION=true + INSTALL_MATLAB=true +fi + +echo -e "\n\n" +echo -e "${GRN}${BOLD}**********************************************${NORM}${OFF}" +echo "" +echo -e "${GRN}${BOLD} Starting installation! ${NORM}${OFF}" +echo -e "${GRN}${BOLD} This process may take around 15 Minutes! ${NORM}${OFF}" +echo "" +echo -e "${GRN}${BOLD}**********************************************${NORM}${OFF}" +echo -e "\n\n" + +sleep 4 +start_time="$(date -u +%s)" + +echo -e "\n# Interbotix Configurations" >> ~/.bashrc + +# Update the system +sudo apt-get update && sudo apt-get -y upgrade +sudo apt-get -y autoremove + +install_essential_packages + +mkdir -p "$INSTALL_PATH"/src + +shopt -s extglob + +if [[ $ROS_VERSION_TO_INSTALL == 1 ]]; then + install_ros1 +elif [[ $ROS_VERSION_TO_INSTALL == 2 ]]; then + install_ros2 +else + failed "Something went wrong." +fi + +setup_env_vars + +shopt -u extglob + +end_time="$(date -u +%s)" +elapsed="$((end_time-start_time))" + +echo -e "${GRN}Installation complete, took $elapsed seconds in total.${OFF}" +echo -e "${GRN}NOTE: Remember to reboot the computer before using the robot!${OFF}"