top of page
Anchor 1

2025年1月9日: ROS1からROS2に移植するガイド

こんにちは、ハチエックスのグエンです。

ROS1 は 2025 年 5 月に公式サポートが終了します。そのため、ROS1 から ROS2 への移植がますます重要になっています。本記事では、ROS1 から ROS2 に移植するためのガイドを共有させていただきます。





目次


背景

ROS (Robot Operating System) は、ロボット制御やシミュレーションに広く利用されるオープンソースのフレームワークです。ROS1 は長年にわたり多くの開発者に利用されてきましたが、公式サポートが終了するため、より機能性と保守性が高い ROS2 への移行が求められています。

ROS2 は、リアルタイム対応、セキュリティ強化、分散システムサポートなど、ROS1 に比べて多くの改善が施されています。そのため、移植を行うことで、これらの利点を活用しながら、将来の開発や運用に備えることができます。本記事では、ROS1 から ROS2 への移植をスムーズに進めるためのガイドを提供します。


移植する共通内容

1. パッケージ構造の変更

ROS2 では、ビルドシステムが catkin から colcon に変更されています。これに伴い、以下の変更を行う必要があります。

  • package.xml の修正

    • ROS2 対応の依存関係を指定します。

    • format を ROS2 用の値(3 または 4)に設定します。

  • CMakeLists.txt の修正

    • ROS2 向けのビルド指示を記述します。

    • ament_cmake を使用したビルドコマンドに置き換えます。


2. ノード実装の更新

ROS1 のノードから ROS2 のノードへ移行する際、以下のポイントに注意します。

  • 初期化とスピン関数の変更

    • ros::init と ros::NodeHandle を rclcpp::init と rclcpp::Node に置き換えます。

  • トピック通信の修正

    • パブリッシャーとサブスクライバーの生成方法が変更されています。

    • QoS 設定を必須で記述する必要があります。

  • サービスとアクションの更新

    • サービスやアクションの実装方法が変更されています。

    • rclcpp::Service と rclcpp::ActionServer を利用します。


3. Launch ファイルの書き換え

ROS1 では XML 形式で記述されていた Launch ファイルが、ROS2 では Python を使用して記述されます。

  • ノードの起動記述

    • launch_ros.actions.Node を利用してノードを定義します。

  • 引数と環境変数の設定

    • LaunchConfiguration や EnvironmentVariable を活用します。


4. メッセージとサービスの修正

ROS1 で定義されていたカスタムメッセージやサービスは、ROS2 に移行する際に再ビルドが必要です。

  • .msg や .srv ファイルを再確認し、ROS2 の形式に適合させます。

  • ビルド後のインタフェースをテストし、正しく動作することを確認します。


5. ノードインスタンスの移植

  • インクルードの変更

  • コンテキスト初期化とインスタンス定義の変更

    • ROS1: std::shared_ptr<ros::NodeHandle> nh_;

    • ROS2: rclcpp::Node::SharedPtr nh_;

  • インスタンス生成の変更

    • ROS1: if(!ros::isInitialized()) { ros::init(argc, argv, "node_name", ros::init_options::NoSigintHandler); } nh_ = std::make_shared<ros::NodeHandle>();

    • ROS2: if (!rclcpp::ok()) { rclcpp::init(argc, argv); } rclcpp::NodeOptions node_options; nh_ = rclcpp::Node::make_shared("node_name", node_options);


6. パブリッシャーの移植

  • インスタンス定義の変更

    • ROS1: ros::Publisher pub_;

    • ROS2: rclcpp::Publisher<std_msgs::msg::Float64>::SharedPtr pub_;

  • インスタンス生成の変更

    • ROS1: pub_ = nh_->advertise<std_msgs::Float64>(topic_name_, 1);

    • ROS2: pub_ = nh_->create_publisher<std_msgs::msg::Float64>(topic_name, 1);

  • publish() 関数の変更

    • ROS1: pub_.publish(msg);

    • ROS2: pub_->publish(msg);


7. サブスクライバーの移植

  • インスタンス定義の変更

    • ROS1: ros::Subscriber sub_;

    • ROS2: rclcpp::Subscription<std_msgs::msg::Float64>::SharedPtr sub_;

  • インスタンス生成の変更

    • ROS1: sub_ = nh_->subscribe<std_msgs::Float64>(topic_name, 1, &MyClass::callback, this);

    • ROS2: sub_ = nh_->create_subscription<std_msgs::msg::Float64>( topic_name, 1, std::bind(&MyClass::callback, this, std::placeholders::_1));


8. 時間処理の移植

  • fromSec() 関数の廃止

    • ROS1: msg.clock.fromSec(d->time);

    • ROS2: builtin_interfaces::msg::Time time; time.sec = static_cast<int32_t>(d->time); time.nanosec = static_cast<uint32_t>((d->time - time.sec) * 1e9); msg.clock = time;

  • toSec() 関数の廃止

    • ROS1: end_time_ = d->time + msg_->duration.toSec();

    • ROS2: end_time_ = d->time + msg_->duration.sec + msg_->duration.nanosec * 1e-9;

  • 複数の時間フレームの考慮

    • ROS1: context_->getFrameManager()->getTransform(first_frame_id, ros::Time(0), frame_pos, frame_quat);

    • ROS2: context_->getFrameManager()->getTransform(first_frame_id, frame_pos, frame_quat); ※ ROS2 では、RCL_SYSTEM_TIME, RCL_ROS_TIME, RCL_STEADY_TIME の 3 種類の時間フレームが存在します。


注意事項

  1. API の互換性の違いに注意 ROS1 と ROS2 では、多くの API に互換性がないため、コードの詳細な修正が必要です。ドキュメントや公式リファレンスを活用してください。

  2. 依存ライブラリの確認 ROS2 に対応していない古いライブラリやパッケージがある場合、代替手段を検討する必要があります。

  3. リアルタイム対応 ROS2 はリアルタイムシステムをサポートしていますが、リアルタイム要件を持つアプリケーションでは適切な QoS 設定やメモリ管理が必要です。

  4. テストとデバッグの重要性 移植後は、各機能を徹底的にテストし、ROS2 環境で正しく動作することを確認します。特に、分散システムでの動作確認は欠かせません。

  5. 移植作業の計画 移植は時間がかかる作業です。段階的な移行を計画し、各ステップで成果物を確認しながら進めてください。


ROS1 から ROS2 への移植は、単なるバージョンアップではなく、新しいアーキテクチャに適応する重要なプロセスです。適切な計画と手順を踏むことで、ROS2 の利点を最大限に活用し、より高度なロボットシステムの構築が可能となります。

Comments


bottom of page