当前位置:   article > 正文

Micro-ros系列教程(1) 在STM32上部署micro-ros包括自定义消息类型_micro ros静态库编译

micro ros静态库编译


前言

国内已经有许多介绍关于如何在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
  • 1
  • 2

实际上,它就是把生成的配置文件给导入docker里面去
在这里插入图片描述
然后在docker里面执行library_generation.sh这个脚本文件
在这里插入图片描述
library_generation.sh脚本文件内容就是docker里面执行的内容,其实大家看得懂里面的内容就知道怎么去编译静态库了。看不懂也没关系,我们接下来会一步步教你编译。

编译micro-ros静态库

环境

  • ros2版本 Humble
  • 生成环境 WSL2-Ubuntu-22.04

安装交叉编译器

我们需要再我们的wsl2里面生成能够在arm 32位cpu上运行的静态库,所以必须使用交叉编译器。

sudo apt-get update
sudo apt-get install -y gcc-arm-none-eabi
  • 1
  • 2

输入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
  • 1
  • 2
  • 3
  • 4
  • 5

在src目录里面我们找到了有micro-ros-setup这个功能包,接着我们编译一下

rosdepc update && rosdepc install --from-paths src --ignore-src -y
colcon build
source install/local_setup.bash
  • 1
  • 2
  • 3

由于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
  • 1

在这里插入图片描述
输出这个说明源码生成成功了

自定义消息类型

回到工作空间下,现在我们应该有五个文件夹
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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

里面就是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"		#自定义传输接口
            ]
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

这里面配置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

  • 1
  • 2

编译完成后可以在firmware/build 里面看到静态库和头文件

头文件偏移

上述直接得到的头文件包含的比较深,外面还有一层文件夹,,比如我需要rclc的库可能得

#include <rcl/rcl/rcl.h>
  • 1

所以需要偏移一下
这里参考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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

然后执行

sudo chmod 777 fix_include.sh
./fix_include.sh
  • 1
  • 2

然后可以发现每个头文件外面的一层没了,这样firmware/build 里面的内容就是我们想要的micro-ros的头文件和静态库了

总结

本文比较详细的介绍了在stm32平台上如何生成micro-ros的静态库,根据官方的文档,剖析docker里面到底干了什么,但是移植到stm32上面还需要一些其他的文件,这个我们将在下一节介绍。
限笔者水平有限,以上若有不正确的地方,欢迎大家批评指正。
如果对您有帮助,麻烦点个star★★★加个关注吧!我会继续努力分享更多ROS2小知识
版权声明:本文为博主原创文章,未经博主允许不得转载。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/661244
推荐阅读
相关标签
  

闽ICP备14008679号