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

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/219537.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python超详细基础文件操作【建议收藏】

文章目录 前言1 文件操作1.1 文件打开与关闭1.1.1 打开文件1.1.2 关闭文件 1.2 访问模式及说明 2 文件读写2.1 写数据&#xff08;write&#xff09;2.2 读数据&#xff08;read&#xff09;2.3 读数据&#xff08;readlines&#xff09;2.3 读数据&#xff08;readline&#x…

机器学习-ROC曲线:技术解析与实战应用

本文全面探讨了ROC曲线&#xff08;Receiver Operating Characteristic Curve&#xff09;的重要性和应用&#xff0c;从其历史背景、数学基础到Python实现以及关键评价指标。文章旨在提供一个深刻而全面的视角&#xff0c;以帮助您更好地理解和应用ROC曲线在模型评估中的作用。…

CSS中 设置文字下划线 的几种方法

在网页设计和开发中&#xff0c;我们经常需要对文字进行样式设置&#xff0c;包括字体,颜色&#xff0c;大小等&#xff0c;其中&#xff0c;设置文字下划线是一种常见需求 一 、CSS种使用 text-decoration 属性来设置文字的装饰效果&#xff0c;包括下划线。 常用的取值&…

蓝桥杯算法心得——仙界诅咒(dfs)

大家好&#xff0c;我是晴天学长&#xff0c;搜索型的dfs&#xff0c;差点开二维矩阵了&#xff0c;仔细一想&#xff0c;没那么夸张啊&#xff0c;哈哈哈&#xff0c;需要的小伙伴可以关注支持一下哦&#xff01;后续会继续更新的。&#x1f4aa;&#x1f4aa;&#x1f4aa; 1…

计算机视觉之手势、面部、姿势捕捉以Python Mediapipe为工具

计算机视觉之手势、面部、姿势捕捉以 Python Mediapipe为工具 文章目录 1.Mediapipe库概述2.手势捕捉(hands)3.面部捕捉(face)4.姿势捕捉(pose) 1.Mediapipe库概述 Mediapipe是一个开源且强大的Python库&#xff0c;由Google开发和维护。它提供了丰富的工具和功能&#xff0c…

java--接口概述

1.认识接口 ①java提供了一个关键字interface&#xff0c;用这个关键字我们可以定义出一个特殊的结构&#xff1a;接口。 ②注意&#xff1a;接口不能创建对象&#xff1b;接口是用来被类实现(implements)的&#xff0c;实现接口的类称为实现类。 ③一个类可以实现多个接口(接…

ROS2教程05 ROS2服务

ROS2服务 版权信息 Copyright 2023 Herman YeAuromix. 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 right…

热点新闻 | 许战海:零食行业的革新之道

2023年11月29日&#xff0c;华糖万商大会在南京国际会展中心隆重举行。著名战略定位咨询专家许战海受邀出席&#xff0c;在“量贩零食产业年度盛典”上发表了主题为《如何通过竞争战略布局年度规划》的精彩演讲&#xff0c;吸引了众多业界关注。 演讲中&#xff0c;许战海老师指…

23史上最全版---SQL注入详解

漏洞原因 一些概念&#xff1a; SQL&#xff1a;用于数据库中的标准数据查询语言。 web分为前端和后端&#xff0c;前端负责进行展示&#xff0c;后端负责处理来自前端的请求并提供前端展示的资源。 而数据库就是存储资源的地方。 而服务器获取数据的方法就是使用SQL语句进…

c语言编译优化引发问题

问题描述 同样的代码,不优化编译,可以正常执行,经过-O2优化编译后,代码被卡住.整体功能涉及多进程,多线程操作. 问题发现 经过加打印,发现卡在while(a!0);//死循环,等待特殊事件发生来解开循环 a初始化为-1; 过一会后,另外有个线程,当特定事件发生的时候,将a置为0; 通过加打…

【云备份】客户端实现 及 项目整体总结

文章目录 客户端客户端实现思想客户端文件操作类的设计与拷贝Util.hpp的设计data.hpp的设计Storage —— 持久化存储Initload——数据初始化加载 cloud.hpp的设计GetFileIdentifier——创建文件唯一标识Upload—— 文件上传IsNeedupload —— 客户端文件是否需要上传判断RunMod…

【原创分享】高功率电源PCB设计中变压器下方走线的关键技巧

高功率电源的设计中&#xff0c;变压器起到了电能的传递与转换的重要作用。变压器下方的走线设计不仅涉及到电路的功率传输效率&#xff0c;还与电磁兼容性&#xff08;EMC&#xff09;、热管理以及电路的可靠性密切相关。 1. 走线布局 在进行变压器下方走线设计时&#xff0c…

Vmware虚拟机简介和安装

作者&#xff1a;余小小 常见的虚拟机 vmwarevirtualBox Vmware 运行在win系统上centos运行在Vm上 先安装vm&#xff0c;在安装centos系统 Vmware介绍 不用分区或者重开机&#xff0c;就可以在同一台pc上使用多种操作系统完全隔离&#xff0c;且保护不同的操作系统环境和文…

Kubernetes常用工作负载控制器

文章目录 一、常用负载控制器是什么二、Deployment控制器1.介绍2.使用流程3.应用部署4.应用升级5.滚动升级实现原理&#xff08;replicaset控制器&#xff09;6.滚动升级实现流程7.滚动升级策略8.应用实例扩容和缩容9.应用发布失败回滚10.应用下线 三、DaemonSet控制器四、Job控…

Linux修改时区失败,手动修改localtime无效

有时候改了这个也不行&#xff0c;用命令行修改也不行 解决办法 &#xff1a;cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 或者想改其他时区的直接 ll /usr/share/zoneinfo/ 查看

2023年1月18日 Go生态洞察:开发者的声音与Go的进化

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

WebGL开发交互式艺术品技术方案

开发交互式艺术品需要使用 WebGL 技术&#xff0c;并结合其他前端技术以实现丰富的用户体验。以下是一个可能的技术方案&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1.WebGL 框架&#xff1a; 选…

AWS攻略——子网

文章目录 分配子网给Public子网分配互联网网关创建互联网网关附加到VPC 给Public子网创建路由表关联子网 打通Public子网和互联网网关 创建Public子网下的EC2进行测试配置Private子网路由给Private子网创建路由表附加在Private子网 创建Private子网下的EC2进行测试创建实例在跳…

Cannot resolve com.lxz.springcloud:cloud-api-commons:1.0-SNAPSHOT

原因可能是groupId等信息写错了 导入的jar包的groupId要与它自己的坐标匹配

创新、升级丨数据手套FOHEART Pro开启手势识别新篇章!

在人机交互领域&#xff0c;我们始终追求更加自然、逼真的体验。正如现实生活中&#xff0c;我们习惯于通过语言和表情来传达思想和情感&#xff0c;然而&#xff0c;在虚拟世界中&#xff0c;人机交互需要以更加直观、生动的方式进行操作、控制和交互。 为了更好地满足市场的…