https://ar-ray.hatenablog.com/entry/2021/03/26/180000の実装時の話です。
ROS2の動画をパブリッシュする公式パッケージってどこなんですかーー
ROS2-Foxyにおいて動画を読み込んでImageメッセージのトピックを配信するパッケージって公式に出ていないんですかね??
— Ar-Ray (@Ray255Ar) 2021年3月25日
(見当たらなかったので自作してしまった)
ということで、ROS-Melodicの時によく使っていたmovie_publisherをROS2仕様にしました。自分で使うようなので、特にパラメータを渡すということはしていません。いずれ実装するとは思いますが…
プログラムはGitHubにupしています。
https://github.com/Ar-Ray-code/movie_publisher/blob/foxy/src/movie_publisher.cpp
実装
パブリッシュしている部分を抜粋して簡単な解説をします。
movie_pub(const std::string &name_space, rclcpp::NodeOptions options):rclcpp::Node(name_space, options) { // 1で解説 name = "/home/ubuntu/Desktop/video.mp4"; cv::Mat image; cv::VideoCapture camera(name.c_str()); if (!camera.isOpened()) { std::cout << name << " failed to open camera." << std::endl; exit(1); } // 2で解説 rclcpp::Rate looprate (camera.get(cv::CAP_PROP_FPS)); image_pub = this->create_publisher<sensor_msgs::msg::Image>("image_raw",1); // 3で解説 while(rclcpp::ok()) { camera >> image; header.stamp = system_clock.now(); header.frame_id = "/map"; msg = cv_bridge::CvImage(header, "bgr8", image).toImageMsg(); image_pub->publish(*msg); looprate.sleep(); } }
1. 動画ファイルのオープン
動画ファイルの名前を指定してVideoCaptureクラスのcameraを作成する。cameraが開けない場合はエラーとなります。
2.パブリッシャ用の宣言
rclcpp::Rateは、While処理中のROSが周期的にトピックを公開し続けるために必要です。レートは動画のフレームレートを参考に取得します。
create_publisherはトピックの公開を行うために必要です。
3.ループ処理
whileからは動画を1フレームごとに送信してきます。sensor_msgs::msg::Image型はheaderとimageで構成されています。header.stampには時間、header.frame_idには座標系、imageにはcv_bridgeで変換した後の画像データが格納されます。
データを全て格納したら、image_pub->publish(*msg)
で公開します。
全てのフレームを切り出したら、勝手にノードが終了します。
気になるところ・追加したい機能
frame_id
はどのように宣言すべきか:適当なフレーム名だとエラーになってしまったので/map
としたが、本来はどうあるべきなのか。Parameterで指定したほうがよさそう。ループ再生や逆再生・早送りを実装したい:Qtで実装すればよさそう。その場合は、フレームをカウントする必要がありそう。