ROS2 (一) - 建立第一個專案 === 本系列教學文不會包含安裝ROS2這一步,相關內容可在官方網站找到: [ROS2安裝教學](https://index.ros.org/doc/ros2/Installation/#installationguide) 本系列文章,採用以下系統配置: * Ubuntu 18.04 x64 * ROS 2 Dashing Diademata * C++ (rclcpp) * Build: colcon 至於為什麼會有本系列文章,原因是因為學習ROS2,順便記錄以下以免忘記(金魚腦)。 --- ### 1-1 建立工作環境: [參考](https://index.ros.org/doc/ros2/Tutorials/Workspace/Creating-A-Workspace/) * 第一步,打開終端機,找到一個想要建立工作環境的目錄(如果有選擇性障礙,可以選擇桌面,如下) : ```Clike= cd ~/Desktop ``` * 第二步,在該目錄底下建立我們的工作目錄(catkin_workspace) 和 專案放置的目錄(src): ```Clike= mkdir -p catkin_workspace/src // 工作目錄(catkin_workspace)可自行取名 ``` * 第三步,進到專案放置目錄(catkin_workspace/src): 建立專案的格式 ```Clike= ros2 pkg create --build-type <build的類型> <專案名稱> --dependencies <依賴的專案> ``` 範例: ```Clike: ros2 pkg create --build-type ament_cmake hello_word --dependencies rclcpp std_msgs ``` 可以建立hello_word目錄,底下具有相關編譯檔,如下樹狀圖: . └── hello_word (專案目錄) ├── CMakeLists.txt (Cmake檔案) ├── include (標頭檔) │ └── hello_word ├── package.xml (專案資訊) └── src (原始碼存放目錄) 在繼續下去之前,讓我們來看看專案中兩個與建置相關的檔案: * CMakeLists.txt: ```Clike= # cmake最小需求版本 cmake_minimum_required(VERSION 3.5) # 專案名稱 project(hello_word) # 定義C語言編譯的標準為C99標準 # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # 定義C++語言編譯的標準為C++14標準 # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() # 如果是GNU或Clang編譯器,則將顯示編譯時期的所有警告 if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # 找到相關依賴包(之後如果要引入其他的依賴,需要將依賴加到這裡) # find dependencies find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) # uncomment the following section in order to fill in # further dependencies manually. # find_package(<dependency> REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # uncomment the line when a copyright and license is not present in all source files #set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # uncomment the line when this package is not in a git repo #set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() ament_package() ``` * package.xml: ```Clike= // xml檔案版本 <?xml version="1.0"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> // package的版本(這裡很重要,確認版本為2(含)以上) <package format="3"> // 專案名稱 <name>hello_word</name> // 專案版本 <version>0.0.0</version> // 專案描述 <description>TODO: Package description</description> <maintainer email="維護者的Email">維護者的名稱</maintainer> // License <license>TODO: License declaration</license> // 建置工具 <buildtool_depend>ament_cmake</buildtool_depend> // 依賴的專案 <depend>rclcpp</depend> <depend>std_msgs</depend> <test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_common</test_depend> <export> <build_type>ament_cmake</build_type> </export> </package> ``` * 第四步,在原始碼存放目錄(catkin_workspace/src/hello_word/src)下,建立名為hello_word.cpp的C++原始檔(CPP),內容如下: ```Clike= // 引入C++ 時間函式庫 #include <chrono> // 引入C++ 記憶體管理函式庫 #include <memory> // 引入ROS2 C++函式庫 #include "rclcpp/rclcpp.hpp" // 引入ROS2 std_msgs訊息函式庫 #include "std_msgs/msg/string.hpp" using namespace std::chrono_literals; /* This example creates a subclass of Node and uses std::bind() to register a * member function as a callback from the timer. */ // 建立一個新節點,名稱為hello_word,發佈Topic名稱為hello class MinimalPublisher : public rclcpp::Node { public: MinimalPublisher() : Node("hello_word"), count_(0) { // 建立發布節點名稱 publisher_ = this->create_publisher<std_msgs::msg::String>("hello", 10); // timer_callback每500ms執行一次 timer_ = this->create_wall_timer( 500ms, std::bind(&MinimalPublisher::timer_callback, this)); } private: void timer_callback() { auto message = std_msgs::msg::String(); message.data = "Hello, world! " + std::to_string(count_++); RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str()); publisher_->publish(message); } rclcpp::TimerBase::SharedPtr timer_; rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_; size_t count_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_shared<MinimalPublisher>()); rclcpp::shutdown(); return 0; } ``` * 第五步,將我們建置原始碼的資訊,加到CMakeLists.txt檔案裡: ```Clike= // 添加檔案編譯資訊<hello_word: 節點名稱,src/publisher_member_function.cpp: 原始檔位置> add_executable(hello_word src/publisher_member_function.cpp) // 添加編譯依賴 ament_target_dependencies(hello_word rclcpp std_msgs) // 將編譯完的檔案放置lib/${PROJECT_NAME}目錄下 install(TARGETS hello_word DESTINATION lib/${PROJECT_NAME}) ``` 加完後: ```Clike= cmake_minimum_required(VERSION 3.5) project(hello_word) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # uncomment the line when a copyright and license is not present in all source files #set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # uncomment the line when this package is not in a git repo #set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() add_executable(hello_word src/hello_word.cpp) ament_target_dependencies(hello_word rclcpp std_msgs) install(TARGETS hello_word DESTINATION lib/${PROJECT_NAME}) ament_package() ``` * 第六步,回到工作目錄的根目錄(catkin_workspace),編譯專案: ```Clike= colcon build ``` 編譯結果如圖:  編譯完成後,會看到工作目錄(catkin_workspace)底下多了,三個目錄: build log install 詳細目錄內容介紹,之後再其他章節在介紹 * 第七步,引入專案環境變數並執行節點: 引入環境變數 ```Clike source install/setup.bash ``` 執行節點: 格式 ```Clike= ros2 run <package_name> <executable_name> ``` 執行我們的節點: ```Clike= ros2 run hello_word hello_word ```  最後開一個新的終端機,執行: ```Clike= ros2 topic echo /hello ``` 就可以看到我們發布的內容了 
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up