tshell_blog

ソフトウェアと車輪がついた乗り物のはなし

Docker環境でROS2プログラム開発

前回作成したROS2開発環境のDockerイメージを使ってROS2プログラムを作っていきます。

tshell.hatenablog.com

以下のような流れです。

  1. パッケージの作成
  2. ソースの記述
  3. CMakeLists.txtの編集
  4. package.xmlの編集
  5. ビルド
  6. 動作確認

コンテナの起動

以下のようにして/etc/group/etc/passwdをマウントし,Dockerコンテナのシェルを一般ユーザーで起動するようにするとソースの記述やCMakeLists.txtを編集するときにsudoを使う手間がなくなります。

以降の手順ではros2 pkg createによってディレクトリやファイルが自動生成されるので,空のディレクトリ内で以下を実行します。

$ docker run --rm -it -v `pwd`:/home -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -u $(id -u $USER):$(id -g $USER) ros2:dashing 

コンテナ起動後に以下を実行します。

$ source /opt/ros2/dashing/setup.bash

パッケージの作成

パッケージはsrcディレクトリ内に作成する必要があります。まずはsrcディレクトリを作成し,その中でros2 pkg createコマンドを実行します。

ビルド時にはここで作成したsrcディレクトリの一つ上(ここでは/home)でcolcon buildコマンドを実行する必要があります。

$ cd /home
$ mkdir src
$ cd src
$ ros2 pkg create --build-type ament_cmake sample --dependencies rclcpp

sample/src内にsample.cppを作成

上のようなros2 pkg createコマンドを実行するとsampleディレクトリが作成され,その中にsrcディレクトリが作成されます。
以下のようなsample.cppをsrcディレクトリ内に作成します。

#include <memory>
#include <chrono>
#include "rclcpp/rclcpp.hpp"

using namespace std::chrono_literals;

class SampleClass : public rclcpp::Node
{
    public:
    SampleClass() : Node("sample_node")
    {
        timer_ = create_wall_timer(1s, std::bind(&SampleClass::timer_callback, this));
    }
    private:
    void timer_callback()
    {
        RCLCPP_INFO(this->get_logger(), "Hello World");
    }
    rclcpp::TimerBase::SharedPtr timer_;
};

int main(int argc, char *argv[])
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<SampleClass>());
    rclcpp::shutdown();
    return 0;
}

CMakeLists.txtの編集

CMakeLists.txtを以下のように編集します。
Dockerコンテナを立ち上げたディレクトリ内にあるファイルを適当なエディタで編集すればDockerコンテナ内にも反映されます(当たり前ですが)

cmake_minimum_required(VERSION 3.5)
project(sample)

# 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)

add_executable(sample_package src/sample.cpp)
ament_target_dependencies(sample_package rclcpp)
install(TARGETS
sample_package
DESTINATION lib/${PROJECT_NAME}
)

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の編集

package.xmlを以下のように編集します。

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>sample</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="root@todo.todo">root</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <build_depend>rclcpp</build_depend>
  <exec_depend>rclcpp</exec_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

ビルド

ros2 pkg createコマンドを実行したディレクトリの一つ上(ここでは/home)に移動し,colcon buildを実行します。

$ cd /home
$ colcon build

動作確認

ビルドに成功したら以下のコマンドを実行し,動作確認を行います。

$ source install/setup.bash
$ ros2 run sample sample_package

ここでsampleros2 pkg createコマンド実行時に与えたパッケージ名,sample_packageはCMakeLists.txtで指定したexecutable名です。
これらを変えれば好きな名前にできます。

上記のコマンドを実行すると以下のように1秒毎に文字列が表示されます。

[INFO] [sample_node]: Hello World
[INFO] [sample_node]: Hello World
[INFO] [sample_node]: Hello World
[INFO] [sample_node]: Hello World

開発環境コンテナでROS2プログラムを作成することができました。
VSCode拡張機能か何かを使ってラクしたいですね〜