note : Sorry, this document is written in Japanese.
ROS Japan UG #36 LT@Google Meetにて"micro-ROS Demo on STM32 nucleo-f767zi"というタイトルで発表した内容を補完し,nucleo-f767ziを所持している方が追試できるようにするために,パッチの公開とチュートリアルを示すためのリポジトリである.
環境としてUbuntu18.04(amd64)を用いる.なお,クロスコンパイルのためのツールチェーンやフラッシュメモリへの書き込みツール,およびMicro XRCE-DDS Agentのインストールは済んでいるものとし,本チュートリアルでは説明しない.
パッチの中身についてはほぼmicro-ROSのソースファイル由来のものであるので,基本的なライセンス条項はそれを継承するものとする.
パッチの中身のコードは下記リポジトリにほぼ由来する.
NuttXをmicro-ROSプロジェクトがforkしたもの
nuttx_appsをmicro-ROSプロジェクトがforkしてexampleなどを追加したもの
Nuttxの範囲については前者に設定されたライセンスが後者を包含していると考えられるため,これを本リポジトリのライセンスとして設定した.
nucleo boardは剥き出しだと裏面のピンがチクチクするので,スマホのバンパーケースみたいなものをFusion360でモデリングして,3Dプリントサービスで造形してみた.塗装していないので色ムラがあるが,強度や質感は良い感じである.これだけで随分取り回しやすくなった.
-
ターミナルを起動する
-
ROS2の環境変数を読み込む.パスは手元の環境に従って適宜読み替えること.
$ cd ~
# ROS2 Dashing Diademataを公式のチュートリアルに従ってソースからビルドしている場合の例
$ source ros2_dashing/install/setup.bash
# aptからバイナリインストールしている場合の例
$ source /opt/ros/dashing/setup.bash
- 作業用ディレクトリの作成
$ cd ~
$ mkdir uros_ws
このuros_wsを作業用ディレクトリとしても問題ないが,ある命名規則に従ってサブディレクトリを作成し,そこを作業用ディレクトリとすることを推奨する.
$ cd uros_ws
$ mkdir nuttx__nucleo-144__f767-netnsh
$ cd nuttx__nucleo-144__f767-netnsh
本チュートリアルにおいては,このnuttx__nucleo-144__f767-netnshを作業ディレクトリとする.
なぜこのようなサブディレクトリを作成するかと言うと,あるボードでmicro-ROSを動作させることに成功すると,他のボードや他のRTOSでも動作させたくなってくるからである(なるよね?).
チェックアウトしたソースを使いまわしながら他のボードの設定ファイルを上書きしたりすると,訳がわからなくなるので推奨できない(やろうと思う人もいないと思うが).
uros_wsをmicro-ROS関連のルートディレクトリと位置付け,その直下にRTOSの種類(これをRTOS nameなどと呼ぶ)やボードの種類(これをplatformなどと呼ぶ),および基本設定(これをconfigurationなどと呼ぶ)を組み合わせてサブディレクトリを作成しておけば,後々ディレクトリの目的がわかりやすい.
大抵のボードについては,ボードの名前ごとにplatformが設定され,その下に"nsh"や"usbnsh"などのconfigurationがぶら下がるという命名規則に従っている.
例としてnucleo-f446reを挙げると
RTOS name | platform | configuration |
---|---|---|
nuttx | nucleo-f446re | nsh |
という組み合わせが可能である.
なおnucleo-f767ziを含むいくつかのボードについては,platformやconfigurationの命名規則がやや変則的ということに注意が必要である. platformとしてnucleo-144という名前に集約され,その下にボード名を含む形で"f767-evalos"や"f722-nsh"などのconfigurationがぶら下がっている.
本チュートリアルにおいては
RTOS name | platform | configuration |
---|---|---|
nuttx | nucleo-144 | f767-netnsh |
となるので,上記のようなサブディレクトリ名を用いる.
- Workspace set-up
$ git clone -b $ROS_DISTRO https://github.com/micro-ROS/micro-ros-build.git src/micro-ros-build
$ rosdep update && rosdep install --from-path src --ignore-src -y
$ colcon build
$ source install/local_setup.bash
- Set the base configuration
# シェルスクリプトの引数は RTOS name と platform
$ ros2 run micro_ros_setup create_firmware_ws.sh nuttx nucleo-144
# この段階で,firmwareディレクトリ以下に実際のNuttXのソース(NuttX)やXRCE DDS関連のソース(mcu_ws)がチェックアウトされているので,どんなplatformやconfigurationがサポートされている(可能性が高い)か,firmware/NuttX/configs以下を覗いてみると良い
# シェルスクリプトの引数は configuration
$ ros2 run micro_ros_setup configure_firmware.sh f767-netnsh
- RMWまわりの不具合回避
2020.05.15現在,チュートリアル通りにファームウェアのビルドを実行していくと,ビルドは通るものの実行時に若干の不具合らしき現象が見られる.nsh上でpublisher exampleを1度実行し,正常終了した後に再びpublisher exampleを実行するとダンプを吐いて死んでしまうという現象が起きている.
2020.05.06にrmw_microxrceddsについて,メモリ初期化に関する変更が行われた影響と思われる(コミットID : f6d2ef61aaef7a93734bcd848bf1566c02ecee6d).これを回避するため,rmw_microxrceddsについて1つ前のコミット(コミットID : 34ed379e4a838201e1bfe36325074c1629db2372)を指定する.
$ cd firmware/mcu_ws/uros/rmw_microxrcedds
$ git checkout 34ed379e4a838201e1bfe36325074c1629db2372
将来的には,本節の操作は必要なくなる可能性がある.
- Micro-ROS Configuration
$ cd ~/uros_ws/nuttx__nucleo-144__f767-netnsh/firmware/NuttX
$ make menuconfig
以下に,make menuconfigで設定する項目を挙げる.
なお今回のデモンストレーションの目的に必須ではないが,ボード上のLEDをユーザアプリから使えるようにする設定と,そのサンプルアプリも有効にする(デフォルトではLEDはシステムの状態を表示するためにカーネルがハンドリングしている).これは,将来的にmicro-ROS側でのsubscribeを確認するための"Lチカ"を実装できるようにしたり,ホストPCからtopicが届く周期の正確性を測定できるようにするための布石である.
区分にverifyと記されているものについては確認のみで良い.addと記されている項目は,公式サイトのチュートリアルに加えて設定するべき項目である.
区分 | 設定箇所 | 設定値 |
---|---|---|
verify | System Type > STM32 Peripheral Support > USART3 | 有効 |
add | Board Selection > Board LED Status support | 無効 |
add | Board Selection > Button interrupt support | 有効 |
add | Board Selection > Enable boardctl() interface | 有効 |
RTOS Features > Clocks and Timers > Support CLOCK_MONOTONIC | 有効 | |
add | Device Drivers > Input Device Support | 有効 |
add | Device Drivers > Input Device Support > Button Inputs | 有効 |
add | Device Drivers > Input Device Support > Button Inputs > Generic Lower Half Button Driver | 有効 |
add | Device Drivers > LED Support > LED Driver | 有効 |
add | Device Drivers > LED Support > LED Driver > Generic Lower Half LED Driver | 有効 |
Device Drivers > Serial Driver Support > Serial TERMIOS support | 有効 | |
Library Routines > Standard Math Library | 有効 | |
Library Routines > sizeof(_Bool) is a 8-bits | 有効 | |
Library Routines > Build uClibc++ (must be installed) | 有効 | |
add | Application Configuration > NSH Library > Have architecture-specific initialization | 有効 |
add | Application Configuration > NSH Library > Networking Configuration > Network initialization > IP Address Configuration > Use DHCP to get IP address | 有効 |
add | Application Configuration > NSH Library > Networking Configuration > Network initialization > IP Address Configuration > Router IPv4 address | DHCPサーバとなるルーターのIPアドレスを16進表記で設定 |
add | Application Configuration > NSH Library > Networking Configuration > Network initialization > IP Address Configuration > IPv4 Network mask | ネットマスクを16進表記で設定.大抵の場合はデフォルトの0xffffff00(= 255.255.255.0)で問題ない |
add | Application Configuration > NSH Library > Networking Configuration > Network initialization > IP Address Configuration > Hardware has no MAC address | 有効 |
Application Configuration > micro-ROS | 有効 | |
verify | Application Configuration > micro-ROS > Transport > UDP Transport | 有効 |
add | Application Configuration > micro-ROS > IP address of the agent | DDS agentを立ち上げるホストPCのIPアドレスを10進表記で設定 |
add | Application Configuration > Examples > Buttons driver example | 有効 |
add | Application Configuration > Examples > Buttons driver example > Show Buttons Names | 有効 |
add | Application Configuration > Examples > LED driver example | 有効 |
Application Configuration > Examples > microROS Publisher | 有効 |
- Add C++ standard library includes
firmware/NuttX/Make.defsにuClibc++のヘッダへのパスを追加する.
else
# Linux/Cygwin-native toolchain
MKDEP = $(TOPDIR)/tools/mkdeps$(HOSTEXEEXT)
ARCHINCLUDES = -I. -isystem $(TOPDIR)/include
ARCHXXINCLUDES = -I. -isystem $(TOPDIR)/include -isystem $(TOPDIR)/include/cxx
ARCHXXINCLUDES+=-isystem $(TOPDIR)/include/uClibc++ # <- here!
ARCHSCRIPT = -T$(TOPDIR)/configs/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)
endif
- Add C++ atomics builtins
libatomicの追加.
$ cd ~/uros_ws/nuttx__nucleo-144__f767-netnsh/
$ cp firmware/NuttX/configs/olimex-stm32-e407/src/libatomic.c firmware/NuttX/configs/nucleo-144/src
firmware/NuttX/configs/nucleo-144/src/Makefileにlibatomic.cのエントリを追加する.
CSRCS = stm32_boot.c libatomic.c
# ^
# |
# here!
- ボタンデバイス(/dev/buttons)のレジストレーション
システム起動時にボタンデバイスを登録するコードが抜けていたので,他のボードを参考に書いたパッチを適用する.
$ cd ~/uros_ws/nuttx__nucleo-144__f767-netnsh/firmware/NuttX/configs/nucleo-144/src
$ wget https://raw.githubusercontent.com/maehara-keisuke/micro-ROS_Demo_on_STM32_nucleo-f767zi/master/firmware/NuttX/configs/nucleo-144/src/stm32_appinitialize.patch
$ patch stm32_appinitialize.c stm32_appinitialize.patch
- publisher exampleの改造
micro-ROSに同梱されているpublisher exampleは,指定回数ループでagentにtopicを送りつけるものである.またNuttXに同梱されているbuttons exampleはボタンを押す or 離すといったイベントを待ち受け,イベントが発生するとコンソールに表示するものである.publisher exampleにbuttons exampleのコードを付け加えることで,ボタンのイベントが発生するたびにagentにtopicを送りつけるように改造した.
ROS Japan UG #36 LT@Google Meetの発表後に当該ソースの変更があったため,パッチが当たらなくなっている(参考情報).このため,パッチ適用前に当該ソースのcommitを1つ前のものに戻すようにしている.
$ cd ~/uros_ws/nuttx__nucleo-144__f767-netnsh/firmware/apps/examples/publisher
$ git checkout 3ff9fb6d385b7936cd55142f1e77cd654ffafaa2
$ wget https://raw.githubusercontent.com/maehara-keisuke/micro-ROS_Demo_on_STM32_nucleo-f767zi/master/firmware/apps/examples/publisher/publisher_main.patch
$ patch publisher_main.c publisher_main.patch
- ファームウェアのビルド
$ cd ~/uros_ws/nuttx__nucleo-144__f767-netnsh/
$ ros2 run micro_ros_setup build_firmware.sh
- ファームウェアの書き込み
st-linkの側のmicroUSBポートをホストPCと接続し,以下の書き込みツールで書き込む.nucleo-f767ziはmbedにも対応しているので,デスクトップ上に現れるUSB Mass Storageにドラッグ・アンド・ドロップするのでも良い.
$ st-flash write firmware/NuttX/nuttx.bin 0x8000000
好みのターミナルアプリでNuttXのシリアルコンソールに接続する.デバイスファイルの名前は通常"/dev/ttyACM0"となり,ボーレートは"115200"を設定する. DHCPサーバ機能を持つルータとEthernetケーブルで接続し,いったんボード上のリセットボタンによりシステムをリセットする.IPの配布が正常に行われれば,ターミナルアプリにNuttXのプロンプトが表示される.
ホストPCの側でMicro XRCE-DDS Agentを立ち上げる.(v1.3.0以降を使用する場合はIPv6 supportに伴ってSubcommandが変更されている)
# v1.1.6以前の場合
$ /usr/local/bin/MicroXRCEAgent udp --port 8888
# v1.3.0以降の場合
$ /usr/local/bin/MicroXRCEAgent udp4 --port 8888
NuttXのシリアルコンソールでpublisherを実行する
nsh> publisher
この段階でMicro XRCE-DDS Agentの画面にセッションが確立されたというメッセージが表示されていればOK.
ホストPCの側で別のターミナルを立ち上げ,topicが見えているか確認する.
# ROS2 Dashing Diademataを公式のチュートリアルに従ってソースからビルドしている場合の例
$ source ros2_dashing/install/setup.bash
# aptからバイナリインストールしている場合の例
$ source /opt/ros/dashing/setup.bash
$ ros2 topic list
/parameter_events
/rosout
/std_msgs_msg_Int32
/std_msgs_msg_Int32が見えていればOK.
topicを待ち受ける.
$ ros2 topic echo /std_msgs_msg_Int32
後はゴールイメージで示したように,ボタンを押したり離したりしたタイミングでtopicを受信できることを確認できればOK.
以上