ROS2 DashingのC++のソースコードをgdbでデバッグする方法

# はじめに
この記事はROS2 Advent Calendar 23日目の記事です。
本当は [Roboclaw](https://www.basicmicro.com/motor-controller) というモータードライバをROS2対応する記事を書く予定だったのですが、間に合いませんでした。こちらは別途目処が立ったらQiitaで紹介したいと思います。

さて、私は2017年に [ROSのC++のソースコードをgdbでデバッグする方法](https://qiita.com/Nasupl_r/items/7610139628fc59d47cb5) という記事をQiitaで執筆したのですが、この記事は今でも自分でよく見返すことがあります。
おそらくROS2での開発においても、gdbを使ってデバッグしようとした時にリファレンスが欲しくなることは間違いないでしょう。

ということで、ROS2を使ってC++のコードを書いた時にgdbでデバッグするときに、`ros2 run`や`ros2 launch`を使った方法を日本語で簡単に解説しているサイトがないのでここに書き留めます。

## 準備
gdbを使用するためには、デバッグ情報を付与する必要があります。
`colcon build`では以下のようにしてデバッグ情報付きでビルドをすることができます．

```
colcon build --cmake-args -DCMAKE_BUILD_TYPE=Debug
```
ROS1では`catkin_make`でも`catkin build`でも直接CMakeに引数を与えていましたが、ROS2では`--cmake-args`オプションをつける必要があるようです。

## ros2 runでgdbを利用する
もちろん、`ros2 run`にも`rosrun`と同じように実行時に引数を与えることで、実行時にプレフィックスを指定することが可能です。例えばgdbを利用する場合には、以下のようなコマンドを実行します。

```
ros2 run --prefix 'gdb --args' pkg_name node_name
```
この書式はROS1と全く変わりありませんね。

## ros2 launchでgdbを利用する
さて、`roslaunch`のROS2版である`ros2 launch`ですが、Dashing時点ではlaunchファイルをPythonでしか記述することができません。`roslaunch`では`<node>`タグに`launch-prefix`属性を設定することができましたが、Pythonでも同じことが可能でしょうか？

結論から書くと、執筆時点ではgdbからNodeを立ち上げることはできましたが、gdbのプロンプトを使うことができませんでした。つまり、ブレークポイントを張ったりプログラムを実行したりすることができませんでした。何か方法はあると思うのですが、まだ見つけられていないので、今後調べたいと思います。

私が取った方法を念の為記述しておきます。Pythonでlaunchファイルを記述して、Nodeを立ち上げる際に使う`launch_ros.actions.Node`クラスは`launch.actions.ExecuteProcess`を基底クラスに持っていて、このクラスはコンストラクタに引数`prefix`を持っています。そのため、launchファイルをPythonで記述して立ち上げるNodeをgdbでデバッグする場合には、以下のように記述してやれば良さそうです。

```py

from launch import LaunchDescription
import launch_ros.actions


def generate_launch_description():
    return LaunchDescription([
        launch_ros.actions.Node(
            package='pkg_name', node_executable='node_name',
            output='screen', prefix='gdb --args'])
```

しかし、このlaunchファイルを`ros2 launch`から起動すると、以下のようにgdbからNodeは立ち上がるものの、先ほども書いたとおりgdbのプロンプトが起動しません。

```sh
user@hostname:~/ros2_ws# ros2 launch pkg_name node_name.launch.py
[INFO] [launch]: All log files can be found below /root/.ros/log/yyyy-mm-dd-HH-MM-SS-MS-hostname-5625
[INFO] [launch]: Default logging verbosity is set to INFO
<launch.launch_description.LaunchDescription object at 0x7f9cbc962748>
[INFO] [node_name-1]: process started with pid [5635]
[node_name-1] GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
[node_name-1] Copyright (C) 2018 Free Software Foundation, Inc.
[node_name-1] License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
[node_name-1] This is free software: you are free to change and redistribute it.
[node_name-1] There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
[node_name-1] and "show warranty" for details.
[node_name-1] This GDB was configured as "x86_64-linux-gnu".
[node_name-1] Type "show configuration" for configuration details.
[node_name-1] For bug reporting instructions, please see:
[node_name-1] <http://www.gnu.org/software/gdb/bugs/>.
[node_name-1] Find the GDB manual and other documentation resources online at:
[node_name-1] <http://www.gnu.org/software/gdb/documentation/>.
[node_name-1] For help, type "help".
[node_name-1] Type "apropos word" to search for commands related to "word"...
[node_name-1] Reading symbols from /root/ros2_ws/install/pkg_name/lib/pkg_name/node_name...done.
```

例えば、`gdb --args`を`gdb -ex run --args`にしてやれば、プログラムをとりあえず実行することができます。しかし、プロンプトが表示されないためSegmentation Faultで落ちてもバックトレースを表示することはできません。

Dashingでは`ros2 launch`からPython以外で記述されたlaunchファイルを立ち上げることはできませんが、6日目の[@youtalkさんの記事](https://ros.youtalk.jp/2019/12/06/launch-xml.html)にもあったように、EloquentではXMLでlaunchファイルを記述できるようなので、そちらも追って試してみたいと思います。