iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
自我挑戰組

一個營建系學生的韌體之路-自走車篇系列 第 15

【AMR_Day15】 關於Launch的歪路

  • 分享至 

  • xImage
  •  

我的學習經驗

眼睛我會了、大腦我會了、手手:等一下!!!!
眼睛我會了、大腦我會了、手手:等一下!!!!

大家是不是常常有上面情況發生呢?XD
我自己的話是感觸非常深阿~
學習ROS2的經驗也是如此,其中印象深刻的有包括了launch。在學習階段的時候用的都是別人寫好的packages,基本上不會在啟動的時候發生什麼問題,不管是節點的啟動或是參數的設定都有預設範本了,因為沒有遇到錯誤就不會深入的去了解程式碼的意義。
除此之外,因為ROS1只能使用XML格式編寫launch文件,又因網路上的資源大多都還是ROS1,導致有時候即使看懂了ROS1的launch文件,要改寫成ROS2版本就會卡關。又或著是要自己從空文件寫出一個可以成功被啟動的launch文件,卻無從下手,一方面也是因為自己還沒真的熟用這些工具,一方面自己的學習方式很雜亂。
那我今天會嘗試著把我從無到有的launch文件寫法記錄下來,方便我未來省去掉重新找資料的時間。

新增一個資料夾

在DAY10的最後有提到怎麼新建一個package
https://ithelp.ithome.com.tw/upload/images/20230930/20140433e32RiscvtH.png
我的sim_ws工作空間中/src的結構,包含了新建的package和它底的include與src

root@Laptop:/sim_ws# tree -d ./src/
./src/
└── it_package
    ├── include #放.h的地方
    │   └── it_package
    └── src #放.cpp的地方

為了要放launch文件,我們就需要一個launch資料夾

root@Laptop:/sim_ws# tree -d ./src/
./src/
└── it_package
    ├── include #放.h的地方
    │   └── it_package
    ├── launch #放launch的地方,可以是.py、.xml或.yaml
    └── src #放.cpp的地方

修改package.xml、CMakeLists.txt

(murmur...昨天之所以猶豫要不要先提寫訂閱/發布者就是和這裡有關。)
這兩個文件是在處理package的基本資訊,告訴電腦編譯方式、需要依賴的函式庫、函式庫連結之類的,我也是會基本而已...總之,要讓launch文件能在ros2 launch package` [tab] 時成功被提示,需要這些設定。

# 在package.xml添加
    <exec_depend>ros2launch</exec_depend>
# 在CMakeLists.txt添加
    install(DIRECTORY
      launch
      DESTINATION share/${PROJECT_NAME}
    )

開始寫launch文件

個人的建議是一開始先固定學習一個格式就好,如果從ROS1跳過來的話就寫xml,反之直接學ROS2的話就先專心把python格式看懂,那我目前大多數時間都是用ROS2,所以就以python為主。
以下是我自己某個package中的python格式launch.py,可以用來開啟gazebo、rviz2和我自己寫的節點。
跟昨天官方的差別是,我後來習慣把LaunchDescription()當作一個變數ld,先使用ld.add_action(pcl_node)return ld,好處是我比較好清楚看懂現在哪些節點要被使用。

import os

from ament_index_python import get_package_share_directory

from launch import LaunchDescription
from launch.actions import ExecuteProcess
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.actions import GroupAction
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch.substitutions import TextSubstitution
from launch_ros.actions import Node
from launch_ros.actions import PushRosNamespace

def generate_launch_description():
    ld = LaunchDescription()

    start_gazebo_cmd = ExecuteProcess(
        cmd=['gazebo','/root/.gazebo/worlds/car_with_tunnel'],
        output="screen"
    )

    start_rviz_cmd = Node(
        package="rviz2",
        executable="rviz2",
        name="rviz2",
        output="screen",
        # arguments=[-d,""]
    )
    
    # 鍵盤控制node 但後來發現不適合放進launch文件
    teleop_node =Node(
        package="teleop_twist_keyboard",
        executable="teleop_twist_keyboard",
        name="teleop_node",
        remappings=[
            ("cmd_vel", "demo/cmd_demo")]
    )
    
    # 我自己寫了pcl節點 但要等gazebo節點跑完才會成功被執行
    # 故先註解不啟動
    pcl_node = Node(
        package="pcl_process",
        executable="pc_boundary",
        name="pc_boundary",
        output="screen",
        parameters=[
                {'KS': 50},
                {'RS':0.1},
                {'AT':1.2}
                ]
    )

    ld.add_action(start_gazebo_cmd)
    ld.add_action(start_rviz_cmd)
    # ld.add_action(pcl_node)

    return ld

我踩過得那些坑

上面pcl_nodestart_rviz_cmd分別有用到parameters、arguments的部份,我當初也花了蠻多時間去弄懂兩者的差異,明天就來好好介紹一下parameters,並且跟launch中的arguments好好比較一下。


上一篇
【AMR_Day14】ROS2 基本功-Launch
下一篇
【AMR_Day16】ROS2 基本功-Parameter
系列文
一個營建系學生的韌體之路-自走車篇30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言