ROS2的安装和配置
版权信息
Copyright 2023 Herman Ye@Auromix. All rights reserved.
This course and all of its associated content, including but not limited to text,
images, videos, and any other materials, are protected by copyright law.
The author holds all rights to this course and its contents.
Any unauthorized use, reproduction, distribution, or modification of this course
or its contents is strictly prohibited and may result in legal action.
This includes, but is not limited to:
Copying or distributing course materials without express written permission.
Reposting, sharing, or distributing course content on any platform without proper attribution and permission.
Creating derivative works based on this course without permission.
Permissions and Inquiries
If you wish to use or reproduce any part of this course for purposes other than personal learning,
please contact the author to request permission.
The course content is provided for educational purposes, and the author makes no warranties or representations
regarding the accuracy, completeness, or suitability of the course content for any specific purpose.
The author shall not be held liable for any damages, losses,
or other consequences resulting from the use or misuse of this course.
Please be aware that this course may contain materials or images obtained from third-party sources.
The author and course creator diligently endeavor to ensure that these materials
are used in full compliance with copyright and fair use regulations.
If you have concerns about any specific content in this regard,
please contact the author for clarification or resolution.
By enrolling in this course, you agree to abide by the terms and conditions outlined in this copyright notice.
学习目标
- 熟悉ROS2的安装及基本环境配置
- 了解ROS2的基本环境配置脚本
- 熟悉ROS2的基本测试方式
- 熟悉ROS2的工作空间的配置
- 了解ROS2中命令行工具的使用
- 熟悉ROS2的领域设置
难度级别
初级 | 中级 | 高级 |
---|---|---|
√ |
预计耗时
40 mins
学习前提
对象 | 类型 | 状态 |
---|---|---|
Ubuntu22.04操作系统 | 软件 | 已确认 |
Shell的基本使用 | 知识 | 已了解 |
快速安装ROS2
若希望快速安装ROS 2,可以使用一键安装脚本。以下是适用于2023年10月31日版本的脚本代码,如需获取最新代码,请访问Auromix一键安装脚本:
wget -O $HOME/ros2_humble_install.sh https://raw.githubusercontent.com/auromix/ros-install-one-click/main/ros2_humble_install.sh && sudo chmod +x $HOME/ros2_humble_install.sh && bash $HOME/ros2_humble_install.sh && rm $HOME/ros2_humble_install.sh
这一组合命令将下载最新的ROS 2安装脚本,使其可执行,然后运行以安装ROS 2。安装完成后,将自动删除已下载的安装脚本。
以下为2023-10-31版本的示例脚本代码:
#!/bin/bash
#
# Copyright 2023 Herman Ye @Auromix
#
# 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.
#
# Description:
# This is a shell script for installing ROS2 Humble and its dependencies in Ubuntu 22.04.
# It uses mirrors from Tsinghua University to speed up the download.
# The script also sets up the sudo privileges and modifies the sources.list file to update the repositories accordingly.
# It installs ROS2 Humble and its dependencies, initializes rosdep.
# It logs the installation progress and redirects the output to the console and logs files.
#
# Version: 1.0
# Date: 2023-10-31
# Author: Herman Ye @Auromix
#
# Warning: This script is ONLY for ROS2 Humble in ubuntu 22.04
# set -x
set -e
# Get script directory
SCRIPT_DIR=$(dirname "$0")
# Get the username of the non-root user
USERNAME=$USERNAME
echo "Current user is: $USERNAME"
echo "Script directory is: $SCRIPT_DIR"
# Save logs to files
LOG_FILE="${SCRIPT_DIR}/ros2_humble_install.log"
ERR_FILE="${SCRIPT_DIR}/ros2_humble_install.err"
echo "Cleaning up traces of last installation..."
rm -f ${LOG_FILE}
rm -f ${ERR_FILE}
# Redirect output to console and log files
exec 1> >(tee -a ${LOG_FILE} )
exec 2> >(tee -a ${ERR_FILE} >&2)
# Output log info to console
echo "Installation logs will be saved to ${LOG_FILE}"
echo "Installation errors will be saved to ${ERR_FILE}"
# Waiting to start
echo "Start to install ROS2 Humble..."
sleep 3
# No Password sudo config
echo "Setting no-passwd sudo"
sudo sed -i 's/^%sudo.*/%sudo ALL=(ALL) NOPASSWD:ALL/g' /etc/sudoers
# Get architecture of the system
if [ $(uname -m) = "x86_64" ]; then
MIRROR="https://mirrors.tuna.tsinghua.edu.cn/ubuntu/"
else
MIRROR="https://mirrors.tuna.tsinghua.edu.cn/ubuntu-ports/"
fi
echo "Current system architecture is: $(uname -m)"
echo "Current mirror is: $MIRROR"
# Backup original software sources
echo "Backing up sources.list to /etc/apt/sources.list.backup ..."
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
# Clear original software sources
echo "# Ubuntu Mirror Settings" | sudo tee /etc/apt/sources.list
# Replace software sources using tee
echo "deb $MIRROR jammy main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
echo "deb $MIRROR jammy-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
echo "deb $MIRROR jammy-backports main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
if [ $(uname -m) = "x86_64" ]; then
echo "deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
else
echo "deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
fi
# System update
echo "Start to update software..."
sudo apt update
echo "Start to upgrade software..."
sudo apt upgrade -y
# Install pip
echo "Installing pip..."
sudo apt install python3-dev -y
sudo apt install pip -y # If you haven't already installed pip
# Set default pip source
echo "configuring pip source..."
pip config set global.index-url http://pypi.tuna.tsinghua.edu.cn/simple
pip config set global.trusted-host pypi.tuna.tsinghua.edu.cn
# check for UTF-8
echo "Checking locale..."
echo "Current locale:"
locale
# Set language
echo "Setting language..."
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
# verify settings
echo "Checking locale..."
locale
# Enable Ubuntu Universe repository
echo "Enabling Ubuntu Universe repository..."
sudo apt install software-properties-common -y
sudo add-apt-repository universe -y
# Add the ROS 2 GPG key with apt
echo "Adding the ROS 2 GPG key with apt..."
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
# Add the repository to your sources list
echo "Adding the ROS 2 repository to your sources list..."
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
# Update apt repository caches
echo "Updating software caches..."
sudo apt update
echo "Upgrading software..."
sudo apt upgrade -y
# Install ROS
echo "Installing ROS2 Humble..."
# ROS Desktop Install(ROS, RViz, demos, tutorials)
sudo apt install ros-humble-desktop -y
# ROS Base Install(Communication libraries, message packages, command line tools but no GUI tools)
sudo apt install ros-humble-ros-base -y
# Development tools(Compilers and other tools to build ROS packages)
sudo apt install ros-dev-tools -y
# Install build tool
sudo apt install python3-colcon-common-extensions -y
# Environment setup
if ! grep -q "source /opt/ros/humble/setup.bash" /home/$USERNAME/.bashrc; then
echo "# ROS2 HUMBLE ENVIRONMENT SETTINGS" | sudo tee -a /home/$USERNAME/.bashrc
echo "source /opt/ros/humble/setup.bash" | sudo tee -a /home/$USERNAME/.bashrc
echo "ROS2 Humble environment setup added to /home/$USERNAME/.bashrc"
else
echo "ROS2 Humble environment is already set in /home/$USERNAME/.bashrc"
fi
source /home/$USERNAME/.bashrc
# Create your ROS2 workspace
if [ -d "$workspace_dir" ]; then
echo " ROS2 workspace already exists, skip creating."
else
echo "Creating ROS2 workspace"
cd /home/$USERNAME
mkdir -p ros2_workspace/src
cd /home/$USERNAME/ros2_workspace
# Install package dependencies
echo "Installing package dependencies..."
sudo pip install rosdep
sudo pip install rosdepc
sudo rosdepc init > /dev/null
rosdepc update > /dev/null
rosdep install --from-paths src --ignore-src --rosdistro humble -y
echo "Building workspace..."
colcon build
fi
# System update again
sudo apt update
sudo apt dist-upgrade -y
# Verifying ROS2 installation
clear
# Define the variables to be printed
TEXT1="ROS2 Humble installation completed!"
TEXT2="Please open new terminals and run commands to verify the installation:"
TEXT3="ros2 run demo_nodes_cpp talker"
TEXT4="ros2 run demo_nodes_py listener"
# Define the colors
RED='\033[0;31m'
BLUE='\033[0;34m'
GREEN='\033[1;32m'
NC='\033[0m'
# Calculate the center of the terminal window
TERMINAL_WIDTH=$(tput cols)
TEXT1_PADDING=$((($TERMINAL_WIDTH-${#TEXT1})/2))
TEXT2_PADDING=$((($TERMINAL_WIDTH-${#TEXT2})/2))
TEXT3_PADDING=$((($TERMINAL_WIDTH-${#TEXT3})/2))
TEXT4_PADDING=$((($TERMINAL_WIDTH-${#TEXT4})/2))
# Print the text in the center of the screen in the desired colors
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo -e "${GREEN}$(printf '%*s' $TEXT1_PADDING)${TEXT1} ${NC}"
echo -e "${NC}$(printf '%*s' $TEXT2_PADDING)${TEXT2} ${NC}"
echo -e "${RED}$(printf '%*s' $TEXT3_PADDING)${TEXT3} ${NC}"
echo -e "${RED}$(printf '%*s' $TEXT4_PADDING)${TEXT4} ${NC}"
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
echo ""
# # Remove ROS2
# sudo apt remove ~nros-humble-* && sudo apt autoremove
# sudo rm /etc/apt/sources.list.d/ros2.list
# sudo apt update
# sudo apt autoremove
# # Consider upgrading for packages previously shadowed.
# sudo apt upgrade
安装完成后,您将看到以下窗口显示。如果您在安装过程中遇到任何问题,您可以查看ros2_humble_install.err
和ros2_humble_install.log
以进行进一步的故障排除。
正常安装ROS2
在Linux系统中,通常使用Debian软件包的方式来安装ROS 2,当前的ROS 2版本为Humble Hawksbill,适配Ubuntu 22.04操作系统。
1.设置语言环境
首先,我们需要更新系统的本地化设置,将系统的默认语言环境设置为英语(美国)并使用UTF-8编码。这是因为如果系统没有正确配置UTF-8编码,处理包含非英语字符的文本可能会导致问题。
# check for UTF-8
locale
# Set language
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
# verify settings
locale
2.设置源
为了确保后续命令的正常执行,我们需要使用software-properties-common
工具集,它提供了管理软件源的必要工具,方便系统的后续操作。
此外,我们还需要启用Ubuntu Universe存储库,因为它包含了一些额外的自由和开源软件,其中有一些将被ROS 2所使用。
# Enable Ubuntu Universe repository
sudo apt install software-properties-common
sudo add-apt-repository universe
接下来,我们将从ROS 2的官方GitHub存储库下载ROS 2的GPG密钥,并将其保存在/usr/share/keyrings/ros-archive-keyring.gpg
文件中。这个GPG密钥文件将在后续用于验证ROS 2软件包的签名,以确保它们没有被篡改或受到恶意软件的侵害。
# Add the ROS 2 GPG key with apt
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
为了将ROS 2软件源添加到系统的软件源列表中,您需要执行以下命令。这将告诉系统在哪里查找和下载ROS 2软件包,以便轻松地安装它们。
这个命令的结构如下:
# Add the repository to your sources list
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
现在让我们分解这个命令:
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main"
部分是要添加到软件源列表的ROS 2软件源的描述。它包括以下信息:arch=$(dpkg --print-architecture)
: 这部分动态指定了系统的架构,以确保只下载与系统架构匹配的ROS 2软件包。signed-by=/usr/share/keyrings/ros-archive-keyring.gpg
: 这指定了软件源的签名密钥文件的路径,用于验证ROS 2软件包的完整性和安全性,以防止在下载过程中被篡改。http://packages.ros.org/ros2/ubuntu
: 这是ROS 2软件包仓库的地址,告诉系统从哪里获取软件包。$(. /etc/os-release && echo $UBUNTU_CODENAME)
: 这部分用于获取当前Ubuntu发行版的代号,以确保添加与Ubuntu版本匹配的ROS 2软件包到软件源列表中。
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
这一部分将ROS 2软件源的描述写入名为ros2.list
的文件,并使用sudo
权限来执行此操作。tee
命令还将标准输出重定向到/dev/null
,以确保不会看到额外的输出。
通过执行此命令成功地将ROS 2软件源添加到系统的软件源列表中,使系统能够识别和下载与Ubuntu版本兼容的ROS 2软件包。这是安装和使用ROS 2的第一步。
cat /etc/apt/sources.list.d/ros2.list
deb [arch=amd64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu jammy main
通过读取ros2.list
软件源配置文件,可以了解以下信息:
deb
: 这表示软件源条目的类型,指示这是一个二进制包(deb)存储库,其中包含可执行程序、库和其他二进制文件,而不是源代码。[arch=amd64]
: 这部分规定了软件源支持的CPU架构。在这种情况下,它明确指定了只支持amd64架构的二进制包。这确保了只有与指定架构兼容的软件包会被下载和安装。signed-by=/usr/share/keyrings/ros-archive-keyring.gpg
: 这一部分指定了软件源的数字签名文件的位置。数字签名文件是用于验证软件包完整性和真实性的关键元素,以确保它们没有在传输过程中被篡改。在这里,软件源使用名为ros-archive-keyring.gpg
的公钥文件来验证软件包的签名,增强了软件包的来源可信度。http://packages.ros.org/ros2/ubuntu
: 这是软件源的URL地址,告诉系统从哪里获取软件包。在这种情况下,软件包存储库位于http://packages.ros.org/ros2/ubuntu
,以确保系统知道在哪里查找ROS 2软件包。jammy
: 这是软件源的分发版本或代号,用于指定特定Ubuntu发行版的版本。在这里,它指明了Ubuntu 22.04版本的代号为"Jammy",确保下载与所安装Ubuntu版本兼容的ROS 2软件包。main
: 这表示软件源中的组件,指定了软件源包含的软件包的主要部分。通常情况下,"main"包含了核心和由官方维护的软件包,而其他组件可能包含额外的软件包,例如工具或扩展包。这有助于组织和管理软件包,确保核心软件包易于找到和安装。
3.更新包
在添加了ROS源后更新软件源的缓存、重新加载软件包列表、检查可用的软件包更新以及获取最新的软件包信息,然后升级系统中已安装的软件包。这可以通过以下命令完成:
# Update apt repository caches
sudo apt update
sudo apt upgrade
4.安装ROS2
安装ROS 2的桌面版本,这将包括ROS核心、RViz可视化工具、编译工具以及一些演示和教程。以下是具体的安装步骤:
# Install ROS
# ROS Desktop Install(ROS, RViz, demos, tutorials)
sudo apt install ros-humble-desktop
# ROS Base Install(Communication libraries, message packages, command line tools but no GUI tools)
sudo apt install ros-humble-ros-base
# Development tools(Compilers and other tools to build ROS packages)
sudo apt install ros-dev-tools
# Install build tool
sudo apt install python3-colcon-common-extensions
5.ROS环境设置
在ROS 2中,我们需要配置环境以确保系统正常运行。为了实现这一点,我们可以利用用户新开终端时执行的.bashrc
脚本文件。.bashrc
文件包含了终端会话的各种配置选项,其中之一是将ROS 2的环境设置脚本添加到该文件中。以下是在.bashrc
文件中添加ROS 2环境设置脚本的详细步骤:
要访问ROS 2命令和ROS 2软件包,您需要在每次打开新的shell终端时执行以下命令,以获取安装文件或将source
命令添加到shell启动脚本中。如果未执行这些步骤,您将无法使用ROS 2命令或访问ROS 2软件包
source /opt/ros/humble/setup.bash
echo "# ROS2 ENVIRONMENT SETTINGS" >> ~/.bashrc
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
打开名为 setup.bash
的文件,我们将详细解读其中的内容,以便更好地理解ROS在环境设置方面所执行的操作:
AMENT_SHELL=bash
这一行代码设置了一个名为 AMENT_SHELL
的环境变量,并将其值设置为 "bash"
。这个环境变量决定了在执行脚本时要使用哪种shell。
通过运行ls /opt/ros/humble/
命令,我们可以看到在该目录下有多个不同种类的shell脚本文件,这些文件用于配置ROS环境。
`AMENT_CURRENT_PREFIX=$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" && pwd)`
这行代码用于获取当前脚本文件所在目录的绝对路径,并将该路径保存在名为 AMENT_CURRENT_PREFIX
的变量中。在这一行中,有以下关键步骤:
${BASH_SOURCE[0]}
:这是一个bash内置变量,包含了当前脚本文件的完整绝对路径,即/opt/ros/humble/setup.bash
。dirname "${BASH_SOURCE[0]}"
:它从脚本的完整绝对路径中提取出脚本所在的目录部分,即/opt/ros/humble/
。cd "
dirname “${BASH_SOURCE[0]}”"
:这一步将进入脚本所在的目录,即/opt/ros/humble/
。pwd
:最后,pwd
命令用于获取当前工作目录的绝对路径,并将其存储在AMENT_CURRENT_PREFIX
变量中,即AMENT_CURRENT_PREFIX=/opt/ros/humble/
。
值得注意的是,builtin
是一个bash内置命令,用于执行与shell相关的内部命令,通过明确使用 builtin
,可以确保使用的是shell内部命令而不是外部命令。
if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
echo "# . \"$AMENT_CURRENT_PREFIX/setup.sh\""
fi
这段代码检查是否已经定义并且不为空的 AMENT_TRACE_SETUP_FILES
环境变量。如果该条件成立,就会输出一行文本,这行文本包含了一个用于source(执行) AMENT_CURRENT_PREFIX/setup.sh
脚本的命令。这可能是用于AMENT调试的目的,通常情况下不需要理会。
. "$AMENT_CURRENT_PREFIX/setup.sh"
最后,这一行代码执行了名为 AMENT_CURRENT_PREFIX/setup.sh
的脚本,它进一步加载和配置与该ROS软件包相关的环境变量和设置,确保ROS环境正确设置和准备就绪。
ROS2环境配置脚本解析
以下是对ROS2环境配置脚本的详细解析,这有助于理解脚本的功能以及如何处理环境变量和路径
那么我们进一步地了解这个真正的环境脚本到底做了什么,这对于在同时使用Conda、ROS等组件时出现环境问题的debug有理解上的帮助:
脚本中使用的ament_append_unique_value()
函数的目的是将_value
追加到名为_listname
的环境变量中,但仅在_value
尚未存在于_listname
中时才执行追加操作。此函数还确保在追加值时不会出现前导分隔符(冒号),并且只追加不重复的值。这种方法通常用于处理环境变量,特别适用于路径列表等情况,以确保唯一性和正确的分隔符使用。
# iterate over all parent_prefix_path files
_prefix_setup_IFS=$IFS
IFS="
"
# this variable contains the concatenated prefix paths in reverse order
_UNIQUE_PREFIX_PATH=""
# this check is used to skip parent prefix path in the Debian package
if [ -z "SKIP_PARENT_PREFIX_PATH" ]; then
# find parent prefix path files for all packages under the current prefix
_RESOURCES="$(\find "$AMENT_CURRENT_PREFIX/share/ament_index/resource_index/parent_prefix_path" -mindepth 1 -maxdepth 1 2> /dev/null | \sort)"
if [ "$AMENT_SHELL" = "zsh" ]; then
ament_zsh_to_array _RESOURCES
fi
for _resource in $_RESOURCES; do
# read the content of the parent_prefix_path file
_PARENT_PREFIX_PATH="$(\cat "$_resource")"
# reverse the list
_REVERSED_PARENT_PREFIX_PATH=""
IFS=":"
if [ "$AMENT_SHELL" = "zsh" ]; then
ament_zsh_to_array _PARENT_PREFIX_PATH
fi
for _path in $_PARENT_PREFIX_PATH; do
# replace placeholder of current prefix
if [ "$_path" = "{prefix}" ]; then
_path="$AMENT_CURRENT_PREFIX"
fi
# avoid leading separator
if [ -z "$_REVERSED_PARENT_PREFIX_PATH" ]; then
_REVERSED_PARENT_PREFIX_PATH=$_path
else
_REVERSED_PARENT_PREFIX_PATH=$_path:$_REVERSED_PARENT_PREFIX_PATH
fi
done
unset _PARENT_PREFIX_PATH
# collect all unique parent prefix path
if [ "$AMENT_SHELL" = "zsh" ]; then
ament_zsh_to_array _REVERSED_PARENT_PREFIX_PATH
fi
for _path in $_REVERSED_PARENT_PREFIX_PATH; do
ament_append_unique_value _UNIQUE_PREFIX_PATH "$_path"
done
unset _REVERSED_PARENT_PREFIX_PATH
done
unset _resource
unset _RESOURCES
fi
接下来的代码片段用于查找并处理软件包的父前缀路径,然后将它们反转并附加到名为_UNIQUE_PREFIX_PATH
的变量中,以确保这些路径是唯一的。这个步骤对于在Debian包中正确处理软件包的依赖关系和前缀路径非常重要。
首先,代码检查了SKIP_PARENT_PREFIX_PATH
变量,以确定是否应跳过父前缀路径的处理。然后,它查找所有位于当前前缀下的软件包的父前缀路径文件,并将它们按照一定的顺序合并到变量_UNIQUE_PREFIX_PATH
中,同时确保在合并过程中不会出现前导分隔符(冒号)。
# append this directory to the prefix path
ament_append_unique_value _UNIQUE_PREFIX_PATH "$AMENT_CURRENT_PREFIX"
unset AMENT_CURRENT_PREFIX
# store AMENT_SHELL to restore it after each prefix
_prefix_setup_AMENT_SHELL=$AMENT_SHELL
# source local_setup.EXT or local_setup.sh file for each prefix path
IFS=":"
if [ "$AMENT_SHELL" = "zsh" ]; then
ament_zsh_to_array _UNIQUE_PREFIX_PATH
fi
for _path in $_UNIQUE_PREFIX_PATH; do
# trace output
if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
echo "# . \"$_path/local_setup.$AMENT_SHELL\""
fi
if [ -f "$_path/local_setup.$AMENT_SHELL" ]; then
if [ "$AMENT_SHELL" = "sh" ]; then
# provide AMENT_CURRENT_PREFIX to .sh files
AMENT_CURRENT_PREFIX=$_path
fi
# restore IFS before sourcing other files
IFS=$_prefix_setup_IFS
. "$_path/local_setup.$AMENT_SHELL"
# restore AMENT_SHELL after each prefix-level local_setup file
AMENT_SHELL=$_prefix_setup_AMENT_SHELL
fi
done
最后的部分用于将当前前缀路径添加到_UNIQUE_PREFIX_PATH
中,然后依次处理所有前缀路径,为每个前缀路径的local_setup.EXT
或local_setup.sh
文件执行源代码操作,以确保正确设置环境。如果设置了AMENT_TRACE_SETUP_FILES
变量,脚本还会输出正在源代码的文件路径,以便跟踪操作。在这个过程中,它还会在每个前缀路径的local_setup
文件执行之前和之后分别保存和还原AMENT_SHELL
环境变量,以确保正确的环境设置。
# local_setup.sh
# generated from ament_package/template/prefix_level/local_setup.sh.in
# since a plain shell script can't determine its own path when being sourced
# either use the provided AMENT_CURRENT_PREFIX
# or fall back to the build time prefix (if it exists)
_ament_prefix_sh_AMENT_CURRENT_PREFIX="/opt/ros/humble"
if [ -z "$AMENT_CURRENT_PREFIX" ]; then
if [ ! -d "$_ament_prefix_sh_AMENT_CURRENT_PREFIX" ]; then
echo "The build time path \"$_ament_prefix_sh_AMENT_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"AMENT_CURRENT_PREFIX\" explicitly." 1>&2
unset _ament_prefix_sh_AMENT_CURRENT_PREFIX
return 1
fi
else
_ament_prefix_sh_AMENT_CURRENT_PREFIX="$AMENT_CURRENT_PREFIX"
fi
# set type of shell if not already set
: ${AMENT_SHELL:=sh}
# use the Python executable known at configure time
_ament_python_executable="/usr/bin/python3.10"
# allow overriding it with a custom location
if [ -n "$AMENT_PYTHON_EXECUTABLE" ]; then
_ament_python_executable="$AMENT_PYTHON_EXECUTABLE"
fi
# if the Python executable doesn't exist try another fall back
if [ ! -f "$_ament_python_executable" ]; then
if /usr/bin/env python3 --version > /dev/null
then
_ament_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
else
echo error: unable to find fallback python3 executable
return 1
fi
fi
# function to source another script with conditional trace output
# first argument: the path of the script
_ament_prefix_sh_source_script() {
if [ -f "$1" ]; then
if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
echo "# . \"$1\""
fi
. "$1"
else
echo "not found: \"$1\"" 1>&2
fi
}
# function to prepend non-duplicate values to environment variables
# using colons as separators and avoiding trailing separators
ament_prepend_unique_value() {
# arguments
_listname="$1"
_value="$2"
#echo "listname $_listname"
#eval echo "list value \$$_listname"
#echo "value $_value"
# check if the list contains the value
eval _values=\"\$$_listname\"
_duplicate=
_ament_prepend_unique_value_IFS=$IFS
IFS=":"
if [ "$AMENT_SHELL" = "zsh" ]; then
ament_zsh_to_array _values
fi
for _item in $_values; do
# ignore empty strings
if [ -z "$_item" ]; then
continue
fi
if [ "$_item" = "$_value" ]; then
_duplicate=1
fi
done
unset _item
# prepend only non-duplicates
if [ -z "$_duplicate" ]; then
# avoid trailing separator
if [ -z "$_values" ]; then
eval export $_listname=\"$_value\"
#eval echo "set list \$$_listname"
else
# field separator must not be a colon
unset IFS
eval export $_listname=\"$_value:\$$_listname\"
#eval echo "prepend list \$$_listname"
fi
fi
IFS=$_ament_prepend_unique_value_IFS
unset _ament_prepend_unique_value_IFS
unset _duplicate
unset _values
unset _value
unset _listname
}
# get all commands in topological order
_ament_additional_extension=""
if [ "$AMENT_SHELL" != "sh" ]; then
_ament_additional_extension="${AMENT_SHELL}"
fi
_ament_ordered_commands="$($_ament_python_executable "$_ament_prefix_sh_AMENT_CURRENT_PREFIX/_local_setup_util.py" sh $_ament_additional_extension)"
unset _ament_additional_extension
unset _ament_python_executable
if [ -n "$AMENT_TRACE_SETUP_FILES" ]; then
echo "_ament_prefix_sh_source_script() {
if [ -f \"\$1\" ]; then
if [ -n \"\$AMENT_TRACE_SETUP_FILES\" ]; then
echo \"# . \\\"\$1\\\"\"
fi
. \"\$1\"
else
echo \"not found: \\\"\$1\\\"\" 1>&2
fi
}"
echo "# Execute generated script:"
echo "# <<<"
echo "${_ament_ordered_commands}"
echo "# >>>"
echo "unset _ament_prefix_sh_source_script"
fi
eval "${_ament_ordered_commands}"
unset _ament_ordered_commands
unset _ament_prefix_sh_source_script
unset _ament_prefix_sh_AMENT_CURRENT_PREFIX
这个脚本主要用于配置ROS软件包的运行时环境,比如设置Python可执行文件、环境变量和执行生成的Shell命令以确保软件包正确初始化,包括以下步骤:
首先,它检查是否设置了环境变量
AMENT_CURRENT_PREFIX
,如果未设置,它将使用默认的路径/opt/ros/humble
作为AMENT_CURRENT_PREFIX
。然后,它设置了一个名为
AMENT_SHELL
的环境变量,用于指定shell类型,默认为sh
。接下来,它确定要使用的Python解释器。它首先尝试使用已知的Python可执行文件
/usr/bin/python3.10
,如果设置了AMENT_PYTHON_EXECUTABLE
环境变量,它将使用该变量指定的Python解释器。如果两者都不存在,它将尝试使用Ubuntu 22.04系统默认的/usr/bin/env python3
。接下来,它定义了两个函数:
_ament_prefix_sh_source_script()
用于条件性地加载另一个脚本,以及ament_prepend_unique_value()
用于在环境变量中添加非重复的值。然后,它执行了
_local_setup_util.py
脚本,该脚本会查找已安装的ROS软件包,并构建它们之间的依赖关系,然后对软件包进行拓扑排序,以确保按正确的顺序生成Shell命令,以设置ROS软件包的运行时环境。这些生成的Shell命令存储在_ament_ordered_commands
变量中。最后,如果设置了
AMENT_TRACE_SETUP_FILES
环境变量,脚本会输出一些关于脚本执行的跟踪信息,包括_ament_prefix_sh_source_script()
函数的定义和生成的Shell命令。
值得一提的是ROS2使用/usr/bin/python3.10
作为解释器,如果没找到将,使用Ubuntu22.04系统默认的/usr/bin/env python3
,在执行这个脚本前可以通过$AMENT_PYTHON_EXECUTABLE
变量来指定python解释器,如果在调试中遇到Python的版本冲突问题,可以再回顾看看。
6.检查ROS2基本环境
# Check environment variables
printenv | grep -i ROS
确保输出的和ROS有关理环境变量中,ROS的版本为ROS2,ROS的python版本为python3,ROS的发行版本为humble
ROS_VERSION=2
ROS_PYTHON_VERSION=3
ROS_DISTRO=humble
7.创造工作空间
ROS 2的正常运行依赖于工作区(Workspace)的概念,这是ROS 2的核心术语,用于定义开发ROS 2应用程序的位置。ROS 2的核心工作区被称为“底层工作区”,而随后创建的本地工作区则被称为“覆盖工作区”。在进行ROS 2开发时,通常会同时存在多个活动的工作区。
可以将工作空间类比为公司内的多个办公室,每个办公室有其特定职能。如果以项目为单位划分工作空间,那么一个项目的相关软件包可能会被组织在同一个工作空间内,以避免不同项目之间的干扰。
例如,在一个机器人项目中,与该项目相关的软件包通常会被放置在同一个工作空间中,以确保项目的整体开发和管理。
以下是创建工作空间、使用rosdep进行软件包依赖管理以及编译整个工作空间的命令
# Go to your home directory
cd ~
# Create workspace
mkdir -p ros2_workspace/src
# Go to your workspace
cd ~/ros2_workspace
# Install rosdep
sudo pip install rosdep
# Init rosdep
sudo rosdepc init
# Update rosdep
rosdepc update
# Install dependecies for packages in workspace
rosdep install --from-paths src --ignore-src --rosdistro humble -y
# Build workspace
colcon build
完成工作空间的编译后,您可以找到工作空间的环境设置脚本位于~/ros2_workspace/install/setup.bash
。要访问此工作区中的ROS 2软件包和相关命令,您需要在每次打开新的shell终端时执行以下命令,以覆盖ROS 2的基本环境设置(opt/ros/humble/setup.bash
),以便使用工作区的设置。否则,工作区中的软件包将无法被发现:
source ~/ros2_workspace/install/setup.bash
配置ROS 2 领域(当需要时)
当同一个局域网下有多个机器人在运行时,就会有冲突问题,在ROS中,这个问题通过DOMAIN来解决。
在ROS 2中,领域(Domain)是一种机制,用于控制ROS 2节点之间的通信和消息传递。要配置领域,您可以选择一个安全数字,该数字应在0到101(包括101)之间。不同领域中的ROS 2节点之间无法直接通信,这有助于隔离不同网络逻辑,以确保通信的安全性和可靠性。默认情况下,所有ROS 2节点都使用领域ID 0,但为了避免来自不同组计算机上运行的ROS 2节点之间的干扰,建议为每个组设置不同的领域ID。
ROS 2使用一种称为DDS(Data Distribution Service)的中间件来进行通信,默认情况下,DDS使用领域ID来计算UDP端口,用于节点之间的通信。UDP端口是无符号的16位整数,可以分配的最高端口号是65535。根据DDS中使用的公式,可以将最高领域ID设置为232,而最低领域ID为0。
默认情况下,Linux内核分配了一定范围的端口作为临时端口,通常为32768-60999。这意味着,领域ID范围在0-101和215-232之间是安全的,因为它们不会与临时端口发生冲突。如果需要自定义临时端口范围,可以通过更改/proc/sys/net/ipv4/ip_local_port_range
文件中的值来配置。在使用自定义临时端口范围时,需要相应地调整领域ID的选择。
以下是有关ROS 2领域配置的一些建议链接和环境变量设置:
- 使用领域ID到UDP端口计算器来计算领域ID对应的UDP端口。
- 更多关于领域的相关文章可以在这里找到。
若要配置ROS 2节点的领域ID,可以使用以下命令,将
<your_domain_id>
替换为所需的领域ID:export ROS_DOMAIN_ID=<your_domain_id>
此外,如果您希望将ROS 2通信限制为仅与本地主机通信,可以使用ROS_LOCALHOST_ONLY环境变量。这将使您的ROS 2系统及其主题、服务和操作仅对本地网络上的其他计算机不可见。这在某些环境中非常有用,例如教室,其中多个机器人可能会发布到同一主题,以避免可能导致不确定行为的冲突。要启用此功能,可以使用以下命令:
export ROS_LOCALHOST_ONLY=1
这些配置选项可帮助您更好地管理ROS 2通信和确保系统的可靠性和安全性。
删除ROS2及其源(当需要时)
当ROS环境出现问题且无法解决时,可以尝试删除ROS2及源
sudo apt remove ~nros-humble-* && sudo apt autoremove
sudo rm /etc/apt/sources.list.d/ros2.list
sudo apt update
sudo apt autoremove
# Consider upgrading for packages previously shadowed.
sudo apt upgrade
测试ROS2
案例1: 基本Topic通信
在ROS2中,我们将展示如何使用经典的示例演示启动并测试Topic类型的节点通信是否正常。这个示例将涉及两个节点,一个负责发布消息(talker),另一个负责接收并显示这些消息(listener)。
运行节点
# Terminal 1
source /opt/ros/humble/setup.bash
ros2 run demo_nodes_cpp talker
# Terminal 2
source /opt/ros/humble/setup.bash
ros2 run demo_nodes_py listener
案例2:Turtlesim
Turtlesim是ROS2中的一个经典演示程序,它实现了ROS2的一些基本功能,非常适合初学者了解ROS2。可以将其视为ROS2的“Hello World”。
通过以下ROS2命令行工具,您可以打开三个终端窗口:一个用于运行turtlesim_node的终端,一个用于运行turtle_teleop_key的终端,以及一个用于显示turtlesim窗口的终端。排列这些窗口,以便您可以在turtlesim窗口中观察海龟的运动,并同时让turtle_teleop_key的终端保持活动状态,以便您可以使用键盘控制海龟。
# Run turtlesim node
ros2 run turtlesim turtlesim_node
# Run turtlesim keyboard node
ros2 run turtlesim turtle_teleop_key
查看节点列表
使用以下命令通过ros2 node list来查询ROS2系统中当前的所有活跃节点:
# Check current node list
ros2 node list
查看话题列表
使用以下命令通过ros2 topic list来查询ROS2系统中当前的所有有效话题:
# Check current topic list
ros2 topic list