ros2

Setsuna00發表於2024-07-09

注:已從RoboMaster退隊,懶得更新

第一章 ros2介紹

1.1 ros為什麼會出現

做一個機器人是非常複雜的一件事情,因為一個機器人需要涉及到多個部分,而且這些部分之間還要進行通訊

例如設計一個像下圖一樣的輪式移動機器人,我們對其進行拆解。可以分為感知、決策、控制三個部分

  • 感知部分有:鐳射雷達、深度相機、IMU、里程計、碰撞感知、建圖
  • 決策部分有:路徑規劃(navigation)演算法、定位演算法
  • 控制部分有:輪子驅動

1.2 ros與ros2對比

上節課說到ROS的設計目標是簡化機器人的開發,如何簡化呢?ROS為此設計了一整套通訊機制(話題、服務、引數、動作)。

透過這些通訊機制,ROS實現了將機器人的各個元件給的連線起來,在設計這套通訊機制的時候就設計了一個叫做Ros Master的東西,所有節點(可以理解為某一個元件,比如:鐳射雷達)的通訊建立必須經過這個主節點。

一旦Ros Master主節點掛掉後,就會造成整個系統通訊的異常,此時避障策略將會失效,如果機器人正在執行,碰到障礙物會徑直裝上去,機毀人亡!

除了不穩定這個問題,ROS還有很多其他地方存在著問題:

  • 通訊基於TCP實現,實時性差、系統開銷大
  • 對Python3支援不友好,需要重新編譯
  • 訊息機制不相容
  • 沒有加密機制、安全性不高

中間層:去中心化Ros Master,各個節點採用DDS通訊,使得ROS2的實時性、可靠性和連續性上都有了增強。

第二章 準備環境與安裝ROS2

2.1 安裝虛擬機器和Ubuntu

2.2安裝ros

  • Ubuntu20.04->foxy
  • Ubuntu22.04->humble
  • 魚香肉絲一鍵安裝ros2:wget http://fishros.com/install -O fishros && bash fishros

2.3 VsCode編輯器安裝與配置

  • 下載:https://code.visualstudio.com/docs/?dv=linux64_deb
  • 安裝sudo dpkg -i code_1.58.0-1625728071_amd64.deb

第三章 ROS2基礎

3.1 節點介紹

節點與節點之間必須要通訊,那他們之間該如何通訊呢?ROS2早已為你準備好了一共四種通訊方式:

  • 話題-topics
  • 服務-services
  • 動作-Action
  • 引數-parameters

啟動節點ros2 run <package_name> <executable_name> (指令意義:啟動 包下的 中的節點。)

檢視節點列表ros2 node list

檢視節點資訊ros2 node info <node_name>

3.2 ROS2工作空間與功能包

一個工作空間下可以有多個功能包,一個功能包可以有多個節點存在。

  • 工作空間:工作空間是包含若干個功能包的目錄,一開始大家把工作空間理解成一個資料夾就行了。
  • 功能包:功能包可以理解為存放節點的地方,ROS2中功能包根據編譯方式的不同分為三種型別。
    • ament_python,適用於python程式
    • cmake,適用於C++
    • ament_cmake,適用於C++程式,是cmake的增強版

功能包的獲取

  1. 安裝獲取:sudo apt install ros-<version>-package_name(安裝獲取會自動放置到系統目錄,不用再次手動source。)
  2. 手動編譯獲取:手動編譯相對麻煩一些,需要下載原始碼然後進行編譯生成相關檔案。(手動編譯之後,需要手動source工作空間的install目錄。)

功能包的相關指令

  • 建立功能包ros2 pkg create <package-name> --build-type {cmake,ament_cmake,ament_python} --dependencies <依賴名字>Copy to clipboard
  • 列出可執行檔案ros2 pkg executables
  • 列出某個功能包ros2 pkg executables turtlesim
  • 列出所有包ros2 pkg list
  • 列出某個包所在路徑的字首ros2 pkg prefix <package-name>
  • 列出包的清單描述檔案(每一個功能包都有一個標配的manifest.xml檔案,用於記錄這個包的名字,構建工具,編譯資訊,擁有者,幹啥用的等資訊。)ros2 pkg xml turtlesim

3.3 ROS2的編譯器Colcon

##小練習

#建立工作空間
mkdir -p turtle_ws/src
cd turtle_ws/src

#下載原始碼功能包到工作空間的src檔案下
git clone https://github.com/fishros/turtle_battle.git

#進入工作空間上一級編譯
cd ..
colcon build

#source空間
source install/setup.bash

#啟動遊戲節點
##開啟一個新終端,進入turtle_ws工作空間,啟動以下節點:
ros2 run turtle_battle turtle_spawner

#啟動烏龜模擬器
##開啟一個新終端,進入turtle_ws工作空間,啟動以下節點:
ros2 run turtlesim turtlesim_node

#開啟遙控器節點
##開啟一個新終端,進入turtle_ws工作空間,啟動以下節點:
ros2 run turtlesim turtle_teleop_key


建立工作空間和功能包

#建立工作空間
mkdir -p town_ws/src
cd town_ws/src

#建立一個功能包
ros2 pkg create village_li --build-type ament_python --dependencies rclpy

#建立節點檔案
##在__init__.py同級別目錄下建立一個叫做li4.py的檔案

使用POP(程序導向程式設計)方法編寫一個節點

#開啟lib4.py
import rclpy
from rclpy.node import Node
def main(args=None):
    """
    ros2執行該節點的入口函式
    編寫ROS2節點的一般步驟
    1. 匯入庫檔案
    2. 初始化客戶端庫
    3. 新建節點物件
    4. spin迴圈節點
    5. 關閉客戶端庫
    """
    rclpy.init(args=args) # 初始化rclpy
    node = Node("li4")  # 新建一個節點
    node.get_logger().info("大家好,我是作家li4.")
    rclpy.spin(node) # 保持節點執行,檢測是否收到退出指令(Ctrl+C)
    rclpy.shutdown() # 關閉rclpy
    
#修改setup.py
##增加一句話,告訴ros2村莊來了一位新村民李四,要找這位村民去village_li.li4:main路徑下尋找。
entry_points={
        'console_scripts': [
            "li4_node = village_li.li4:main"
        ],
    },
)

#編譯,source

#執行節點
ros2 run village_li li4_node

物件 = 屬性+行為

如果只需要實現一個很簡單的功能,比如只是做一個鍵盤控制器,實現控制小車前進後退,直接採用程序導向的設計思想即可。但如果是做一個稍大的工程,且後續要考慮功能的擴充性,這個時候就需要採用物件導向的思路來了。

使用OOP(物件導向程式設計)方法編寫一個節點

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node

class WriterNode(Node):
    """
    建立一個作家節點,並在初始化時輸出一個話
    """
    def __init__(self,name):
        super().__init__(name)
        self.get_logger().info("大家好,我是%s,我是一名作家!" % name)


def main(args=None):
    """
    ros2執行該節點的入口函式
    1. 匯入庫檔案
    2. 初始化客戶端庫
    3. 新建節點
    4. spin迴圈節點
    5. 關閉客戶端庫
    """
    rclpy.init(args=args) # 初始化rclpy
    node = WriterNode("li4")  # 新建一個節點
    rclpy.spin(node) # 保持節點執行,檢測是否收到退出指令(Ctrl+C)
    rclpy.shutdown() # 關閉rclpy
    
#修改setup.py
##增加一句話,告訴ros2村莊來了一位新村民李四,要找這位村民去village_li.li4:main路徑下尋找。
entry_points={
        'console_scripts': [
            "li4_node = village_li.li4:main"
        ],
    },
)

#編譯,source

#執行節點
ros2 run village_li li4_node

POP使用C++編寫節點並測試

#建立一個C++功能包
ros2 pkg create village_wang --build-type ament_cmake --dependencies rclcpp

#建立一個節點
##接著我們在village_wang/src下建立一個wang2.cpp檔案
//POP
#include "rclcpp/rclcpp.hpp"
int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    /*產生一個Wang2的節點*/
    auto node = std::make_shared<rclcpp::Node>("wang2");
    // 列印一句自我介紹
    RCLCPP_INFO(node->get_logger(), "大家好,我是單身狗wang2.");
    /* 執行節點,並檢測退出訊號*/
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}



//OOP
#include "rclcpp/rclcpp.hpp"
/*建立一個類節點,名字叫做SingleDogNode,繼承自Node.*/
class SingleDogNode : public rclcpp::Node
{
public:
    // 建構函式,有一個引數為節點名稱
    SingleDogNode(std::string name) : Node(name)
    {
        // 列印一句自我介紹
        RCLCPP_INFO(this->get_logger(), "大家好,我是單身狗%s.",name.c_str());
    }
};

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    /*產生一個Wang2的節點*/
    auto node = std::make_shared<SingleDogNode>("wang2");
    /* 執行節點,並檢測退出訊號*/
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}
#新增到CmakeLists
##在CmakeLists.txt最後一行加入下面兩行程式碼。(新增這兩行程式碼的目的是讓編譯器編譯wang2.cpp這個檔案,不然不會主動編譯。)
add_executable(wang2_node src/wang2.cpp)
ament_target_dependencies(wang2_node rclcpp)

#接著在上面兩行程式碼下面新增下面的程式碼。(這個是C++比Python要麻煩的地方,需要手動將編譯好的檔案安裝到install/village_wang/lib/village_wang下)
install(TARGETS
  wang2_node
  DESTINATION lib/${PROJECT_NAME}
)

第四章 通訊機制-話題與服務

我們讓王二(Node)透過訂閱(Subscribe)李四(Node)釋出(Publish)的《豔娘傳奇》(Topic)來欣賞小說的。

4.1 話題

需要滿足以下規則:

  • 話題名字是關鍵,釋出訂閱介面型別要相同,釋出的是字串,接受也要用字串來接收;
  • 同一個人(節點)可以訂閱多個話題,同時也可以釋出多個話題,就像一本書的作者也可以是另外一本書的讀者;
  • 同一個小說不能有多個作者(版權問題),但跟小說不一樣,同一個話題可以有多個釋出者。

工具RQT之rqt_graph

ros2 run demo_nodes_py listener
ros2 run demo_nodes_cpp talker
rqt_graph
  • ROS2作為一個強大的工具,在執行過程中,我們是可以透過命令來看到節點和節點之間的資料關係的。

ROS2話題相關命令列介面(CLI)

ros2 topic -h

返回系統中當前活動的所有主題的列表:ros2 topic list

接著上一條,增加訊息型別:ros2 topic list -t

列印實時話題內容:ros2 topic echo /chatter

檢視主題內容:ros2 topic info /chatter

4.2 ROS2話題程式設計實現