Uruchamianie ROS na wielu maszynach

ROS pozwala na łączenie programów – które nazywane są Nodami, w wielu językach i, co ważne, na wielu komputerach. Jednak samo ustawienie sieci ROS na wielu komputerach, jest trochę podchwytliwe, stąd w tym artykule chcę wam przybliżyć moją konfigurację, ew mój sposób na znalezienie błędów w konfiguracji.

Na każdym komputerze musi być oczywiście zainstalowany, chociaż w podstawowym zakresie ROS, wszędzie w tej samej wersji (np. ROS Indigo). Dość ciężko łączy się ROS’y w różnych wersjach.

Artykuł piszę w takiej kolejności, jak ustawiałbym to na maszynach. Sporo zależy od możliwości routera czy wsześniejszej konfiguracji komputerów. Komputery muszą być w tej samej sieci i muszą się widzieć.

Podstawowe testy

Załóżmy, że komputer z roscore nazwaliśmy (hostname) duzy_ros a komputer-klienta maly_ros. Rzeczywistą nazwę możemy sprawdzić, pisząc w konsoli polecenie hostname. Zazwyczaj nazwa hosta pojawia się też po znaku @ w konsoli.

igor@duzy_ros:~$ hostname
duzy_ros

Dobrze jest też na tym etapie wiedzieć, jaki komputer ma adres IP. Ogólnie radzę na routerze ustawić tzw static DHCP (rezerwowanie adresów DHCP), to znaczy, aby danemu adresowi MAC ustalał zawsze ten sam adres IP. Można też ustawić stałe adresy samym komputerom, jednak jest to stosunkowo uciążliwe jeśli tym komputerem jest np. nasz laptop, który raz służy do kontrolowania robota, a innym razem jest komputerem domowym. Sprawdzić IP możemy za pomocą komendy ifconfig.

igor@maly_ros:~$ ifconfig
eth0      Link encap:Ethernet  HWaddr 2c:41:38:09:f9:d4  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:452957 errors:0 dropped:0 overruns:0 frame:0
          TX packets:227647 errors:0 dropped:0 overruns:0 carrier:2
          collisions:0 txqueuelen:1000 
          RX bytes:617762669 (617.7 MB)  TX bytes:20174253 (20.1 MB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:150077 errors:0 dropped:0 overruns:0 frame:0
          TX packets:150077 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:17070833 (17.0 MB)  TX bytes:17070833 (17.0 MB)

wlan0     Link encap:Ethernet  HWaddr bc:77:37:dc:d2:1e  
          inet addr:192.168.1.103  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::be77:37ff:fedc:d21e/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3432045 errors:0 dropped:1 overruns:0 frame:0
          TX packets:2071139 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:3574669623 (3.5 GB)  TX bytes:440387517 (440.3 MB)

W zależności od tego, czy komputer jest wpięty poprzez kabel Ethernet czy WiFi, interesuje nas adres IP (inet addr) opisany w części wlan albo eth. W moim przypadku, adres karty WiFi komputera maly_ros to 192.168.1.103

Kolejnym testem jest to, czy komputery się widzą . Radzę sprawdzić na obu komputerach, poleceniem ping. Odpowiedź będzie miała podobny charakter. Powinny być czasy w milisekundach (albo częściach milisekudny). Router powinien znaleźć adres ip po nazwie hosta – ale tak będzie się działo tylko przy nowych routerach.

Na serwerze

igor@duzy_ros:~$ ping maly_ros
PING maly_ros (192.168.3.103) 56(84) bytes of data.
64 bytes from maly_ros: icmp_seq=1 ttl=61 time=3.96 ms
64 bytes from maly_ros: icmp_seq=2 ttl=61 time=2.61 ms

Na kliencie

igor@maly_ros:~$ ping duzy_ros
PING duzy_ros (192.168.3.101) 56(84) bytes of data.
64 bytes from duzy_ros: icmp_seq=1 ttl=61 time=3.11 ms
64 bytes from duzy_ros: icmp_seq=2 ttl=61 time=2.01 ms

Jeśli to się nie udało to musimy nazwy hostów przypisać na sztywno ( jest to opisane w dalszej części tego artykułu), ale próbujemy czy chociaż widzą się po adresach ip. W poleceniu ping, piszemy wobec tego adres ip zamiast nazwy hosta.

igor@duzy_ros:~$ ping 192.168.3.103
PING 192.168.3.103 (192.168.3.103) 56(84) bytes of data.
64 bytes from 192.168.3.103: icmp_seq=1 ttl=61 time=3.96ms
64 bytes from 192.168.3.103: icmp_seq=2 ttl=61 time=2.61 ms

To musi zakończyć się sukcesem zanim pójdziemy dalej. Jeśli komputery się nie pingują, chociaż po adresie IP, to problem tkwi w samej konfiguracji sieci. Dla przykładu, komputery podłączone są do innych sieci WiFi (zdaża się, szczególnie w przypadku uczelni czy firm gdzie tych sieci jest sporo).

Ostatnią rzeczą wartą przetestowania na starcie, jest sprawdzenie czy aby na komputerze z roscore nie ma uruchomionego firewalla. Natura ROS’a ogólnie wymusza, aby firewalla nie było ani na serwerze ani na komputerach klienckich, firewall powienien być ustawiony tylko na routerze. Najprostrzym testem jest wejść przeglądarką na stronę o adresie ip (ew. hostname) roscore i porcie 11311 czyli w przeglądarce napiszę albo 192.168.1.101:11311 albo duzy_ros:11311

wchodzenie na stronę

Interesuje nas aby strona wyglądała jak na screenshocie, to znaczy aby wyświetlił się błąd 501, a nie np. błąd 404, że strona nie istnieje. Jeśli strona nie istnieje, a na serwerze jest uruchomiony roscore (upewnij się ;) ), to znaczy, że komputer serwera blokuje port 11311 (i pewnie inne). Trzeba wyłączyć firewall np. pisząc w konsoli.

igor@duzy_ros:~$ sudo ufw disable
[sudo] password for igor: 
Firewall stopped and disabled on system startup

Sam stan firewalla można sprawdzić też w samym ubuntu uruchamiająć graficzny program, który wygląda tak:

firewall

Przejdźmy do samych ustawień

Ustawienia klienta

Na komputerze klienta (maly_ros) w pliku ~/.bashrc dodajemy linijki (dopisujemy na końcu). Polecam otworzyć ten plik i zapoznać się z jego strukturą. Plik .bashrc jest to plik programu bash, który uruchamia się za każdym razem gdy otworzymy terminal.

export ROS_MASTER_URI=http://duzy_ros:11311
export ROS_HOSTNAME=maly_ros

Jeśli komputery nie widziały się po nazwach hosta, możemy zamiast tego napisać

export ROS_MASTER_URI=http://192.168.1.101:11311
export ROS_ID=192.168.1.103

Ustawienia serwera

W pliku bash ustalamy podobnie:

export ROS_MASTER_URI=http://duzy_ros:11311
export ROS_HOSTNAME=duzy_ros

Następnie, na obu komputerach, w konsoli sourcujemy to znaczy ładujemy do konsoli zawartość plików poprzez polecenie source.

source ~/.bashrc

Finalne testy

Możemy sprawdzić, czy zmiany zostały wprowadzone, sprawdzająć zawartość zmienionych zmiennych

igor@maly_ros:~$ echo $ROS_MASTER_URI
http://duzy_ros:11311

Wreszcie, jeśli roscore na serwerze (duzy_ros) jest uruchomiamy na maly_ros polecenie rostopic list

igor@maly_ros:~$ rostopic list
/rosout
/rosout_agg

jeśli pojawia się ERROR: Unable to communicate with master!, coś mamy jeszcze źle skonfigurowane, polecam uruchomić testy z początku tego dokumentu.

Ustawienia hosts

Jeśli komputery się nie widzą po nazwach hostów, można zastąpić router w poszukiwaniu hosts, na obu komputerach przypisując wzajemnie swoje adresy w pliku /etc/hosts Uwaga! W takiej konfiguracji adresy IP poszczególnych komputerów nie mogą się zmieniać, co musimy ustalić albo na routerze albo ustalając stałe adresy ip na komputerach. Nie ma sensu przeprowadzać poniższej

Na obu komputerach, będziemy edytować plik /etc/hosts. Można to zrobić dowolnym programem do edycji plików tekstowych, np gedit czy vim

igor@maly_ros:~$ sudo gedit /etc/hosts.

W zawartości dopisujemy linijkę (na końcu). Pomiędzy adresem ip a nazwą hosta jest znak tabulator.

192.168.1.101	duzy_ros

analogicznie na serwerze

192.168.1.103	maly_ros

po zapisaniu plików, można przetestować konfigurację, pingująć komputery po nazwach, tak jak było to opisane na początku.