天天看點

NO.14 關于ROS2的第一個程式

零蝕

這應該也會很困擾一些沒有過ros開發,又想直接ros2開始的人吧

開啟第一個ros2程式

  • 從環境搭建開始

    • 如果沒有經曆過ros的開發,在macos上開發ros2你可能會很淩亂,這些都是啥,到底該怎麼開發,用什麼ide,怎麼做才能讓開發變得簡潔。當有ros開發經驗後,你會發現其實我們要做的内容和之前大緻一樣(官網上啥都沒說,隻是說你打開你喜歡的編輯文本,現在能用文本編輯c++和python代碼)。
    • 如果沒有ros開發和安裝經驗的話,可以先去看一下我的關于ros安裝和第一個程式

    [ 🔗 NO.1 Ros 安裝&介紹 ]

    [ 🔗 NO.2 Ros 第一個程式(cpp & py)]。

    ~/ros2/install/setup.bash
    ~/ros2/ros2-osx/setup.bash
               
    • 然後我們建立我們包,在src的路徑下,這裡和ros就大不同了,ros感覺比較雜揉,它裡面是cpp和python在一起開發(我之前用的是clion),項目裡有個頂層CmakeLists來管理項目,c++可能需要用到catkin cmake來重新建構項目,但是如果在裡面編輯python代碼,完全是不必要的,是以這就很亂,而且,python和c++可以編輯相同的功能,就會顯得沒必要在一起混合開發,用某一個語言不就可以了?,當然ros2網上還闡述了很多優點(對标ros)。然後ros2 就被拆開了,python做python項目,c++做c++項目,這裡的build-type就是限定做的項目類型,但不能将兩個項目類型放在一起。

      . install/local_setup.bash

      是将目前的運作環境設定為ros的專屬環境。
    cd ~/ws/src 
    #cpp
    ros2 pkg create --build-type ament_cmake <package_name>
    ros2 pkg create --build-type ament_cmake --node-name my_node my_package
    #python
    ros2 pkg create --build-type ament_python <package_name>
    ros2 pkg create --build-type ament_python --node-name my_node my_package
    
    # 建構
    cd ~/ws
    colcon build
    colcon build --packages-select my_package
    
     # 将軟體包添加到目前路徑的環境中
    . install/local_setup.bash
    
               
    • 然後就是如何編輯代碼,如果你是沒有開發過ros,大機率是輕按兩下clion或者pycharm,但是打開你會發現,clion不能解析CmakeLists檔案,pycharm也不能

      import rclpy

      (這個等同于ros中的rospy,ros的python庫)。項目在建構的時候就找不到ros2的運作庫,哪怕你将python位址改成ros2安裝的[email protected]也不行。
    • 回想ros不難發現,ros開發(基于ubuntu的linux)它是将項目在ros的運作環境下打開的,比如

      sh clion.sh

      ,它是在ros的運作環境中打開了軟體的shell運作腳本,是以ros2必然也是這樣,在尋找中我發現了如下兩個執行檔案,在合理的猜測下解決了編譯器的問題
    # cpp 和ros一樣是打開CmakeLists檔案
    /Applications/Clion.app/Contents/MacOS/clion
    # python 
    /Applications/PyCharm.app/Contents/MacOS/pycharm
               
    • 然後我們先看一下clion,運作後是這樣當我們打開了clion之後open項目,選擇我們cpp項目的頂層CMakelists之後,我們可以看到Cmake (Debug)建構完成,表示項目已經建構成功。反之如果出現報錯,則是不是ros環境中打開,導緻找不到調用的庫。
    NO.14 關于ROS2的第一個程式
    NO.14 關于ROS2的第一個程式
    NO.14 關于ROS2的第一個程式
    • 然後我們看一下python,python開發就簡單許多了,因為完全用不到頂層CMakeLists是以我們不需要以項目的形式打開某個檔案,直接用PyCharm正常打開項目就行,如果導入rclpy沒有報錯,說明打開成功,反之沒有在環境中打開項目。
    NO.14 關于ROS2的第一個程式
    • 項目建立就到這,這些都是官網甚至外網都沒解決的問題,其實也就是舉一反三的事,并沒什麼,但沒必要在這方面浪費時間,最後來看一下運作項目,作為一個有折騰過ros經驗的人,能清楚的知道,我們不能在IDE圖示上點選運作,因為這樣是錯的,很多東西不會在環境中生效,是以老規矩,指令行(以python項目為例):
    NO.14 關于ROS2的第一個程式

小知識點

  • launch

    • launch的功能是為了一次性開啟多個node,因為我們可能編輯了很多node,為了友善同時開啟,ros是加入了launch這個啟動項,ros中launch 是在項目下的 launch檔案夾中進行編寫,而ros2項目進行了拆分,是以launch是在項目之外建立的。這裡我是在ros_ws目錄下建構的。然後重點是我運作官網的案例報錯了,經過認真比對錯誤日志,我發現,官網的寫法在我這是有問題的,如果想運作多個node的正确寫法應該如下:
    rom launch import LaunchDescription
    from launch_ros.actions import Node
    
    def generate_launch_description():
        return LaunchDescription([
            Node(
                package='turtlesim',
    	    	node_executable='turtlesim_node',
                name='sim1'
            ),
            Node(
                package='turtlesim',
    	    	node_executable='turtlesim_node',
                name='sim2'
            )
        ])
               
    ros2 launch turtlesim_minic_test_launch.py
               
    NO.14 關于ROS2的第一個程式
    • 為了更好了解節點之間的關系,我們可以使用rqt_graph
    NO.14 關于ROS2的第一個程式
    • 檢視ros2的日志消息使用rqt_console
    ros2 run rqt_console rqt_console 
               
    NO.14 關于ROS2的第一個程式
    • 展示所有的topic

      ros2 topic list

      ,如果想知道topic所攜帶message的類型可使用

      ros2 topic list -t

    NO.14 關于ROS2的第一個程式

ROS2 開發

  • topic開發(Python)

    • topic就是一個消息池,功能和UDP類似。代碼如下:
    # publish
    import rclpy
    from rclpy.node import Node
    from std_msgs.msg import String
    import time
    
    
    def main(args=None):
        rclpy.init(args=args)
        # 建構一個node
        node = Node("my_demo_publish")
        # 建構一個publish
        publish = node.create_publisher(String, 'my_topic', 100)
    
        for i in range(0, 9):
            content = String()
            content.data = "消息的index:"+str(i)
            publish.publish(content)
            node.get_logger().info('Publishing: "%s"' % content.data)
            time.sleep(1)
    
        rclpy.spin(node)
    
    
    if __name__ == '__main__':
        main()
        
    # Subscribe
    import rclpy
    from rclpy.node import Node
    from std_msgs.msg import String
    
    node = None
    
    
    # 監聽的回調函數
    def call_bask(msg):
        node.get_logger().info('Publishing: "%s"' % msg.data)
    
    
    def main(args=None):
        rclpy.init(args=args)
        # 建構一個node
        global node
        node = Node("my_demo_subscribe")
        # 建構一個subscribe
        subscribe = node.create_subscription(String, 'my_topic', call_bask, 100)
        rclpy.spin(node)
    
    
    if __name__ == '__main__':
        main()
               
    • 檔案名分别對應publish–>py_my_demo,subscribe–>py_my_demo1,然後我們将其建構到我們的build裡面去。首先我們要在setup.py中添加我們node,
    entry_points={
        'console_scripts': [
            'py_my_demo = py_demo.py_my_demo:main',
            'py_my_demo1 = py_demo.py_my_demo1:main'
        ],
    },
               
    • 然後建構項目
    colcon build --packages-select py_demo
    ros2 run  py_demo py_my_demo1
    ros2 run py_demo py_my_demo 
               
    • 輸出内容👌
    # publish
    [INFO] [my_demo_publish]: Publishing: "消息的index:0"
    [INFO] [my_demo_publish]: Publishing: "消息的index:1"
    [INFO] [my_demo_publish]: Publishing: "消息的index:2"
    [INFO] [my_demo_publish]: Publishing: "消息的index:3"
    [INFO] [my_demo_publish]: Publishing: "消息的index:4"
    [INFO] [my_demo_publish]: Publishing: "消息的index:5"
    [INFO] [my_demo_publish]: Publishing: "消息的index:6"
    [INFO] [my_demo_publish]: Publishing: "消息的index:7"
    [INFO] [my_demo_publish]: Publishing: "消息的index:8"
    # subscribe
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:0"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:1"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:2"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:3"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:4"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:5"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:6"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:7"
    [INFO] [my_demo_subscribe]: Publishing: "消息的index:8"
               
  • topic開發(Cpp)

    • 在開發c++的功能時候需要先在CMakeLists中導入對應的庫
    NO.14 關于ROS2的第一個程式
    • 然後我們看一下cpp的代碼實作。官網上都是以類的形式,我覺得沒必要,我這都簡化了。
    NO.14 關于ROS2的第一個程式
    // publish
    #include <cstdio>
    #include <chrono>
    #include <memory>
    #include <iostream>
    
    #include "rclcpp/rclcpp.hpp"
    #include "std_msgs/msg/string.hpp"
    
    using  namespace std;
    
    
    
    int main(int argc, char **argv) {
        rclcpp::init(argc,argv);
        //建立一個publish
        auto node = rclcpp::Node::make_shared("cpp_demo_publisher");
    
        //建構推送
        auto publisher=node->create_publisher<std_msgs::msg::String>("my_topic",10);
        auto message = std_msgs::msg::String();
    
        //1s内執行的速度
        rclcpp::WallRate rate(1);
        for (int i = 0; i < 10; ++i) {
            message.data="這index值是:"+std::to_string(i);
            RCLCPP_INFO(node->get_logger(),"cpp publisher:%s",message.data.c_str());
            publisher->publish(message);
            rclcpp::spin_some(node);
            rate.sleep();
        }
    
    
    
        rclcpp::shutdown();
        return 0;
    }
    
    // subscribe
    #include <memory>
    
    #include "rclcpp/rclcpp.hpp"
    #include "std_msgs/msg/string.hpp"
    using std::placeholders::_1;
    
    
    int main(int argc, char * argv[]){
        rclcpp::init(argc, argv);
        auto node = rclcpp::Node::make_shared("cpp_demo_subscribe");
        rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscriber =
                node->create_subscription<std_msgs::msg::String>("my_topic",10,[node](std_msgs::msg::String::SharedPtr msg){
                    RCLCPP_INFO(node->get_logger(), "I heard: '%s'", msg->data.c_str());
                });
        rclcpp::spin(node);
        rclcpp::shutdown();
        return 0;
    }
               
    • 後面的功能開發不再送出,後面筆記會再次從 攝像頭 生成點雲圖開始,主要内容是ROS2+kinect2驅動開發。

🔗 前言

🔗 Robot ROS 作業系統清單

🔗 NO.1 Ros 安裝&介紹

🔗 NO.2 Ros 第一個程式(cpp & py)

🔗 NO.3 Ros Topic 通訊

🔗 NO.4 Ros 消息補充&小烏龜

🔗 NO.5 Ros Turtle &日志開發

🔗 NO.6 Ros Service 簡單通訊

🔗 NO.7 Ros Service 複雜通訊

🔗 NO.8 Ros PID算法案例

🔗 NO.9 PID原理&曲線計算原理

🔗 NO.10 Action 通訊 上

🔗 NO.11 Action 通訊 下

🔗 NO.12 Param & Launch & TF 案例

🔗 NO.13 ROS 2 Foxy安裝(Mac OS)

繼續閱讀