結論
メッセージ内容を補完する前にダブルクォーテーション(")を入力して補完しよう!
検証環境
- OS: Ubuntu 20.04 LTS
- ROS 2バージョン: Humble
背景
作成したノードの動作確認をする際に、"ros2 topic pub"を使うと楽なのですが、タブ補完を使ってメッセージ内容を補完すると表示がおかしい。
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist linear:\
\ \ x:\ 0.0\
\ \ y:\ 0.0\
\ \ z:\ 0.0\
angular:\
\ \ x:\ 0.0\
\ \ y:\ 0.0\
\ \ z:\ 0.0\
さらに、実行してみると以下のようなよくわからないエラーが発生する。
Traceback (most recent call last):
File "/root/ros2_humble/install/ros2cli/bin/ros2", line 11, in <module>
load_entry_point('ros2cli', 'console_scripts', 'ros2')()
File "/root/ros2_humble/build/ros2cli/ros2cli/cli.py", line 89, in main
rc = extension.main(parser=parser, args=args)
File "/root/ros2_humble/build/ros2topic/ros2topic/command/topic.py", line 41, in main
return extension.main(args=args)
File "/root/ros2_humble/build/ros2topic/ros2topic/verb/pub.py", line 222, in main
return main(args)
File "/root/ros2_humble/build/ros2topic/ros2topic/verb/pub.py", line 240, in main
return publisher(
File "/root/ros2_humble/build/ros2topic/ros2topic/verb/pub.py", line 271, in publisher
values_dictionary = yaml.safe_load(values)
File "/usr/lib/python3/dist-packages/yaml/__init__.py", line 162, in safe_load
return load(stream, SafeLoader)
File "/usr/lib/python3/dist-packages/yaml/__init__.py", line 114, in load
return loader.get_single_data()
File "/usr/lib/python3/dist-packages/yaml/constructor.py", line 49, in get_single_data
node = self.get_single_node()
File "/usr/lib/python3/dist-packages/yaml/composer.py", line 36, in get_single_node
document = self.compose_document()
File "/usr/lib/python3/dist-packages/yaml/composer.py", line 55, in compose_document
node = self.compose_node(None, None)
File "/usr/lib/python3/dist-packages/yaml/composer.py", line 84, in compose_node
node = self.compose_mapping_node(anchor)
File "/usr/lib/python3/dist-packages/yaml/composer.py", line 127, in compose_mapping_node
while not self.check_event(MappingEndEvent):
File "/usr/lib/python3/dist-packages/yaml/parser.py", line 98, in check_event
self.current_event = self.state()
File "/usr/lib/python3/dist-packages/yaml/parser.py", line 428, in parse_block_mapping_key
if self.check_token(KeyToken):
File "/usr/lib/python3/dist-packages/yaml/scanner.py", line 116, in check_token
self.fetch_more_tokens()
File "/usr/lib/python3/dist-packages/yaml/scanner.py", line 223, in fetch_more_tokens
return self.fetch_value()
File "/usr/lib/python3/dist-packages/yaml/scanner.py", line 577, in fetch_value
raise ScannerError(None, None,
yaml.scanner.ScannerError: mapping values are not allowed here
in "<unicode string>", line 1, column 11:
linear: x: 0.0 y: 0.0 z: 0.0angular: x ...
上記のような経験をされた方は私だけではないと思います。結果として、メッセージの中身を手打ちする必要に迫られて"ros2 topic pub"を使わなくなる人もいるんじゃないでしょうか。この記事を作成するまで私もそうでした。
CrystalやDashingの頃ならまだしもHumbleまでバージョンが進んでいたら、何かしら解決策があるはずだということで調査してみました。
解決策
"ros2 topic pub"は、ros2cliパッケージに格納されています。そこで、ros2cliのGitHubページのissueを確認すると、以下のように未だに問題として取り上げられていることがわかります(2023/07/20時点)。
https://github.com/ros2/ros2cli/issues/793
しかし、このissueの元を辿ると、とりあえずこれで動くという解決策がありました。
https://github.com/ros2/ros2cli/issues/563#issuecomment-782135494
この投稿曰く、メッセージ内容を補完する前にダブルクォーテーションを入力すると良いらしいです。
実際に入力した結果は以下のとおりです。
ros2 topic pub /float geometry_msgs/msg/Twist "l
上記の時点でタブキーを押下して補完
ros2 topic pub /float geometry_msgs/msg/Twist "linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0"
綺麗な形のメッセージ内容を見ることが出来ました。
実行結果も以下のように問題ありませんでした。
publisher: beginning loop
publishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0))
publishing #2: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0))
publishing #3: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0))
最後に
上記の解決策は初心者にとって直感的ではなく分かりにくいので、ソースコードを眺めて問題になりそうな箇所に手を加えたりして試行してみましたが、根本的な解決策は見つかりませんでした。我こそはというエンジニアの方は、ぜひ根本的な解決を模索していただけると助かります。