Emileの備忘録

色々な事をだらだらと

STM32 Nucleo-F767ziでmicro-ROSを動かす(CubeMX+CMake)

この記事は学ロボアドベントカレンダーの1日目の記事です。
今年も先駆けを務めさせて頂きます。殿も務める予定です。


adventar.org


この記事はSTM32 Nucleo-F767zi上でmicro-ROSを動かす為の設定をまとめた記事です。
CubeMX+CMakeで動かす事を前提にしています。

動作環境はUbuntu 22.04を想定しています。


==============目次==============

===============================


1. micro-ROSとは

micro-ROSはマイコン等の組み込みシステム上で動作するROS2のclientライブラリです。
real-time性が考慮されており、一般的なROS2よりも低遅延で動作します。

PC上のROS2とマイコンの間で(表面的には)通信レイヤーを意識せずtopic通信等が可能であり、単純に便利です。

micro.ros.org



mROS2と違ってhost PC上でagentを動作させる必要があるのがデメリットですが、
ユーザーが多く、調べれば色々と出てくるのがメリットだとは思います。

※ micro-ROSはμROSと略す事が多いっぽいです。(mROSとするとmROS2と判別しにくい)


今年のキャチロボで実戦投入しました。



2. Agentの準備

PCで動かすmicro-ROS Agentを導入します。

以下のリポジトリをcloneして下さい。
github.com


パス等通したら次を実行して行きます。

・micro-ROS Agentを作成

ros2 run micro_ros_setup create_agent_ws.sh  # Download micro-ROS-Agent packages
ros2 run micro_ros_setup build_agent.sh  # build step
source install/local_setup.bash  # setup env


・micro-ROSのAgentを動かす

ros2 run micro_ros_agent micro_ros_agent serial -b 115200 --dev /dev/ttyACM0  # Run a micro-ROS agent

※ /dev/ttyACM0のデバイスと115200のserial通信でやり取りする場合の設定


Agentは簡単に動かせます。





3. firmware libraryの設定

3-1. CubeMXの設定

CubeMXのpin設定は以下のリポジトリと同様に行います。
github.com


具体的には、以下の様にpinを設定します。

・System Core/RCC
 ・HSE: Crystal/Ceramic Resonator

・System Core/SYS
 ・Timerbase Source: TIM1

・Connectivity/USART3
 ・NVIC Setting: Mode:Asynchronous
 ・USART3 global interrupt: Enable

 ・DMA SettingsでUSART3_RXを追加
  ・Request SettingのModeをCircular
  ・PriorityをVery High

 ・DMA SettingsでUSART3_TXを追加
  ・PriorityをVery High

・Connectivity/USB_OTG_HS
 ・External Phy: Device Only

・Middleware and Software Packs/FREERTOS
 ・Interface: CMSIS_V2
 ・FPU: Enable
 ・Taskを追加
  ・stack sizeは必ず3000以上に
   

・Middleware and Software Packs/USB_DEVICE
 ・Class For FS IP:Communication Device Class(Virtual Port Com)

・Project Manager/Code Generator
 ・Generate peripheral initialization as a pair of .c/.h files per peripheralをonにする。(忘れやすい)




3-2. library generationの設定

CubeMX+Makefileで動かす例が公式から上がっているので、こちらを流用します。
github.com



ここで説明する設定の全体像は以下のリポジトリにまとめてあります。
GitHub - Emile-Aquila/micro-ROS_example_for_F767zi: Example Codes for micro-ROS on F767zi with CMake + STM32 CubeMX


まずmicro_ros_stm32cubemx_utilsリポジトリをcloneし、
・extra_sources
・microros_static_library
の2つのフォルダのみ残して、projectフォルダへ移植します。(これ以外のフォルダ/ファイルを削除)


さらに、microros_static_library/library_generation下のlibrary_generation.shを
FPUを使えるように無理矢理書き換えます。

#export RET_CFLAGS=$(make print_cflags)
export RET_CFLAGS="-mcpu=cortex-m7 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard -specs=nosys.specs -fdata-sections -ffunction-sections"

詳細: micro-ROS_example_for_F767zi/micro_ros_stm32cubemx_utils/microros_static_library/library_generation/library_generation.sh at main · Emile-Aquila/micro-ROS_example_for_F767zi · GitHub


加えて、library_generation下のcolcon.metaのmicroxrcedds_clientに以下を追加します。

"-DUCLIENT_HARD_LIVELINESS_CHECK=ON",
"-DUCLIENT_HARD_LIVELINESS_CHECK_TIMEOUT=1000"

Agentからmicro-ROSの生存確認が出来る様になります。

ネットサーフィンしてて設定を見つけました。
4.3. Reconnections and liveliness — Vulcanexus 1.0.0 documentation



micro-ROSで使うpackageを追加したい場合は、
library_generation/extra_packages/extra_packages.reposにリポジトリを追記して下さい。



最後に以下を実行してlibraryを生成します。
micro_ros_stm32cubemx_utilsが含まれるディレクトリで実行して下さい。

sudo docker run -it --rm -v $(pwd):/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library microros/micro_ros_static_library_builder:humble

※ static libraryの設定を書き換える度に上のコマンドを実行します。



3.3. CMakeの設定

CMakeの設定について説明します。

CMakeを選択したのは普段CLionで開発していて都合が良い&Makefileよりも書きやすいからです。
(ClionでCubeMXのProjectを読み込む方法は以下の記事にまとめられています。)
STM32CubeMX プロジェクト | CLion ドキュメント



設定の要点を抜き出すと以下の様になります。

・CMakeLists.txt

set(MROS_UTILS_DIR "./micro_ros_stm32cubemx_utils")

include_directories(
        ${MROS_UTILS_DIR}/microros_static_library/libmicroros/microros_include
        Core/Inc ... 
)

(略)


file(GLOB_RECURSE SOURCES
        "${MROS_UTILS_DIR}/extra_sources/custom_memory_manager.c"
        "${MROS_UTILS_DIR}/extra_sources/microros_allocators.c"
        "${MROS_UTILS_DIR}/extra_sources/microros_time.c"
        "${MROS_UTILS_DIR}/extra_sources/microros_transports/dma_transport.c"
        "Core/*.*" "Middlewares/*.*" "Drivers/*.*" "USB_DEVICE/*.*"
)

(略)

target_link_libraries(${PROJECT_NAME}.elf ${CMAKE_SOURCE_DIR}/micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a)
link_directories(${PROJECT_NAME}.elf ${CMAKE_SOURCE_DIR}/micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a)

(略)

公式のstm32cubemx_utilsに記述されていたMakefileの設定をCMakeに移植しただけです。
細かいCMakeの書き方や中身については省略させて頂きます。


これでCMakeでbuild出来るようになったはずです。
(.ioc -> CMakeはCLionにやらせています。)




4. micro-ROSのCodeを書く

rclcで書きます。頑張って下さい。

micro-ROS公式のドキュメントが参考になります。
micro.ros.org



キャチロボのF767ziのコードを公開しているので、こちらも参考になるかもしれません。

Catch23_F7/Core/Src/freertos.c at main · Emile-Aquila/Catch23_F7 · GitHub

補足すると、上のコードは

rmw_ret_t ping_result = rmw_uros_ping_agent(1000, 5);  // ping Agent

でAgentの接続確認を行っています。(Tutorialだとこの機能が探しにくかったはず)


RTOSのタスクの一つとしてmicro-ROS Clientは動作する様に実装されているので、
他のRTOSのタスクも一応動かす事が出来ます。


何かしら参考になる部分があれば嬉しいです。