1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VPN上でのROS(ROS2対応)

Last updated at Posted at 2024-08-18

下準備

この文書ではVPNとしてtailscaleを想定しています。
tailscaleをまだインストールしていない場合は、下のコマンドでインストールします。

$ curl -fsSL https://tailscale.com/install.sh | sh
$ sudo tailscale up

以降、sudoなしでtailscaleコマンドが使えるように、以下のコマンドも実行してください。

$ sudo tailscale set --operator=$USER

ROS通信の仕組みとROS over VPN

VPN上でROSを理解した上で使うために、まずはROS通信の仕組みを説明します。

talkerlistenerの2ノードからなる通信サンプルを立ち上げます。

$ roslaunch roscpp_tutorials talker_listener.launch

普段は意識しないで使っていますが、roslaunchを起動すると、rosmasterというプロセスがポート11311上で自動で立ち上がります。

$ lsof -sTCP:LISTEN -i:11311
COMMAND   PID   USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
rosmaster  99 yosuke    4u  IPv4 24080870      0t0  TCP *:11311 (LISTEN)

通信の中身を確認するために、xmlrpcコマンドをインストールします。

$ sudo apt install libxmlrpc-core-c3-dev

rosmasterが使用するxmlrpc APIは、以下に定義されています。

ここでは、rosmasterからノードtalkerの情報を取得してみましょう。

$ xmlrpc localhost:11311 lookupNode client1 talker
Result:

Array of 3 items:
  Index  0 Integer: 1
  Index  1 String: 'node api'
  Index  2 String: 'http://myhostname:45405/'

ホストmyhostnameのポート45405でノード用のサーバ(ROS slave)が立ち上がっているようです。

slaveが使うxmlrpcを呼び出すことで、ノードの詳細を見ることもできます。

$ xmlrpc myhostname:45405 getBusInfo client1
Result:

Array of 3 items:
  Index  0 Integer: 1
  Index  1 String: ''
  Index  2 Array of 2 items:
             Index  0 Array of 7 items:
                        Index  0 Integer: 0
                        Index  1 String: '/rosout'
                        Index  2 String: 'o'
                        Index  3 String: 'TCPROS'
                        Index  4 String: '/rosout'
                        Index  5 Boolean: TRUE
                        Index  6 String: 'TCPROS connection on port 38369 to [127.0.0.1:36152 on socket 12]'
             Index  1 Array of 7 items:
                        Index  0 Integer: 1
                        Index  1 String: '/listener'
                        Index  2 String: 'o'
                        Index  3 String: 'TCPROS'
                        Index  4 String: '/chatter'
                        Index  5 Boolean: TRUE
                        Index  6 String: 'TCPROS connection on port 38369 to [127.0.0.1:36166 on socket 10]'

各ROSノードは、rosmasterにホスト名とポート番号を問い合わせた後で、以降はノード間で直接TCP/IP接続することで効率的に通信します。各ポート番号を追いかけていくことで、ノード間通信の詳細も確認できます。

ここで問題は、myhostnameというホスト名です。このホスト名には127.0.1.1というIPアドレスが割り振られており、VPN内での通信に使うことはできません。

$ ping myhostname
PING myhostname (127.0.1.1): 56 data bytes
64 bytes from 127.0.1.1: icmp_seq=0 ttl=64 time=0.044 ms
64 bytes from 127.0.1.1: icmp_seq=1 ttl=64 time=0.047 ms
64 bytes from 127.0.1.1: icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from 127.0.1.1: icmp_seq=3 ttl=64 time=0.047 ms

VPN内での通信には、以下のコマンドで得られるtailscale内で割り振られたIPアドレスを使う必要があります。

$ tailscale ip -4
100.121.86.85

ここで、環境変数ROS_IPを使って、上記のIPアドレスを設定してみます。

$ ROS_IP=$(tailscale ip -4) roslaunch roscpp_tutorials talker_listener.launch

無事に、ROSが使用するIPアドレスをVPN通信可能なものに変更することができました。

$ xmlrpc localhost:11311 lookupNode client1 talker
Result:

Array of 3 items:
  Index  0 Integer: 1
  Index  1 String: 'node api'
  Index  2 String: 'http://100.121.86.85:36595/'

ROS1の場合

ROSノードを立ち上げる前に、環境変数ROS_IPROS_MASTER_URIを設定してください。

export ROS_MASTER_URI=http://$(tailscale ip -4 rosmasterを立ち上げたホスト名):11311
export ROS_IP=$(tailscale ip -4)

ROS2の場合

ROS2ではブロードキャスト通信を使って各ノードのdiscoveryを行いますが、多くのVPNではブロードキャスト通信が利用できません。
ここでは、ブロードキャスト通信を使う代わりに、ROS1のrosmasterに相当するfastdds discoveryを使用します。

$ sudo apt install fastdds-tools

fastdds discoveryを以下のオプションで起動します。

$ fastdds discovery -i 0 -l $(tailscale ip -4) -p 11811

毎回の起動が面倒な場合は、supervisordを使って自動起動させるのがおすすめです。

/etc/supervisor/conf.d/fastdds-discovery.conf
[program:fastdds-discovery]
command=bash -c "fastdds discovery -i 0 -l $(tailscale ip -4) -p 11811"
autostart=true
autorestart=true

ROS2ノードを起動させる各ホスト上に、以下の内容のスクリプトを作成します。

ここで、DS_IPにはdiscoveryサーバを立ち上げたホストのIPアドレスを設定してください。

~/fastdds_tailscale.sh
DS_IP=$(tailscale ip -4 discoveryサーバを立ち上げたホスト名)
DS_PORT=11811
HOST_IP=$(tailscale ip -4)

cat > /tmp/fastdds_tailscale_configuration.xml <<EOF
<?xml version="1.0" encoding="UTF-8" ?>
<dds>
    <profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
        <transport_descriptors>
            <transport_descriptor>
                <transport_id>TailscaleTransport</transport_id>
                <type>UDPv4</type>
            </transport_descriptor>
        </transport_descriptors>
        <participant profile_name="client_profile" is_default_profile="true">
            <rtps>
                <userTransports>
                    <transport_id>TailscaleTransport</transport_id>
                </userTransports>
                <useBuiltinTransports>true</useBuiltinTransports>
                <defaultUnicastLocatorList>
                    <locator>
                        <udpv4>
                            <address>${HOST_IP}</address>
                        </udpv4>
                    </locator>
                </defaultUnicastLocatorList>
                <builtin>
                    <discovery_config>
                        <discoveryProtocol>SUPER_CLIENT</discoveryProtocol>
                        <discoveryServersList>
                            <RemoteServer prefix="44.53.00.5f.45.50.52.4f.53.49.4d.41">
                                <metatrafficUnicastLocatorList>
                                    <locator>
                                        <udpv4>
                                            <address>${DS_IP}</address> 
                                            <port>${DS_PORT}</port>
                                        </udpv4>
                                    </locator>
                                </metatrafficUnicastLocatorList>
                            </RemoteServer>
                        </discoveryServersList>
                    </discovery_config>
                    <metatrafficUnicastLocatorList>
                        <locator>
                            <udpv4>
                                <address>${HOST_IP}</address>
                            </udpv4>
                        </locator>
                    </metatrafficUnicastLocatorList>
                </builtin>
            </rtps>
        </participant>
    </profiles>
</dds>
EOF

export RMW_IMPLEMENTATION=rmw_fastrtps_cpp
export FASTRTPS_DEFAULT_PROFILES_FILE=/tmp/fastdds_tailscale_configuration.xml
ros2 daemon stop
ros2 daemon start

ROSノードを立ち上げる前に、以下のコマンドでROS2環境をセットアップします。

$ source /opt/ros/jazzy/setup.bash
$ source ~/fastdds_tailscale.sh

余談

ROS2のDDS(FastDDS)は、XML形式の設定ファイルを使うことでプロトコルの詳細までカスタマイズできる。

VPNは本来UDP通信はあまり得意でなく、下のURLで記述された設定によってUDPからTCPに切り替えることもできるが、ROS2ならではのQoS制御を有効化するため、今回はUDPを使う設定にした。
https://fast-dds.docs.eprosima.com/en/latest/fastdds/transport/tcp/tcp.html

tailscaleでは、IPv6アドレスも利用できるのだが、VPN上でのIPv6はまだ実装が枯れていない部分も多いので、今回はIPv4のユニキャスト通信を使う設定にした。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?