ROS2教程02 ROS2的安装、配置和测试

本文涉及的产品
资源编排,不限时长
简介: 本文是关于ROS2(机器人操作系统2)的安装、配置和测试的教程。内容包括使用一键安装脚本快速安装ROS2 Humble版,手动安装步骤,设置语言环境、添加软件源、更新软件包、安装ROS2桌面版和开发工具,配置ROS2环境,创建工作空间,配置ROS2领域以避免网络冲突,以及如何删除ROS2。此外,还包括了测试ROS2是否安装成功的两个案例:基本的Topic通信测试和使用Turtlesim演示程序。适用于Ubuntu 22.04操作系统。

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.errros2_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

现在让我们分解这个命令:

  1. "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软件包到软件源列表中。

  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.EXTlocal_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命令以确保软件包正确初始化,包括以下步骤:

  1. 首先,它检查是否设置了环境变量AMENT_CURRENT_PREFIX,如果未设置,它将使用默认的路径/opt/ros/humble作为AMENT_CURRENT_PREFIX

  2. 然后,它设置了一个名为AMENT_SHELL的环境变量,用于指定shell类型,默认为sh

  3. 接下来,它确定要使用的Python解释器。它首先尝试使用已知的Python可执行文件/usr/bin/python3.10,如果设置了AMENT_PYTHON_EXECUTABLE环境变量,它将使用该变量指定的Python解释器。如果两者都不存在,它将尝试使用Ubuntu 22.04系统默认的/usr/bin/env python3

  4. 接下来,它定义了两个函数:_ament_prefix_sh_source_script() 用于条件性地加载另一个脚本,以及ament_prepend_unique_value() 用于在环境变量中添加非重复的值。

  5. 然后,它执行了_local_setup_util.py脚本,该脚本会查找已安装的ROS软件包,并构建它们之间的依赖关系,然后对软件包进行拓扑排序,以确保按正确的顺序生成Shell命令,以设置ROS软件包的运行时环境。这些生成的Shell命令存储在_ament_ordered_commands变量中。

  6. 最后,如果设置了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

在这里插入图片描述

相关实践学习
使用ROS创建VPC和VSwitch
本场景主要介绍如何利用阿里云资源编排服务,定义资源编排模板,实现自动化创建阿里云专有网络和交换机。
阿里云资源编排ROS使用教程
资源编排(Resource Orchestration)是一种简单易用的云计算资源管理和自动化运维服务。用户通过模板描述多个云计算资源的依赖关系、配置等,并自动完成所有资源的创建和配置,以达到自动化部署、运维等目的。编排模板同时也是一种标准化的资源和应用交付方式,并且可以随时编辑修改,使基础设施即代码(Infrastructure as Code)成为可能。 产品详情:https://www.aliyun.com/product/ros/
目录
相关文章
|
21天前
|
测试技术 Linux 虚拟化
iOS自动化测试方案(五):保姆级VMware虚拟机安装MacOS
详细的VMware虚拟机安装macOS Big Sur的保姆级教程,包括下载VMware和macOS镜像、图解安装步骤和遇到问题时的解决方案,旨在帮助读者顺利搭建macOS虚拟机环境。
30 3
iOS自动化测试方案(五):保姆级VMware虚拟机安装MacOS
|
22天前
|
存储 自然语言处理 机器人
ROS2教程06 ROS2行动
这篇文章是关于ROS2(Robot Operating System 2)行动(Action)通信机制的教程,包括行动的概念、特点、命令行工具的使用,以及如何编写行动的客户端和服务器代码,并介绍了如何测试行动通信。
49 4
ROS2教程06 ROS2行动
|
14天前
|
Ubuntu Shell C++
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
30 1
|
21天前
|
测试技术 开发工具 虚拟化
iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程
这篇文章提供了一份保姆级的教程,指导如何在MacOS虚拟机上安装Xcode,包括环境准备、基础软件安装以及USB扩展插件的使用,以实现iOS自动化测试方案的第一步。
23 0
iOS自动化测试方案(一):MacOS虚拟机保姆级安装Xcode教程
|
22天前
|
机器人 Shell 开发者
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
这篇文章是关于ROS2(Robot Operating System 2)中功能包、依赖管理、工作空间配置和编译的教程,涵盖了ROS2工作空间的概念、如何获取和安装功能包的依赖、构建工作空间的步骤,以及如何创建和管理ROS2功能包,包括使用命令行工具对功能包进行操作的方法。
55 0
ROS2教程08 ROS2的功能包、依赖管理、工作空间配置与编译
|
22天前
|
编解码 机器人 C++
ROS2教程07 ROS2自定义消息接口
这篇文章是关于如何在ROS2(Robot Operating System 2)中创建和使用自定义消息类型的教程,包括消息类型的定义、特点、命令行工具的使用,以及如何编写和测试自定义消息类型接口的步骤。
13 0
ROS2教程07 ROS2自定义消息接口
|
16天前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
18天前
|
网络协议 测试技术 网络安全
Python进行Socket接口测试的实现
在现代软件开发中,网络通信是不可或缺的一部分。无论是传输数据、获取信息还是实现实时通讯,都离不开可靠的网络连接和有效的数据交换机制。而在网络编程的基础中,Socket(套接字)技术扮演了重要角色。 Socket 允许计算机上的程序通过网络进行通信,它是网络通信的基础。Python 提供了强大且易于使用的 socket 模块,使开发者能够轻松地创建客户端和服务器应用,实现数据传输和交互。 本文将深入探讨如何利用 Python 编程语言来进行 Socket 接口测试。我们将从基础概念开始介绍,逐步引导大家掌握创建、测试和优化 socket 接口的关键技能。希望本文可以给大家的工作带来一些帮助~
|
19天前
|
SQL Java 测试技术
SpringBoot单元测试快速写法问题之PorkService 接口中的 getPork 方法的作用如何解决
SpringBoot单元测试快速写法问题之PorkService 接口中的 getPork 方法的作用如何解决
|
21天前
|
XML Web App开发 数据挖掘
Postman接口测试工具全解析:功能、脚本编写及优缺点探讨
文章详细分析了Postman接口测试工具的功能、脚本编写、使用场景以及优缺点,强调了其在接口自动化测试中的强大能力,同时指出了其在性能分析方面的不足,并建议根据项目需求和个人偏好选择合适的接口测试工具。
30 1

推荐镜像

更多