はじめに
タイトルの通り、rosbagを保存時に各トピックのHeaderに保存されるタイムスタンプとは別に取得時間に基づく時刻情報がトピック毎に付与されるわけですがあるターミナルでrosbagをrosbag play(ros2 bag play)で再生、もう一つのターミナルでrosbag record(ros2 bag record)で保存した際にrosbagには元のROSBAGのクロックではなく現在のrostimeがrosbagに付与されてしまうので保存されたデータを使って新しい処理を挟む場合、ros::time::now()等で時刻を取ると取得できるタイムスタンプとヘッダーに付与されたタイムスタンプが異なるという問題が発生してしまいました。
今回元のrosbagファイルの特定のトピックをノードで処理、再度rosbagで保存をした際に元のクロック情報を保持する必要になったため元のrosbagのクロック情報を保持しつつ処理&データの保存にはどうしたらいいのだろうかということでちょっと色々と試した結果をここにまとめます。
ROS1の場合
ROS1の場合、以下のコマンドにてまずはroscoreから出力されるクロックを停止した上でrosbag play時に--clockオプションを有効にすることでrosbag record時の元のrosbagで保持している時刻情報のまま処理をすることができます。
(rosbag recordで保持すると元のrosbagの時刻情報と新たに保存したrosbagの時刻情報が合致しているのが確認できると思います)
rosparam set /use_sim_time true
rosbag play ${PATH_TO_ROSBAG} --clock
ROS2の場合
ROS1の時と同様にros2 param setにて/use_sim_timeをセットしようとしたところros2の場合、ROS1で言うとroscoreに当たるものがないので先にros2 bag record $${TOPIC_NAME}を先に立ち上げてROS1と同様にtime_simを有効にしてros2 bag play ${PATH_TO_ROSBAG} --clockでクロック情報を発信させつつros2 bag recordでトピックを保存したところROS1の時とは異なり、生成したrosbagには現在のクロックが記録されてしまっていました。
(もし元のrosbagクロックを保持し続ける方法ご存じの方いらっしゃったら教えていただきたいです・・・)
ros2 param set /rosbag2_recorder use_time_sim true
応急処置的な対応
正しくros2系のコマンドを使えばROS2でもできそうな気がしますがぱっと見分からんということで元のrosbagからクロック情報を取得して処理済みデータを保存したrosbagファイルのクロック情報を書き換えるといった荒業な方法にて対応してみました。需要あるかどうか分からないですが一応Githubにあげておきます。
引数に以下のパラメータを渡してあげる事でトピックのヘッダーに含まれるタイムスタンプを元にrosbagファイルの処理前のトピックからクロック情報を取得し、処理済みのrosbagファイルのタイムスタンプを上書きすることで同様の結果が得られ(る気が)します。
・元のrosbagファイルへのパス
・処理済みデータを保存したrosbagファイルへのパス
・処理結果のrosbag保存先のパス
・対象のトピック名