赞
踩
国内已经有许多介绍关于如何在Arduino平台上部署micro-ros的方法,但是对于stm32平台上部署micro-ros的方法却很少。micro-ros对于单片机来说,无非是一个静态库(xx.a)和头文件,目前stm32生成静态库很多人会推荐参考官方给的一个例子:cubemx生成静态库
但是按照步骤文档步骤成功率非常低,主要是网络原因,需要解决docker内部的科学上网问题才能成功。而且用官方的这个文档,很多地方我们都不能自己配置,比如如何自定义消息类型等等。我们更希望能不借助docker,直接在本地环境编译出静态库。
在官方给出的文档里面,会用docker运行
docker pull microros/micro_ros_static_library_builder:humble
docker run --rm -v <ABSOLUTE_PATH_TO_PROJECT>:/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:humble
实际上,它就是把生成的配置文件给导入docker里面去
然后在docker里面执行library_generation.sh这个脚本文件
library_generation.sh脚本文件内容就是docker里面执行的内容,其实大家看得懂里面的内容就知道怎么去编译静态库了。看不懂也没关系,我们接下来会一步步教你编译。
我们需要再我们的wsl2里面生成能够在arm 32位cpu上运行的静态库,所以必须使用交叉编译器。
sudo apt-get update
sudo apt-get install -y gcc-arm-none-eabi
输入arm-none-eabi-gcc -v
查看是否安装成功
由于是使用arm-none-eabi-gcc编译出来的静态库,所以是无法在KEIL里面和IAR里面使用。笔者推荐可以熟悉下如何搭建linux下的STM32开发环境。
下载官方的功能包
source /opt/ros/$ROS_DISTRO/setup.bash
mkdir uros_ws && cd uros_ws
git clone -b humble https://github.com/micro-ROS/micro_ros_setup.git src/micro_ros_setup
在src目录里面我们找到了有micro-ros-setup这个功能包,接着我们编译一下
rosdepc update && rosdepc install --from-paths src --ignore-src -y
colcon build
source install/local_setup.bash
由于rosdep是国外的服务器,所以这里我采用了小鱼社区的rosdepc
上一步我们编译出了可执行文件,接下来我们借助功能包编译出静态库
首先我们修改一下create_firmware_ws.sh里面的东西,这个sh文件在uros_ws/src/micro_ros_setup/scripts里面113行把rosdep改为rosdepc
这一步需要从github下载大量的源码,不使用代理速度很慢,失败率也很高,建议开启下代理。失败后下次生成会提示firmware已经存在,要rm这个文件夹。
ros2 run micro_ros_setup create_firmware_ws.sh generate_lib
输出这个说明源码生成成功了
回到工作空间下,现在我们应该有五个文件夹
build
fireware
install
log
src
其中fireware
是我们生成micro-ros的空间,我们在mcu_ws
创建我们的自定义的消息类型即可,参考官方文档
micro-ros自定义消息类型
这里面的colcon.meta和toolchain.cmake就是我们生成静态库需要指定的配置文件了,其中colcon.meta描述了我们micro-ros的配置,toolchain.cmake描述了单片机的平台。cubemx生成静态库的教程里面,library_generation.sh会找到cubemx生成的Makefile,然后从这里面知道单片机的信息,这里我们完全可以参考给的例子自己重新写。
新建这两个文件
toolchain.cmake里面的内容
set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_CROSSCOMPILING 1) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # SET HERE THE PATH TO YOUR C99 AND C++ COMPILERS # 在这里添加编译器路径 set(PIX /opt/gcc-arm-none-eabi-10.3-2021.10/bin) set(CMAKE_C_COMPILER ${PIX}/arm-none-eabi-gcc) set(CMAKE_CXX_COMPILER ${PIX}/arm-none-eabi-g++) set(CMAKE_C_COMPILER_WORKS 1 CACHE INTERNAL "") set(CMAKE_CXX_COMPILER_WORKS 1 CACHE INTERNAL "") # SET HERE YOUR BUILDING FLAGS set(FLAGS "-O2 -ffunction-sections -fdata-sections -fno-exceptions -mcpu=cortex-m7 -mfpu=fpv5-d16 -mfloat-abi=hard -nostdlib -mthumb --param max-inline-insns-single=500 -D'RCUTILS_LOG_MIN_SEVERITY=RCUTILS_LOG_MIN_SEVERITY_NONE'" CACHE STRING "" FORCE) #-mcpu=cortex-m3 改成 -mcpu=cortex-m7 # 加入 mfpu=fpv5-d16 -mfloat-abi=hard 支持硬件浮点编译 set(CMAKE_C_FLAGS_INIT "-std=c11 ${FLAGS} -DCLOCK_MONOTONIC=0 -D'__attribute__(x)='" CACHE STRING "" FORCE) set(CMAKE_CXX_FLAGS_INIT "-std=c++11 ${FLAGS} -fno-rtti -DCLOCK_MONOTONIC=0 -D'__attribute__(x)='" CACHE STRING "" FORCE) set(__BIG_ENDIAN__ 0)
里面就是cmake的写法,我首先指定了我arm-none-eabi-gcc的位置,然后主要修改的就是编译的标志,-mcpu=cortex-m7 -mfpu=fpv5-d16
因为笔者手里的单片机是H7系列的,是M7内核,有M4或者M3内核的同学请自行修改这两项,其他基本不需要改动。从这块我们也可以看出来,生产的静态库一个系列应该都是通用的!
colcon.meta里面的内容
{ "names": { "tracetools": { "cmake-args": [ "-DTRACETOOLS_DISABLED=ON", "-DTRACETOOLS_STATUS_CHECKING_TOOL=OFF" ] }, "rosidl_typesupport": { "cmake-args": [ "-DROSIDL_TYPESUPPORT_SINGLE_TYPESUPPORT=ON" ] }, "rcl": { "cmake-args": [ "-DBUILD_TESTING=OFF", "-DRCL_COMMAND_LINE_ENABLED=OFF", "-DRCL_LOGGING_ENABLED=OFF" ] }, "rcutils": { "cmake-args": [ "-DENABLE_TESTING=OFF", "-DRCUTILS_NO_FILESYSTEM=ON", "-DRCUTILS_NO_THREAD_SUPPORT=ON", "-DRCUTILS_NO_64_ATOMIC=ON", "-DRCUTILS_AVOID_DYNAMIC_ALLOCATION=ON" ] }, "microxrcedds_client": { "cmake-args": [ "-DUCLIENT_PIC=OFF", "-DUCLIENT_PROFILE_UDP=OFF", "-DUCLIENT_PROFILE_TCP=OFF", "-DUCLIENT_PROFILE_DISCOVERY=OFF", "-DUCLIENT_PROFILE_SERIAL=OFF", "-UCLIENT_PROFILE_STREAM_FRAMING=ON", "-DUCLIENT_PROFILE_CUSTOM_TRANSPORT=ON", "-DUCLIENT_PROFILE_SHARED_MEMORY=ON", #允许内存共享 "-DUCLIENT_SHARED_MEMORY_MAX_ENTITIES=20" ] }, "rmw_microxrcedds": { "cmake-args": [ "-DRMW_UXRCE_MAX_NODES=5", #最大节点数 "-DRMW_UXRCE_MAX_PUBLISHERS=6", #最大发布者数量 "-DRMW_UXRCE_MAX_SUBSCRIPTIONS=4", #最大订阅者数量 "-DRMW_UXRCE_MAX_SERVICES=6", #最大服务端数量 "-DRMW_UXRCE_MAX_CLIENTS=1", #最大客户端数量 "-DRMW_UXRCE_MAX_HISTORY=4", "-DRMW_UXRCE_TRANSPORT=custom" #自定义传输接口 ] } } }
这里面配置micro-ros的内容我大多和官方的例子一样,也有几个区别:由于我使用FreeRTOS需要多个任务进行ros的发布订阅等,所以我开启了`“-DUCLIENT_PROFILE_SHARED_MEMORY=ON”``允许内存共享来完成多任务接入ros,其实官方有针对FreeRTOS的多线程处理,但是我没有做成功,也期待有大佬可以弄出来做个教程,有人在GitHub上提出过这个问题FreeRTOS开启多线程支持。使用内存共享后,那些最大数量就应该尽量开的大一些。
退到ws目录下
ros2 run micro_ros_setup build_firmware.sh $(pwd)/firmware/toolchain.cmake $(pwd)/firmware/colcon.meta
编译完成后可以在firmware/build
里面看到静态库和头文件
上述直接得到的头文件包含的比较深,外面还有一层文件夹,,比如我需要rclc的库可能得
#include <rcl/rcl/rcl.h>
所以需要偏移一下
这里参考library_generation.sh里面的内容写个脚本文件,在firware里面建立脚本fix_include.sh
,里面的内容如下:
#!/bin/bash
######## Fix include paths ########
BASE_PATH=build
pushd mcu_ws > /dev/null
INCLUDE_ROS2_PACKAGES=$(colcon list | awk '{print $1}' | awk -v d=" " '{s=(NR==1?s:s d)$0}END{print s}')
popd > /dev/null
for var in ${INCLUDE_ROS2_PACKAGES}; do
if [ -d "${BASE_PATH}/include/${var}/${var}" ]; then
rsync -r ${BASE_PATH}/include/${var}/${var}/* $BASE_PATH/include/${var}
rm -rf ${BASE_PATH}/include/${var}/${var}
fi
done
然后执行
sudo chmod 777 fix_include.sh
./fix_include.sh
然后可以发现每个头文件外面的一层没了,这样firmware/build
里面的内容就是我们想要的micro-ros的头文件和静态库了
本文比较详细的介绍了在stm32平台上如何生成micro-ros的静态库,根据官方的文档,剖析docker里面到底干了什么,但是移植到stm32上面还需要一些其他的文件,这个我们将在下一节介绍。
限笔者水平有限,以上若有不正确的地方,欢迎大家批评指正。
如果对您有帮助,麻烦点个star★★★加个关注吧!我会继续努力分享更多ROS2小知识
版权声明:本文为博主原创文章,未经博主允许不得转载。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。