こんにちは、ハチエックスのグエンです。
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 種類の時間フレームが存在します。
注意事項
API の互換性の違いに注意 ROS1 と ROS2 では、多くの API に互換性がないため、コードの詳細な修正が必要です。ドキュメントや公式リファレンスを活用してください。
依存ライブラリの確認 ROS2 に対応していない古いライブラリやパッケージがある場合、代替手段を検討する必要があります。
リアルタイム対応 ROS2 はリアルタイムシステムをサポートしていますが、リアルタイム要件を持つアプリケーションでは適切な QoS 設定やメモリ管理が必要です。
テストとデバッグの重要性 移植後は、各機能を徹底的にテストし、ROS2 環境で正しく動作することを確認します。特に、分散システムでの動作確認は欠かせません。
移植作業の計画 移植は時間がかかる作業です。段階的な移行を計画し、各ステップで成果物を確認しながら進めてください。
ROS1 から ROS2 への移植は、単なるバージョンアップではなく、新しいアーキテクチャに適応する重要なプロセスです。適切な計画と手順を踏むことで、ROS2 の利点を最大限に活用し、より高度なロボットシステムの構築が可能となります。
Comments