diff --git a/docs/conf.py b/docs/conf.py index d4c52c84..a6e1ab6e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -75,6 +75,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom extensions = [ "sphinx.ext.autodoc", + "sphinx.ext.autosectionlabel", "sphinx.ext.doctest", "sphinx.ext.intersphinx", "sphinx.ext.todo", diff --git a/docs/docker/docker_use_cases/docker_use_cases.rst b/docs/docker/docker_use_cases/docker_use_cases.rst new file mode 100644 index 00000000..05725c7a --- /dev/null +++ b/docs/docker/docker_use_cases/docker_use_cases.rst @@ -0,0 +1,18 @@ +============================== +Use Cases with docker support +============================== +.. _uc-with-docker-support-index: + +All use cases with docker suppert are listed below. For a detailed description of the use case as well as the respective commands, you can click on the link in the use case column. + +.. list-table:: Overview of currently supported use cases + :widths: auto + :header-rows: 1 + :stub-columns: 1 + + * - use case + - docker command + - description + * - :ref:`Setup a new Workspace` with ``setup-ros-workspace`` + - ``setup-ros-workspace-docker`` + - Creates a new workspace and maps the workspace inside a docker container. You can then switch to docker using ``rtw_switch_to_docker``. diff --git a/docs/docker/general_information_docker/general_information_docker.rst b/docs/docker/general_information_docker/general_information_docker.rst new file mode 100644 index 00000000..3518db82 --- /dev/null +++ b/docs/docker/general_information_docker/general_information_docker.rst @@ -0,0 +1,32 @@ +============================== +General information on docker +============================== +.. _general-info-on-docker-index: + +Generally you can always have a look at the `docs of docker `_. + +Installation +"""""""""""""""" +You have to install docker which is dependent on the operating system you are using. + +* `Windows `_ +* `Mac `_ +* `Linux `_: it depends. + +.. note:: + However make sure your user is in the docker group. Check with: ``groups`` command. To add your user to the docker group run: ``sudo usermod -aG docker ``. + +Usful commands +"""""""""""""""" +For complete list of commands have a look at `official docker cli reference `_. + +* ``docker container ``: + + * ``ls`` lists all current active containers + * ``ls -a`` lists all containers + * ``rm `` removes container + +* ``docker image ``: + + * ``ls`` lists all images + * ``rm `` removes image diff --git a/docs/docker/index.rst b/docs/docker/index.rst new file mode 100644 index 00000000..90421365 --- /dev/null +++ b/docs/docker/index.rst @@ -0,0 +1,17 @@ +=========== +Docker +=========== +.. _docker-overview: + +RosTeamWS supports the usage of docker containers. + +.. toctree:: + :maxdepth: 1 + :glob: + + general_information_docker/* + docker_use_cases/* + supported_versions/* + +.. note:: + If you want to forward a xsession from docker (e.g. rviz2), you have to install xhost. diff --git a/docs/docker/supported_versions/supported_versions.rst b/docs/docker/supported_versions/supported_versions.rst new file mode 100644 index 00000000..4e689936 --- /dev/null +++ b/docs/docker/supported_versions/supported_versions.rst @@ -0,0 +1,24 @@ +============================================= +Supported ros versions and operating systems +============================================= +.. _supported-os-ros-docker-versions-index: + +For the supported Ubuntu and ros version combinations have a look at the table below. + +.. list-table:: Supported Ubuntu and ros versions combinations are marked with an X. + :widths: auto + :header-rows: 1 + :stub-columns: 1 + + * - ros version + - ubuntu 20.04 + - ubuntu 22.04 + * - foxy + - X + - + * - galactic + - X + - + * - rolling + - X + - X diff --git a/docs/faq/index.rst b/docs/faq/index.rst new file mode 100644 index 00000000..b457c45b --- /dev/null +++ b/docs/faq/index.rst @@ -0,0 +1,14 @@ +================================ +FAQ +================================ + +On Docker +---------------- + +How to forward a xsession +""""""""""""""""""""""""""""" +If you want to forward a xsession from docker (e.g. rviz2), you have to install xhost. When executing the commands ``start_container`` the docker user is added to the X Server access list. + +sudo: unable to resolve host : Name or service not known +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +Problem using sudo: If you encounter following message trying to use sudo: ``sudo: unable to resolve host : Name or service not known``. You have to add ``127.0.0.1 `` to the ``/etc/hosts`` file inside the container. However, using sudo should work fine without adding it. diff --git a/docs/index.rst b/docs/index.rst index f3607b62..257ea9a3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -53,3 +53,5 @@ The opinions and proposals stated here are merely related to the authors' experi getting_started/index.rst guidelines/index.rst use-cases/index.rst + docker/index.rst + faq/index.rst diff --git a/docs/use-cases/operating_system/create_setup_workspace.rst b/docs/use-cases/operating_system/create_setup_workspace.rst index 46eadc83..a951a73c 100644 --- a/docs/use-cases/operating_system/create_setup_workspace.rst +++ b/docs/use-cases/operating_system/create_setup_workspace.rst @@ -3,7 +3,10 @@ Setup a new Workspace =========================== .. _uc-setup-workspace: -This use-case describes how to setup a new ROS workspace using scripts from the ROS Team Workspace (RosTeamWS) framework. +This use-case describes how to setup a new ROS workspace using scripts from the ROS Team Workspace (RosTeamWS) framework. Besides the creation of a local workspace, creation of a Ubuntu based docker container is supported. For more details have a look below in the `Docker workspace`_ section. + +Local workspace +---------------- ``setup-ros-workspace`` accepts ros distro name workspace suffix and workspace folder as parameters. All three parameters are optional. @@ -17,3 +20,48 @@ All three parameters are optional. The script creates in the ``$HOME/`` a new ROS workspace with name ``ros_ws___``. If you want to omit any of input parameters use ``"-"`` as argument. Default value for ```` is "workspace". + +.. _uc-setup-docker-workspace: + +Docker workspace +------------------ + +.. code-block:: bash + :caption: How to setup a workspace inside a docker container. + :name: setup docker workspace + + setup-ros-workspace-docker ROS_DISTRO WS_FOLDER WS_PREFIX WS_SUFFIX. + +Like the script ``setup-ros-workspace`` the ``setup-ros-workspace-docker`` creates a new local ROS workspace. Then a Ubuntu docker container gets built and the created workspace is mounted inside the docker container under the home directory. The first time a docker container is build can take quite a while. When the first build is finished you are directly connected as user inside the container. You can verify this by checking if your hostname has changed. To exit a container simply type the ``exit`` command. + +Reconnect to a container +"""""""""""""""""""""""""" + +If you exited a container an want to reconnect as a user, you have to run the ``rtw_switch_to_docker`` command. However before executing this you have to source your workspace with ``_``. If you want to connect as a root user you can execute ``rtw_switch_to_docker_root``. + +Recreate a container +"""""""""""""""""""""" + +If you removed an image, you can recreate it by switching into the ``.rtw_docker_defines`` folder inside your workspace and then executing the ``.\build_docker_image`` command. After the container is rebuilt, you can create it with ``.\create_docker_container`` command. Thereafter, you should be able to normally start, reconnect and stop the container. + +.. note:: + For more general questions on the usage of docker and the limitations of RosTeamWS in interacting with docker have a look at our :ref:`docker related docs`. + +CLI overview +""""""""""""" + +.. list-table:: Overview of the cli + :widths: auto + :header-rows: 1 + :stub-columns: 1 + + * - command + - description + * - ``setup-ros-workspace-docker`` + - Creates a new workspace and maps the workspace inside a docker container. You can then switch to docker using ``rtw_switch_to_docker``. + * - ``rtw_switch_to_docker`` + - Starts the docker container if it has been stopped and connects to the container as user. + * - ``rtw_switch_to_docker_root`` + - Starts the docker container if it has been stopped and connects to the container as root-user. + * - ``rtw_stop_docker`` + - Stops the docker container. diff --git a/scripts/_RosTeamWs_Defines.bash b/scripts/_RosTeamWs_Defines.bash index eda41332..9b0b195a 100755 --- a/scripts/_RosTeamWs_Defines.bash +++ b/scripts/_RosTeamWs_Defines.bash @@ -55,9 +55,12 @@ function RosTeamWS_setup_exports { export RAW_TERMINAL_COLOR_LIGHT_GRAY=$'\e[0;37m' export RAW_TERMINAL_COLOR_WHITE=$'\e[1;37m' + ## Define semantics of each color export TERMINAL_COLOR_USER_NOTICE=${TERMINAL_COLOR_YELLOW} export TERMINAL_COLOR_USER_INPUT_DECISION=${TERMINAL_COLOR_PURPLE} export TERMINAL_COLOR_USER_CONFIRMATION=${TERMINAL_COLOR_BLUE} + export RTW_COLOR_NOTIFY_USER=${TERMINAL_COLOR_YELLOW} + export RTW_COLOR_ERROR=${TERMINAL_COLOR_RED} } # TODO(denis): add this into setup.bash @@ -224,21 +227,25 @@ function print_and_exit { message=$1 echo "" - echo -e "${TERMINAL_COLOR_RED}$message !!Exiting...${TERMINAL_COLOR_NC}" + echo -e "${RTW_COLOR_ERROR}$message!!! Exiting...${TERMINAL_COLOR_NC}" if [ ! -z "$2" ]; then echo "" - echo -e "${TERMINAL_COLOR_YELLOW}Usage: '$2'${TERMINAL_COLOR_NC}" + echo -e "${TERMINAL_COLOR_USER_NOTICE}Usage: '$2'${TERMINAL_COLOR_NC}" fi - echo -e "${TERMINAL_COLOR_BLUE}Error has happened. Press + C two times...${TERMINAL_COLOR_NC}" + echo -e "${TERMINAL_COLOR_USER_CONFIRMATION}Error has happened. Press + C two times...${TERMINAL_COLOR_NC}" read -p "" - throw_error + exit 1 } function framework_default_paths { ros_distro=$1 FRAMEWORK_NAME="ros_team_workspace" - FRAMEWORK_BASE_PATH=${FRAMEWORK_BASE_PATH:=/opt/RosTeamWS} + + # if we suppose a structure like + # /opt/RosTeamWS/ros_ws_/src/ros_team_ws/... + # then FRAMEWORK_BASE_PATH should be /opt/RosTeamWS/ + FRAMEWORK_BASE_PATH="$(RosTeamWS_script_own_dir)/../../../.." FRAMEWORK_PACKAGE_PATH="$FRAMEWORK_BASE_PATH/ros_ws_$ros_distro/src/$FRAMEWORK_NAME" if [ ! -d "$FRAMEWORK_PACKAGE_PATH" ]; then @@ -253,19 +260,24 @@ function framework_default_paths { ROS2_CONTROL_HW_ITF_TEMPLATES="$ROS2_CONTROL_TEMPLATES/hardware" ROS2_CONTROL_CONTROLLER_TEMPLATES="$ROS2_CONTROL_TEMPLATES/controller" LICENSE_TEMPLATES="$FRAMEWORK_PACKAGE_PATH/templates/licenses" + DOCKER_TEMPLATES="$FRAMEWORK_PACKAGE_PATH/templates/docker" } function check_ros_distro { ros_distro=$1 if [ -z "$1" ]; then - ros_distro=$DEFAULT_ROS_DISTRO - echo "No ros_distro defined. Using default: '$ros_distro'" - if [ ! -d "/opt/ros/$ros_distro" ]; then - print_and_exit "FATAL: ROS '$ros_distro' not installed on this computer! Exiting..." -# echo "FATAL: ROS '$ros_distro' not installed on this computer! Exiting..." -# exit + if [ -n "$DEFAULT_ROS_DISTRO" ]; then + ros_distro=$DEFAULT_ROS_DISTRO + echo "No ros_distro defined. Using default: '$ros_distro'" + if [ ! -d "/opt/ros/$ros_distro" ]; then + print_and_exit "FATAL: ROS '$ros_distro' not installed on this computer! Exiting..." + # echo "FATAL: ROS '$ros_distro' not installed on this computer! Exiting..." + # exit + fi + read -p "Press to continue or +C to exit." + else + return 2>/dev/null fi - read -p "Press to continue or +C to exit." fi if [ ! -d "/opt/ros/$ros_distro" ]; then @@ -279,6 +291,8 @@ function check_ros_distro { ros_version=2 elif [[ $ros_distro == "galactic" ]]; then ros_version=2 + elif [[ $ros_distro == "humble" ]]; then + ros_version=2 elif [[ $ros_distro == "rolling" ]]; then ros_version=2 elif [[ $ros_distro == "noetic" ]]; then @@ -314,4 +328,4 @@ function compile_and_source_package { # END: Framework functions -FRAMEWORK_MAIN_PATH="$(RosTeamWS_script_own_dir)/../" +FRAMEWORK_MAIN_PATH="$(RosTeamWS_script_own_dir)/.." diff --git a/scripts/_RosTeamWs_Docker_Defines.bash b/scripts/_RosTeamWs_Docker_Defines.bash index d5621abd..7fe25259 100644 --- a/scripts/_RosTeamWs_Docker_Defines.bash +++ b/scripts/_RosTeamWs_Docker_Defines.bash @@ -14,4 +14,34 @@ ## BEGIN: Default RosTeamWS Docker Definitions and Aliases -# function _run_docker() +setup-ros-workspace-docker () { + source "$RosTeamWS_FRAMEWORK_SCRIPTS_PATH"/setup-ros-workspace.bash + create_workspace_docker "$@" +} + +rtw_switch_to_docker () { + if [ -z "$RosTeamWS_WS_DOCKER_SUPPORT" ] || [ "$RosTeamWS_WS_DOCKER_SUPPORT" == false ]; then + print_and_exit"It seems your current workspace does not support docker. If it should, did you activate it by executing _\"\"?" + fi + + source "$RosTeamWS_FRAMEWORK_SCRIPTS_PATH"/docker/_RosTeamWs_Docker_Defines.bash + start_and_connect_user_to_docker "$RosTeamWS_DOCKER_TAG" +} + +rtw_switch_to_docker_root () { + if [ -z "$RosTeamWS_WS_DOCKER_SUPPORT" ] || [ "$RosTeamWS_WS_DOCKER_SUPPORT" == false ]; then + print_and_exit "It seems your current workspace does not support docker. If it should, did you activate it by executing _\"\"?" + fi + + source "$RosTeamWS_FRAMEWORK_SCRIPTS_PATH"/docker/_RosTeamWs_Docker_Defines.bash + start_and_connect_root_to_docker "$RosTeamWS_DOCKER_TAG" +} + +rtw_stop_docker () { + if [ -z "$RosTeamWS_WS_DOCKER_SUPPORT" ] || [ "$RosTeamWS_WS_DOCKER_SUPPORT" == false ]; then + print_and_exit "It seems your current workspace does not support docker. If it should, did you activate it by executing _\"\"?" + fi + + source "$RosTeamWS_FRAMEWORK_SCRIPTS_PATH"/docker/_RosTeamWs_Docker_Defines.bash + stop_docker_container "$RosTeamWS_DOCKER_TAG" +} diff --git a/scripts/_Team_Defines.bash b/scripts/_Team_Defines.bash index ee23f114..6c8038a8 100644 --- a/scripts/_Team_Defines.bash +++ b/scripts/_Team_Defines.bash @@ -12,28 +12,20 @@ # See the License for the specific language governing permissions and # limitations under the License. -## BEGIN: Team specific definitions - -DEFAULT_ROS_DISTRO="rolling" -DEFAULT_ROS_VERSION=2 +## BEGIN: definitions # TODO(denis): We have two example teams. On is working with industrial and other with mobile robots # TEAM_TEAM_NAMES=("Industrial" "Mobile") -TEAM_LICENSE="Apache-2.0" - -TEAM_REPOSITORY_SERVER="https://github.com" - -TEAM_PRIVATE_CONFIG_PATH="" - # Define a path to a repository with your internal assets and configurations TEAM_INTERNAL_ASSETS="/opt/RosTeamWS/assets/" ## END: definitions # TODO(denis): implement here support for internal repos -source $TEAM_INTERNAL_ASSETS/setup.bash - +if [ -f $TEAM_INTERNAL_ASSETS/setup.bash ]; then + source $TEAM_INTERNAL_ASSETS/setup.bash +fi ## BEGIN: Framework definition adjustable by users # TBD @@ -62,7 +54,6 @@ alias setup_ros2_aliases=RosTeamWS_setup_ros2_aliases # BEGIN: Define aliases for standard scripts # Change those to your custom ones you would like to use. - alias create-new-package=$RosTeamWS_FRAMEWORK_SCRIPTS_PATH/create-new-package.bash alias setup-repository=$RosTeamWS_FRAMEWORK_SCRIPTS_PATH/setup-repository.bash @@ -71,6 +62,11 @@ alias setup-repository-ci=$RosTeamWS_FRAMEWORK_SCRIPTS_PATH/setup-ci-config.bash alias setup-ros-workspace=$RosTeamWS_FRAMEWORK_SCRIPTS_PATH/setup-ros-workspace.bash +setup-ros-workspace () { + source "$RosTeamWS_FRAMEWORK_SCRIPTS_PATH"/setup-ros-workspace.bash + create_workspace "$@" +} + alias setup-robot-bringup=$RosTeamWS_FRAMEWORK_SCRIPTS_PATH/setup-robot-bringup.bash alias setup-robot-description=$RosTeamWS_FRAMEWORK_SCRIPTS_PATH/setup-robot-description.bash diff --git a/scripts/docker/_RosTeamWs_Docker_Defines.bash b/scripts/docker/_RosTeamWs_Docker_Defines.bash new file mode 100755 index 00000000..c6d3a364 --- /dev/null +++ b/scripts/docker/_RosTeamWs_Docker_Defines.bash @@ -0,0 +1,164 @@ +#!/usr/bin/env bash +# Copyright (c) 2022, Stogl Robotics Consulting UG (haftungsbeschränkt) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Load Framework defines +docker_script_own_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" +source $docker_script_own_dir/../_RosTeamWs_Defines.bash + +# assoziative array which maps the chosen rosdistro to the name which is used to install the corresponding +# ros distribution inside docker +declare -r -A map_to_docker_ros_distro_name=( ["foxy"]="foxy" ["galactic"]="galactic" ["rolling"]="rolling" ) +declare -r -A ros_distro_to_rtw_branch=( ["foxy"]="foxy" ["galactic"]="master" ["rolling"]="master") + +# $1 = name (tag) of the created docker image +# $2 = Dockerfile which is used for creating the image +build_docker_image () { + if [ -z "$1" ]; then + echo "No docker image tag specified. Can not create image." + return 1 + fi + if [ -z "$2" ]; then + echo "No docker file specified. Can not create image." + return 1 + fi + local docker_image_tag=$1 + local docker_file_path=$2 + + # apparently docker checks every file in dir, its best to be in new dir + prev_pwd=$(pwd) + cd "$(dirname "$docker_file_path")" || { echo "Could not change directory to new workspace"; return 1; } + + echo "Building docker image $docker_image_tag with docker file $docker_file_path. This can take a while..." + sleep 1 # sleep a second, so that user can read above message + docker build \ + --build-arg user=$USER \ + --build-arg uid=$UID \ + --build-arg gid=$GROUPS \ + --build-arg home=$HOME \ + -t "$docker_image_tag" . || { return 1; } + + cd "$prev_pwd" || { print_and_exit "Build of docker container succeeded but changing back previous working directory failed."; } +} + +create_docker_container() { + if [ -z "$1" ]; then + print_and_exit "No docker image (tag) specified. Can not instantiate image." + fi + local docker_image_tag=$1 + + if [ -z "$2" ]; then + print_and_exit "No workspace which should be mapped to the container is given. Can not instantiate image." + fi + local ws_folder=$2 + + if [ -z "$3" ]; then + print_and_exit "No RosTeamWS_DISTRO given. Can not instantiate image." + fi + local RosTeamWS_DISTRO=$3 + + if [ -z "$4" ]; then + print_and_exit "No docker host name given. Can not instantiate image." + fi + local docker_host_name=$4 + + echo "Instantiating docker image '$docker_image_tag' and mapping workspace folder '$HOME/$ws_folder'." + echo "ros_team_ws is located under /opt/RosTeamWS/ros_ws_${RosTeamWS_DISTRO}/src/ros_team_workspace" + xhost +local:docker + docker run \ + --net=host \ + -h ${docker_host_name} \ + -e DISPLAY \ + --tmpfs /tmp \ + -v /tmp/.X11-unix/:/tmp/.X11-unix:rw \ + -v "$HOME/$ws_folder":"$HOME/$ws_folder":rw \ + -v "$HOME/.ssh":"$HOME/.ssh":ro \ + --name "$docker_image_tag"-instance \ + -it "$docker_image_tag" /bin/bash +} + +connect_user () { + if [ -z "$1" ]; then + print_and_exit "No container name given. Can not connect to instance." + fi + local container_instance_name + container_instance_name=$1 # assigen separate https://github.com/koalaman/shellcheck/wiki/SC2155 + + echo "Connecting to container instance: $container_instance_name as user." + docker exec -u $USER -it "$container_instance_name" /bin/bash +} + +connect_root_user () { + if [ -z "$1" ]; then + print_and_exit "No container name given. Can not connect to instance." + fi + local container_instance_name + container_instance_name=$1 # assigen separate https://github.com/koalaman/shellcheck/wiki/SC2155 + + echo "Connecting to container instance: $container_instance_name as root-user." + docker exec -u root -it "$container_instance_name" /bin/bash +} + +start_container () { + if [ -z "$1" ]; then + print_and_exit "No container name given. Can not start dockerinstance." + fi + local container_instance_name + container_instance_name=$1 # assigen separate https://github.com/koalaman/shellcheck/wiki/SC2155 + + echo "Starting container instance: $container_instance_name " + xhost +local:docker + docker start "$container_instance_name" +} + +stop_container () { + if [ -z "$1" ]; then + print_and_exit "No container name given. Can not stop dockerinstance." + fi + local container_instance_name + container_instance_name=$1 # assigen separate https://github.com/koalaman/shellcheck/wiki/SC2155 + + echo "Stopping container instance: $container_instance_name " + xhost -local:docker + docker stop "$container_instance_name" +} + +start_and_connect_user_to_docker () { + if [ -z "$1" ]; then + print_and_exit "The given docker tag is empty, something went wrong. Does your current workspace contain a RosTeamWS_DOCKER_TAG in .ros_team_ws_rc ?" + fi + local container_instance_name="$1-instance" + + start_container "$container_instance_name" + connect_user "$container_instance_name" +} + +start_and_connect_root_to_docker () { + if [ -z "$1" ]; then + print_and_exit "The given docker tag is empty, something went wrong. Does your current workspace contain a RosTeamWS_DOCKER_TAG in .ros_team_ws_rc ?" + fi + local container_instance_name="$1-instance" + + start_container "$container_instance_name" + connect_root_user "$container_instance_name" +} + +stop_docker_container () { + if [ -z "$1" ]; then + print_and_exit "The given docker tag is empty, something went wrong. Does your current workspace contain a RosTeamWS_DOCKER_TAG in .ros_team_ws_rc ?" + fi + local container_instance_name="$1-instance" + + stop_container "$container_instance_name" +} diff --git a/scripts/environment/setup.bash b/scripts/environment/setup.bash index aed7263c..3b9d0d36 100644 --- a/scripts/environment/setup.bash +++ b/scripts/environment/setup.bash @@ -105,6 +105,10 @@ elif [[ $ros_version == 2 ]]; then print_and_exit "Neither '$WS_FOLDER_0', '$WS_FOLDER_1', '$WS_FOLDER_2' nor '$WS_FOLDER_3' exist. Can not find ROS workspace!" fi + if [ -n "$RosTeamWS_DOCKER_TAG" ] && [ "$RosTeamWS_DOCKER_TAG" != "-" ]; then + echo -e "${TERMINAL_COLOR_BLUE}RosTeamWS: The workspace uses docker container '$RosTeamWS_DOCKER_TAG'." + fi + export ROS_WS=$WS_FOLDER # TODO: COLCON_WS is deprecated!! export COLCON_WS=$ROS_WS diff --git a/scripts/setup-ros-workspace.bash b/scripts/setup-ros-workspace.bash index 0664becc..5e826058 100755 --- a/scripts/setup-ros-workspace.bash +++ b/scripts/setup-ros-workspace.bash @@ -1,135 +1,317 @@ #!/bin/bash -# workspace folder is relative to your home +# Load Framework defines +setup_ws_script_own_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" +source $setup_ws_script_own_dir/_RosTeamWs_Defines.bash +source $setup_ws_script_own_dir/docker/_RosTeamWs_Docker_Defines.bash -usage="setup-ros-workspace.bash ROS_DISTRO WS_FOLDER WS_PREFIX WS_SUFFIX" +check_user_input () { + # ros distribution name will be set in ${ros_distro} + check_ros_distro "$1" + + ws_folder="$2" + if [ -z "$2" ]; then + ws_folder="workspace" + echo "Using default '~/workspace' folder to setup ros workspace" + elif [ "$use_docker" == true ] && [[ "$2" == *"-"* ]]; then + print_and_exit "Workspace names for docker cannot contain \"-\"." + fi + + # Todo Manuel make this more generic + if [ "$use_docker" == true ]; then + if [ "$ros_distro" == "rolling" ]; then + echo -e "${TERMINAL_COLOR_USER_INPUT_DECISION}'$ros_distro' is currently supported on multiple versions of Ubuntu. Which version of ubuntu would you like to choose:" + select ubuntu_version in Ubuntu_20_04 Ubuntu_22_04; + do + case "$ubuntu_version" in + Ubuntu_20_04) + ubuntu_version="ubuntu:20.04" + ubuntu_version_tag="ubuntu_20_04" + break + ;; + Ubuntu_22_04) + ubuntu_version="ubuntu:22.04" + ubuntu_version_tag="ubuntu_22_04" + break + ;; + esac + done + echo -n -e "${TERMINAL_COLOR_NC}" + else + ubuntu_version="ubuntu:20.04" + ubuntu_version_tag="ubuntu_20_04" + fi + fi + + ros_ws_prefix="$3" + if [ -z "$3" ]; then + ros_ws_prefix="-" + echo "No ros_ws_prefix used..." + fi + + ros_ws_suffix="$4" + if [ -z "$4" ]; then + ros_ws_suffix="-" + echo "No ros_ws_suffix used..." + fi +} + +setup_new_workspace () { + ros_distro_base_workspace_source_path="/opt/ros/$ros_distro/setup.bash" + +# # TODO: Write this automatically from the user's definitions +# echo "Please choose which workspace should be basis for yours:" +# echo "(0) (or if non sourced, source '${ros_distro_base_workspace_source_path}')" +# read choice + + # TODO(destogl): This is only temporarily solution until we offer different base-workspaces support (above commented lines) + choice="0" + echo -e "${RTW_COLOR_NOTIFY_USER} The new workspace will base on currently sourced workspace or if none is sourced, '${ros_distro_base_workspace_source_path}' will be sourced." + + if [ -z "$choice" ]; then + print_and_exit "No workspace is chosen!" "$usage" + fi + + case "$choice" in + # "1") + # base_ws=Industrial + # ;; + # "2") + # base_ws=Mobile + # ;; + "0") + base_ws="" + ;; + *) + print_and_exit "No workspace chosen! Exiting..." + esac + + base_ws_path="" + + if [ -z "$ROS_DISTRO" ]; then + echo -e "${TERMINAL_COLOR_YELLOW}No workspace is sourced, sourcing: '${ros_distro_base_workspace_source_path}'${TERMINAL_COLOR_NC}" + source ${ros_distro_base_workspace_source_path} + base_ws_path="${ros_distro_base_workspace_source_path}" + fi + + # Form here the full name + ws_full_name=${ros_distro} + + if [ "$ros_ws_prefix" != "-" ]; then + ws_full_name=${ros_ws_prefix}_${ws_full_name} + fi + if [ "$ros_ws_suffix" != "-" ]; then + ws_full_name=${ws_full_name}_${ros_ws_suffix} + fi + + # TODO: Add here output of the WS + echo "" + echo -e "${TERMINAL_COLOR_USER_NOTICE}ATTENTION: Creating a new workspace in folder '${ws_folder}' for ROS '${ros_distro}' (ROS$ros_version) with suffix '${ros_ws_suffix}' (full path: '${ws_folder}/${ws_full_name}') using '${base_ws}' (${base_ws_path}) as base workspace.${TERMINAL_COLOR_NC}" + echo "" + echo -e "${TERMINAL_COLOR_USER_CONFIRMATION}If correct press , otherwise +C and start the script again from the package folder and/or with correct controller name.${TERMINAL_COLOR_NC}" + read + + # TODO(destogl): This part with base workspaces should be updated!!! - this is obsolete logic + # Create and initialise ROS-Workspace + if [[ ${base_ws} != "" ]]; then + if [[ $ros_version == 1 ]]; then + source $FRAMEWORK_BASE_PATH/${base_ws}_ros_ws_${ros_distro}/devel/setup.bash + else + source $FRAMEWORK_BASE_PATH/${base_ws}_ros_ws_${ros_distro}/install/setup.bash + fi + fi + + mkdir -p ~/${ws_folder}/${ws_full_name} + cd ~/${ws_folder}/${ws_full_name} || { print_and_exit "Could not change dir to workspace folder. Something went wrong."; } + + if [ "$use_docker" = false ]; then # only build if not in docker, to avoide wrong dependencies + if [[ $ros_version == 1 ]]; then + wstool init src + catkin config -DCMAKE_BUILD_TYPE=RelwithDebInfo + catkin build + elif [[ $ros_version == 2 ]]; then + mkdir src + # cb + colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo + fi + fi + + # Go to Home folder of the user + cd || print_and_exit "Could not change back to home dir. This should never happen..." +} + +setup_ros_team_ws_file() { + if [ -z "$1" ]; then + print_and_exit "No ros_team_ws_file given. Cannot setup workspace defines." + fi + local ros_team_ws_file=$1 + if [ -z "$2" ]; then + print_and_exit "Not specified if docker should be used. Cannot setup workspace defines." + fi + local use_docker=$2 + if [ -z "$2" ]; then + print_and_exit "Not specified if ros_teamws_file is for docker. Cannot setup workspace defines." + fi + local is_docker_rtw_file=$3 + + # Create a function name + fun_name_suffix=${chosen_ros_distro} + + if [ "$ros_ws_prefix" != "-" ]; then + fun_name_suffix=${fun_name_suffix}_${ros_ws_prefix} + fi + if [ "$ros_ws_suffix" != "-" ]; then + fun_name_suffix=${fun_name_suffix}_${ros_ws_suffix} + fi + + alias_name=_${ws_full_name} + fun_name="RosTeamWS_setup_${fun_name_suffix}" + + cp "$ros_team_ws_file" "$ros_team_ws_file".bkp + # Comment out the old configuration if such exists - this is hard if using functions... + sed -i -e '/'"$fun_name"'/ s/^#*/OLD_/' "$ros_team_ws_file" + sed -i -e '/alias st_ros'"$ros_version=$fun_name"'/ s/^#*/#/' "$ros_team_ws_file" + + if [ "$use_docker" = true ]; then + docker_image_tag=$(sed "s/[\/]/-/g" <(echo "ros-team-ws_${ubuntu_version_tag}__${ws_folder}__${ws_full_name}")) + docker_host_name="rtw-${ws_full_name}-docker" + else + docker_image_tag="-" + docker_host_name="-" + fi + + local docker_support="$use_docker" + if [ "$is_docker_rtw_file" = true ]; then + source_path_rtw=" source /opt/RosTeamWS/ros_ws_$chosen_ros_distro/src/ros_team_workspace/scripts/environment/setup.bash \"\$RosTeamWS_DISTRO\" \"\$RosTeamWS_WS_FOLDER\" \"\$RosTeamWS_WS_PREFIX\" \"\$RosTeamWS_WS_SUFFIX\"" + docker_support=false # don't use docker in docker + else + source_path_rtw=" source $FRAMEWORK_BASE_PATH/ros_ws_\"\$RosTeamWS_DISTRO\"/src/$FRAMEWORK_NAME/scripts/environment/setup.bash \"\$RosTeamWS_DISTRO\" \"\$RosTeamWS_WS_FOLDER\" \"\$RosTeamWS_WS_PREFIX\" \"\$RosTeamWS_WS_SUFFIX\"" + fi + + echo "" >> "$ros_team_ws_file" + echo "$fun_name () {" >> "$ros_team_ws_file" + echo " RosTeamWS_BASE_WS=\"${base_ws}\"" >> "$ros_team_ws_file" + + echo " RosTeamWS_DISTRO=\"${chosen_ros_distro}\"" >> "$ros_team_ws_file" + echo " RosTeamWS_WS_FOLDER=\"${ws_folder}\"" >> "$ros_team_ws_file" + echo " RosTeamWS_WS_PREFIX=\"${ros_ws_prefix}\"" >> "$ros_team_ws_file" + echo " RosTeamWS_WS_SUFFIX=\"${ros_ws_suffix}\"" >> "$ros_team_ws_file" + echo " RosTeamWS_WS_DOCKER_SUPPORT=\"${docker_support}\"" >> "$ros_team_ws_file" + echo " RosTeamWS_DOCKER_TAG=\"${docker_image_tag}\"" >> "$ros_team_ws_file" + echo "$source_path_rtw" >> "$ros_team_ws_file" + echo "}" >> "$ros_team_ws_file" + echo "alias $alias_name=$fun_name" >> "$ros_team_ws_file" + +} + +update_config() +{ + local rtw_file=~/.ros_team_ws_rc + + setup_ros_team_ws_file "$rtw_file" "$use_docker" "$is_docker_rtw_file" + + # source new workspace + source "$rtw_file" + + # Update rosdep definitions + rosdep update -# Load Framework defines -script_own_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" -source $script_own_dir/_RosTeamWs_Defines.bash - -# ros distribution name will be set in ${ros_distro} -check_ros_distro $1 - -ws_folder="$2" -if [ -z "$2" ]; then - ws_folder="workspace" - echo "Using default '~/workspace' folder to setup ros workspace" -fi - -ros_ws_prefix="$3" -if [ -z "$3" ]; then - ros_ws_prefix="-" - echo "No ros_ws_prefix used..." -fi - -ros_ws_suffix="$4" -if [ -z "$4" ]; then - ros_ws_suffix="-" - echo "No ros_ws_suffix used..." -fi - -# TODO: Write this automatically from the user's definitions -echo "Please choose which workspace should be basis for yours:" -echo "(0) " -read choice - -if [ -z "$choice" ]; then - print_and_exit "No workspace is chosen!" "$usage" -fi - -case "$choice" in -# "1") -# base_ws=Industrial -# ;; -# "2") -# base_ws=Mobile -# ;; -"0") - base_ws="" - ;; -*) - echo "No workspace chosen! Exiting..." - exit -esac - -# Form here the full name -ws_full_name=${ros_distro} - -if [ "$ros_ws_prefix" != "-" ]; then - ws_full_name=${ros_ws_prefix}_${ws_full_name} -fi -if [ "$ros_ws_suffix" != "-" ]; then - ws_full_name=${ws_full_name}_${ros_ws_suffix} -fi - -# TODO: Add here output of the WS -echo "" -read -p "ATTENTION: Creating a new workspace in folder '${ws_folder}' for ROS '${ros_distro}' (ROS$ros_version) with suffix '${ros_ws_suffix}' (full path: '${ws_folder}/${ws_full_name}') using '${base_ws}' as base workspace. Press to continue..." - -# Create and initialise ROS-Workspace -if [[ ${base_ws} != "" ]]; then if [[ $ros_version == 1 ]]; then - source $FRAMEWORK_BASE_PATH/${base_ws}_ros_ws_${ros_distro}/devel/setup.bash + rospack profile + fi +} + +setup_docker_files () { + echo "Not implemented" +} + +# workspace folder is relative to your home +create_workspace () { + local usage="setup-ros-workspace.bash create_workspace ROS_DISTRO WS_FOLDER WS_PREFIX WS_SUFFIX" + local use_docker=false + + check_user_input "$@" + local chosen_ros_distro=$ros_distro + setup_new_workspace + + local is_docker_rtw_file=false + update_config + + echo -e "${RTW_COLOR_NOTIFY_USER}Finished creating new workspace: Please open a new terminal and execute '$alias_name'${TERMINAL_COLOR_NC}" +} + +create_workspace_docker () { + local usage="setup-ros-workspace.bash create_workspace_docker ROS_DISTRO WS_FOLDER WS_PREFIX WS_SUFFIX" + local use_docker=true + + # create new workspace locally + check_user_input "$@" + local chosen_ros_distro=$ros_distro # need to store, ros_distro gets overwritten while creating workspace... + setup_new_workspace + + # TODO(destogl): we should remove updating of configs if docker is used - can we do this already? + local is_docker_rtw_file=false + update_config + + ############################################################################ + # DOCKER PART: create corresponding docker image and map worksapce and rtw # + ############################################################################ + + # first get name for creating correct ros distro in docker + local docker_ros_distro_name + if [[ -v "map_to_docker_ros_distro_name[$chosen_ros_distro]" ]];then + docker_ros_distro_name=${map_to_docker_ros_distro_name["$chosen_ros_distro"]} + else + print_and_exit "For $chosen_ros_distro does no docker container exist." + fi + local rtw_branch_for_ros_distro + if [[ -v "ros_distro_to_rtw_branch[$docker_ros_distro_name]" ]];then + rtw_branch_for_ros_distro=${ros_distro_to_rtw_branch["$docker_ros_distro_name"]} else - source $FRAMEWORK_BASE_PATH/${base_ws}_ros_ws_${ros_distro}/install/setup.bash - fi -fi - -mkdir -p ~/${ws_folder}/${ws_full_name} -cd ~/${ws_folder}/${ws_full_name} - -if [[ $ros_version == 1 ]]; then - wstool init src - catkin config -DCMAKE_BUILD_TYPE=RelwithDebInfo - catkin build -elif [[ $ros_version == 2 ]]; then - mkdir src -# cb - colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo -fi - -# Go to Home folder of the user -cd - -# Create a function name -fun_name_suffix=${ros_distro} - -if [ "$ros_ws_prefix" != "-" ]; then - fun_name_suffix=${fun_name_suffix}_${ros_ws_prefix} -fi -if [ "$ros_ws_suffix" != "-" ]; then - fun_name_suffix=${fun_name_suffix}_${ros_ws_suffix} -fi - -alias_name=_${ws_full_name} -fun_name="RosTeamWS_setup_${fun_name_suffix}" - -cp ~/.ros_team_ws_rc ~/.ros_team_ws_rc.bkp -# Comment out the old configuration is such exists - this is hard if using functions... -sed -i -e '/'"$fun_name"'/ s/^#*/OLD_/' ~/.ros_team_ws_rc -sed -i -e '/alias st_ros'"$ros_version=$fun_name"'/ s/^#*/#/' ~/.ros_team_ws_rc - -echo "" >> ~/.ros_team_ws_rc -echo "$fun_name () {" >> ~/.ros_team_ws_rc -echo " RosTeamWS_BASE_WS=\"${base_ws}\"" >> ~/.ros_team_ws_rc -echo " RosTeamWS_DISTRO=\"${ros_distro}\"" >> ~/.ros_team_ws_rc -echo " RosTeamWS_WS_FOLDER=\"${ws_folder}\"" >> ~/.ros_team_ws_rc -echo " RosTeamWS_WS_PREFIX=\"${ros_ws_prefix}\"" >> ~/.ros_team_ws_rc -echo " RosTeamWS_WS_SUFFIX=\"${ros_ws_suffix}\"" >> ~/.ros_team_ws_rc -echo " source $FRAMEWORK_BASE_PATH/ros_ws_\"\$RosTeamWS_DISTRO\"/src/$FRAMEWORK_NAME/scripts/environment/setup.bash \"\$RosTeamWS_DISTRO\" \"\$RosTeamWS_WS_FOLDER"\" \"\$RosTeamWS_WS_PREFIX\" \"\$RosTeamWS_WS_SUFFIX\" >> ~/.ros_team_ws_rc -echo "}" >> ~/.ros_team_ws_rc -echo "alias $alias_name=$fun_name" >> ~/.ros_team_ws_rc - -# Setup new workspace -source ~/.ros_team_ws_rc - -# Update rosdep definitions -rosdep update - -if [[ $ros_version == 1 ]]; then - rospack profile -fi - -echo "------------------------------------------------------" -echo "Finished: Please open a new terminal and execute '$alias_name'" + print_and_exit "For $docker_ros_distro_name does no RosTeamWorkspace branch exist." + fi + + # setup Dockerfile bashrc and .ros_team_ws_rc + # and copy needed files to workspace dir + ws_docker_folder="${ws_folder}/${ws_full_name}/.rtw_docker_defines" + mkdir -p "$ws_docker_folder" + + # setup .bashrc + cp "$DOCKER_TEMPLATES/bashrc" "$ws_docker_folder/." + # add the name of the workspace folder in docker, so that it can be inited in bashrc the first time used. + local docker_ws_folder + docker_ws_folder="${ws_folder}/${ws_full_name}" + sed -i "s|DUMMY_WS_FOLDER|${docker_ws_folder}|g" "$ws_docker_folder/bashrc" + echo "" >> "$ws_docker_folder/bashrc" + echo "$alias_name" >> "$ws_docker_folder/bashrc" + + # setup Dockerfile: set correct docker version + cp "$DOCKER_TEMPLATES/Dockerfile" "$ws_docker_folder/." + sed -i "s/UBUNTU_DUMMY_VERSION/${ubuntu_version}/g" "$ws_docker_folder/Dockerfile" + sed -i "s/ROS_DUMMY_VERSION/${docker_ros_distro_name}/g" "$ws_docker_folder/Dockerfile" + sed -i "s/ROS_TEAM_WS_DUMMY_BRANCH/${rtw_branch_for_ros_distro}/g" "$ws_docker_folder/Dockerfile" + + # setup ros_team_ws + cp "$DOCKER_TEMPLATES/ros_team_ws_rc_docker" "$ws_docker_folder/." + # make copied .ros_team_ws match to source + local rtw_file="$ws_docker_folder/ros_team_ws_rc_docker" + sed -i "s/ROS_DUMMY_VERSION/${chosen_ros_distro}/g" "$rtw_file" + setup_ros_team_ws_file "$rtw_file" "$use_docker" "true" + + # copy file for recreating docker + cp "$DOCKER_TEMPLATES/recreate_docker.sh" "$ws_docker_folder/." + sed -i "s/DUMMY_DOCKER_IMAGE_TAG/${docker_image_tag}/g" "$ws_docker_folder/recreate_docker.sh" + sed -i "s/DUMMY_DOCKER_HOSTNAME/${docker_host_name}/g" "$ws_docker_folder/recreate_docker.sh" + sed -i "s|DUMMY_WS_FOLDER|${docker_ws_folder}|g" "$ws_docker_folder/recreate_docker.sh" + + # now we are all set for building the container + build_docker_image "$docker_image_tag" "$ws_docker_folder/Dockerfile" || { print_and_exit "Build of docker container failed."; } + + echo "" + echo "######################################################################################################################" + echo -e "${RTW_COLOR_NOTIFY_USER}Finished creating new workspace with docker support: Going to switch to docker. Next time simply run '$alias_name'${TERMINAL_COLOR_NC}" + echo "######################################################################################################################" + sleep 2 # give user time to read above message before switching to docker container + + create_docker_container "$docker_image_tag" "${docker_ws_folder}" "$chosen_ros_distro" "$docker_host_name" +} diff --git a/setup.bash b/setup.bash index 13563c2b..2e6d649e 100644 --- a/setup.bash +++ b/setup.bash @@ -1,11 +1,13 @@ -script_own_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" -FRAMEWORK_BASE_PATH=$script_own_dir +setup_script_own_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null && pwd )" # Load RosTeamWS defines -source $script_own_dir/scripts/_RosTeamWs_Defines.bash +source $setup_script_own_dir/scripts/_RosTeamWs_Defines.bash # Load Team defines -source $script_own_dir/scripts/_Team_Defines.bash +source $setup_script_own_dir/scripts/_Team_Defines.bash + +# Load Docker defines +source $setup_script_own_dir/scripts/_RosTeamWs_Docker_Defines.bash # Set main path where source.bash is defined RosTeamWS_FRAMEWORK_MAIN_PATH="$(RosTeamWS_script_own_dir)/../" diff --git a/templates/.ros_team_ws_rc b/templates/.ros_team_ws_rc index 35ab17fc..dfa12685 100644 --- a/templates/.ros_team_ws_rc +++ b/templates/.ros_team_ws_rc @@ -1,7 +1,16 @@ #!/bin/bash # RosTeamWS - main setup -source /setup.bash +DEFAULT_ROS_DISTRO="rolling" +DEFAULT_ROS_VERSION=2 + +TEAM_LICENSE="Apache License 2.0" + +TEAM_REPOSITORY_SERVER="https://github.com" + +TEAM_PRIVATE_CONFIG_PATH="" + +source /setup.bash # User specific setup / variables diff --git a/templates/docker/Dockerfile b/templates/docker/Dockerfile new file mode 100644 index 00000000..524f8784 --- /dev/null +++ b/templates/docker/Dockerfile @@ -0,0 +1,66 @@ +FROM UBUNTU_DUMMY_VERSION + +#Arguments maybe add defaults? +ARG user +ARG uid +ARG gid +ARG home + +# make bash default +SHELL ["/bin/bash", "-c"] + +# upgrade to newest version +RUN apt-get update -y && apt-get -y dist-upgrade + +# install locales +RUN apt-get update -y && apt-get install -y locales + +# Configure user env +ENV TZ=Europe/Berlin +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +# Set the locale to include UTF-8. UTF-8 compatible locales are needed for install +RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \ + locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +# Make sure UTF-8 is supported +RUN locale + +# Install basic utilities +RUN apt-get -y update && apt-get -y install git nano sudo tmux tree vim iputils-ping + +# install ROS2:ROS_DUMMY_VERSION dependencies +RUN apt-get install -y curl gnupg gnupg2 lsb-release software-properties-common && apt-add-repository universe +RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg +RUN 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" | tee /etc/apt/sources.list.d/ros2.list > /dev/null + +# install ROS2:ROS_DUMMY_VERSION and things needed for ros development, DEBIAN_FRONTEND is needed to ignore interactive keyboard layout setting while install +RUN apt-get update -y && DEBIAN_FRONTEND=noniteractive apt-get install -y ros-ROS_DUMMY_VERSION-desktop pip python3-colcon-common-extensions +RUN pip install -U rosdep && \ + rosdep init + +# setup ros_team_ws +RUN git clone -b ROS_TEAM_WS_DUMMY_BRANCH https://github.com/StoglRobotics/ros_team_workspace.git /opt/RosTeamWS/ros_ws_ROS_DUMMY_VERSION/src/ros_team_workspace/ + +# setup standard .bashrc +COPY bashrc ${home}/.bashrc +COPY ros_team_ws_rc_docker ${home}/.ros_team_ws_rc + +# clone user into docker image, add to sudo users needed for xsharing +# the passwd delete is needed to update /etc/shadow otherwise user cannot use sudo +RUN mkdir -p ${home} && \ + echo "${user}:x:${uid}:${gid}:${user},,,:${home}:/bin/bash" >> /etc/passwd && \ + echo "${user}:x:${uid}:" >> /etc/group && \ + echo "${user} ALL=(ALL) NOPASSWD: ALL" > "/etc/sudoers.d/${user}" && \ + chmod 0440 "/etc/sudoers.d/${user}" && \ + usermod -aG sudo ${user} && \ + passwd -d ${user} && \ + mkdir ${home}/workspace && \ + chown ${uid}:${gid} -R ${home} + +#switch to user +USER ${user} +WORKDIR ${home} diff --git a/templates/docker/bashrc b/templates/docker/bashrc new file mode 100644 index 00000000..e3f2627b --- /dev/null +++ b/templates/docker/bashrc @@ -0,0 +1,196 @@ +# ~/.bashrc: executed by bash(1) for non-login shells. +# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) +# for examples + +# If not running interactively, don't do anything +[ -z "$PS1" ] && return + +# don't put duplicate lines in the history. See bash(1) for more options +# ... or force ignoredups and ignorespace +HISTCONTROL=ignoredups:ignorespace + +# append to the history file, don't overwrite it +shopt -s histappend + +# for setting history length see HISTSIZE and HISTFILESIZE in bash(1) +HISTSIZE=1000 +HISTFILESIZE=2000 + +# check the window size after each command and, if necessary, +# update the values of LINES and COLUMNS. +shopt -s checkwinsize + +# make less more friendly for non-text input files, see lesspipe(1) +[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" + +# set variable identifying the chroot you work in (used in the prompt below) +if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then + debian_chroot=$(cat /etc/debian_chroot) +fi + +# set a fancy prompt (non-color, unless we know we "want" color) +case "$TERM" in + xterm-color) color_prompt=yes;; +esac + +# uncomment for a colored prompt, if the terminal has the capability; turned +# off by default to not distract the user: the focus in a terminal window +# should be on the output of commands, not on the prompt +#force_color_prompt=yes + +if [ -n "$force_color_prompt" ]; then + if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then + # We have color support; assume it's compliant with Ecma-48 + # (ISO/IEC-6429). (Lack of such support is extremely rare, and such + # a case would tend to support setf rather than setaf.) + color_prompt=yes + else + color_prompt= + fi +fi + +if [ "$color_prompt" = yes ]; then + PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ ' +else + PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' +fi +unset color_prompt force_color_prompt + +# If this is an xterm set the title to user@host:dir +case "$TERM" in +xterm*|rxvt*) + PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1" + ;; +*) + ;; +esac + + +# BEGIN: Stogl Robotics custom setup for nice colors and showing ROS workspace + +# Check this out: https://www.shellhacks.com/bash-colors/ +export TERMINAL_COLOR_NC='\e[0m' # No Color +export TERMINAL_COLOR_BLACK='\e[0;30m' +export TERMINAL_COLOR_GRAY='\e[1;30m' +export TERMINAL_COLOR_RED='\e[0;31m' +export TERMINAL_COLOR_LIGHT_RED='\e[1;31m' +export TERMINAL_COLOR_GREEN='\e[0;32m' +export TERMINAL_COLOR_LIGHT_GREEN='\e[1;32m' +export TERMINAL_COLOR_BROWN='\e[0;33m' +export TERMINAL_COLOR_YELLOW='\e[1;33m' +export TERMINAL_COLOR_BLUE='\e[0;34m' +export TERMINAL_COLOR_LIGHT_BLUE='\e[1;34m' +export TERMINAL_COLOR_PURPLE='\e[0;35m' +export TERMINAL_COLOR_LIGHT_PURPLE='\e[1;35m' +export TERMINAL_COLOR_CYAN='\e[0;36m' +export TERMINAL_COLOR_LIGHT_CYAN='\e[1;36m' +export TERMINAL_COLOR_LIGHT_GRAY='\e[0;37m' +export TERMINAL_COLOR_WHITE='\e[1;37m' + +export TERMINAL_BG_COLOR_BLACK='\e[40m' +export TERMINAL_BG_COLOR_GRAY='\e[1;40m' +export TERMINAL_BG_COLOR_RED='\e[41m' +export TERMINAL_BG_COLOR_LIGHT_RED='\e[1;41m' +export TERMINAL_BG_COLOR_GREEN='\e[42m' +export TERMINAL_BG_COLOR_LIGHT_GREEN='\e[1;42m' +export TERMINAL_BG_COLOR_BROWN='\e[43m' +export TERMINAL_BG_COLOR_YELLOW='\e[1;43m' +export TERMINAL_BG_COLOR_BLUE='\e[44m' +export TERMINAL_BG_COLOR_LIGHT_BLUE='\e[1;44m' +export TERMINAL_BG_COLOR_PURPLE='\e[45m' +export TERMINAL_BG_COLOR_LIGHT_PURPLE='\e[1;45m' +export TERMINAL_BG_COLOR_CYAN='\e[46m' +export TERMINAL_BG_COLOR_LIGHT_CYAN='\e[1;46m' +export TERMINAL_BG_COLOR_LIGHT_GRAY='\e[47m' +export TERMINAL_BG_COLOR_WHITE='\e[1;47m' + +if [ -n "$SSH_CLIENT" ]; then text="-ssh-session" +fi + +function parse_vc_branch_and_add_brackets { + gitbranch=`git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'` + + if [[ "$gitbranch" != '' ]]; then + echo "<${gitbranch}" +# else +# echo "\['"\[${TERMINAL_COLOR_LIGHT_PURPLE}\]"'\W\['"\[${TERMINAL_COLOR_LIGHT_PURPLE}\]"'$\['"\[${TERMINAL_COLOR_NC}\]"'\[\e[m\] ' + +# END: Stogl Robotics custom setup for nice colors and showing ROS workspace + + +# enable color support of ls and also add handy aliases +if [ -x /usr/bin/dircolors ]; then + test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)" + alias ls='ls --color=auto' + #alias dir='dir --color=auto' + #alias vdir='vdir --color=auto' + + alias grep='grep --color=auto' + alias fgrep='fgrep --color=auto' + alias egrep='egrep --color=auto' +fi + +# some more ls aliases +alias ll='ls -alF' +alias la='ls -A' +alias l='ls -CF' + +# Add an "alert" alias for long running commands. Use like so: +# sleep 10; alert +alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"' + +# Alias definitions. +# You may want to put all your additions into a separate file like +# ~/.bash_aliases, instead of adding them here directly. +# See /usr/share/doc/bash-doc/examples in the bash-doc package. + +if [ -f ~/.bash_aliases ]; then + . ~/.bash_aliases +fi + +# enable programmable completion features (you don't need to enable +# this, if it's already enabled in /etc/bash.bashrc and /etc/profile +# sources /etc/bash.bashrc). +if [ -f /etc/bash_completion ] && ! shopt -oq posix; then + . /etc/bash_completion +fi + +ws_inited_check_file=~/.rtw_ws_inited +ws_folder=DUMMY_WS_FOLDER +if [ ! -e "$ws_inited_check_file" ] && [ ! -d "$HOME/$ws_folder/src" ]; then + touch "$ws_inited_check_file" + cd "$HOME/$ws_folder" || { echo "Could not init workspace $ws_folder. You have to init the workspace yourself."; return 1;} + mkdir src + colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=RelWithDebInfo + rosdep update + cd ~/ +fi + +# source ros_team_ws_rc automatically +if [ -f ~/.ros_team_ws_rc ]; then + . ~/.ros_team_ws_rc +fi diff --git a/templates/docker/recreate_docker.sh b/templates/docker/recreate_docker.sh new file mode 100755 index 00000000..3dba2e4e --- /dev/null +++ b/templates/docker/recreate_docker.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash +# Copyright (c) 2022, Stogl Robotics Consulting UG (haftungsbeschränkt) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +build_docker_image () { + docker build \ + --build-arg user=$USER \ + --build-arg uid=$UID \ + --build-arg gid=$GROUPS \ + --build-arg home=$HOME \ + -t DUMMY_DOCKER_IMAGE_TAG . +} + +create_docker_container () { + xhost +local:docker + docker run \ + --net=host \ + -h DUMMY_DOCKER_HOSTNAME \ + -e DISPLAY \ + --tmpfs /tmp \ + -v /tmp/.X11-unix/:/tmp/.X11-unix:rw \ + -v "$HOME/DUMMY_WS_FOLDER":"$HOME/$DUMMY_WS_FOLDER":rw \ + -v "$HOME/.ssh":"$HOME/.ssh":ro \ + --name DUMMY_DOCKER_IMAGE_TAG-instance \ + -it DUMMY_DOCKER_IMAGE_TAG /bin/bash +} + +build_docker_image +create_docker_container diff --git a/templates/docker/ros_team_ws_rc_docker b/templates/docker/ros_team_ws_rc_docker new file mode 100644 index 00000000..3db26112 --- /dev/null +++ b/templates/docker/ros_team_ws_rc_docker @@ -0,0 +1,30 @@ +#!/bin/bash + +# This is used for docker, to include ros_team_workspace inside docker and auto source it. + +# RosTeamWS - main setup +DEFAULT_ROS_DISTRO="ROS_DUMMY_VERSION" +DEFAULT_ROS_VERSION=2 + +TEAM_LICENSE="Apache License 2.0" + +TEAM_REPOSITORY_SERVER="https://github.com" + +TEAM_PRIVATE_CONFIG_PATH="" + +# ros_team_workspace is always at same location inside docker. +source /opt/RosTeamWS/ros_ws_ROS_DUMMY_VERSION/src/ros_team_workspace/setup.bash + +# User specific setup / variables + +#export CYCLONEDDS_URI='ADD_HERE_INTERFACE_NAME' + +export ROS_DOMAIN_ID=46 # Set your Domain ID if you are in a network with multiple computers + +# Logging setup +# export RCUTILS_LOGGING_CONFIG_FILE="/home/deniss/workspace/ros2_logging_config" +#export RCUTILS_CONSOLE_OUTPUT_FORMAT="[{severity} {time}] [{name}]: {message} ({function_name}() at {file_name}:{line_number})" # Custom logging format +export RCUTILS_COLORIZED_OUTPUT=1 +#export RCUTILS_LOGGING_USE_STDOUT=1 # force all logging output to stdout + +# WORKSPACES