使用CLion进行嵌入式开发并配置micro-ROS 接入ROS2生态

使用CLion进行嵌入式开发并配置micro-ROS 接入ROS2生态

环境

  • Ubuntu 22.04
  • ROS2-Humble
  • MPU:STM32F407VET6
  • 树莓派4b(已安装好ROS2-Humble)
  • 可访问国际互联网的代理

性能较弱的芯片可能无法运行microros

image.png

配置开发环境

配置CLion开发嵌入式

参考稚晖君的博客https://zhuanlan.zhihu.com/p/145801160,以下步骤建立在已经安装好CLion喝CubeMX的情况下进行

  1. 下载arm-none-eabi-gcc,解压

image.png

  1. 打开CLion,安装设置→构建、执行、部署→工具链,点击左上角加号添加一个工具链

image.png

其中C和C++编译器选择上一步解压的arm-none-eabi-gcc,并把bin文件夹添加到环境变量

image.png

测试会在编译micro-Ros app中进行

使用CubeMX配置芯片

参考视频

micro_ros_stm32cubemx_utils

  1. 选择芯片型号STM32F407VET6
  2. RCC配置,HSE选择crystal

image.png

  1. 打开debugtimebase ,source 选择tim1

image.png

  1. 配置FREERTOS

    选择中间件Middleware→freertos,interface选v2,选择Tasks and Queues,双击Tasks,配置如下

    image.png

    OK保存配置

  2. 串口配置

    • DMA

image.png

image.png

  1. Clock Configuration

image.png

  1. Project Mangager

    Toolchain IDE选择Makefile

    CodeGenerator

    image.png

  2. 生成代码

创建microros-ROS app

准备工作

  1. 使用CLion打开刚才生成的文件夹

image.png

  1. 点击小锤子构建,输出以下构建成功,会多出一个build文件夹

image.png

  1. 创建config文件夹,创建daplink.cfg,根据下载自定义文件内容

image.png

  1. 点击小锤子旁边的运行/调试配置,点击加号选择‘OpenOCD下载并运行’,根据自己路径填写可执行的二进制文件和面板配置文件

image.png

  1. 连接开发版,烧录代码,点击小锤子旁的绿色三角,提示已下载固件表示烧录成功

image.png

创建micoro-ROS app

  1. 克隆https://github.com/micro-ROS/micro_ros_stm32cubemx_utils到项目文件夹
  2. 将以下内容复制到Makefile,注意复制到

# build the application 之前的一行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#######################################
# micro-ROS addons
#######################################
LDFLAGS += micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a
C_INCLUDES += -Imicro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include

# Add micro-ROS utils
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c

# Set here the custom transport implementation
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c

print_cflags:
@echo $(CFLAGS)

image.png

  1. 执行静态库生成工具,我的代理端口是7897
1
docker run -it --rm -v ${PWD}:/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library --env http_proxy=http://host.docker.internal:7897 --env https_proxy=http://host.docker.internal:7897 microros/micro_ros_static_library_builder:humble
  1. 编辑freertos.c,以下替换头文件
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
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "usart.h"
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <uxr/client/transport.h>
#include <rmw_microxrcedds_c/config.h>
#include <rmw_microros/rmw_microros.h>
#include <std_msgs/msg/int32.h>
#include <geometry_msgs/msg/twist.h>

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
typedef StaticTask_t osStaticThreadDef_t;
/* USER CODE BEGIN PTD */
bool cubemx_transport_open(struct uxrCustomTransport * transport);
bool cubemx_transport_close(struct uxrCustomTransport * transport);
size_t cubemx_transport_write(struct uxrCustomTransport* transport, const uint8_t * buf, size_t len, uint8_t * err);
size_t cubemx_transport_read(struct uxrCustomTransport* transport, uint8_t* buf, size_t len, int timeout, uint8_t* err);

void * microros_allocate(size_t size, void * state);
void microros_deallocate(void * pointer, void * state);
void * microros_reallocate(void * pointer, size_t size, void * state);
void * microros_zero_allocate(size_t number_of_elements, size_t size_of_element, void * state);

  1. 编辑freertos.c里的StartDefaultTask函数

和main.c的while功能类似,来完成主要的逻辑,这段代码可以在micro_ros_stm32cubemx_utils/sample_main.c中找到,里面提供了各种实例

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
57
58
59
60
61
62
63
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
// micro-ROS configuration

rmw_uros_set_custom_transport(
true,
(void *) &huart1,
cubemx_transport_open,
cubemx_transport_close,
cubemx_transport_write,
cubemx_transport_read);

rcl_allocator_t freeRTOS_allocator = rcutils_get_zero_initialized_allocator();
freeRTOS_allocator.allocate = microros_allocate;
freeRTOS_allocator.deallocate = microros_deallocate;
freeRTOS_allocator.reallocate = microros_reallocate;
freeRTOS_allocator.zero_allocate = microros_zero_allocate;

if (!rcutils_set_default_allocator(&freeRTOS_allocator)) {
printf("Error on default allocators (line %d)\n", __LINE__);
}

// micro-ROS app

rcl_publisher_t publisher;
std_msgs__msg__Int32 msg;
rclc_support_t support;
rcl_allocator_t allocator;
rcl_node_t node;

allocator = rcl_get_default_allocator();

//create init_options
rclc_support_init(&support, 0, NULL, &allocator);

// create node
rclc_node_init_default(&node, "cubemx_node", "", &support);

// create publisher
rclc_publisher_init_default(
&publisher,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32),
"cubemx_publisher");

msg.data = 0;

for(;;)
{
rcl_ret_t ret = rcl_publish(&publisher, &msg, NULL);
if (ret != RCL_RET_OK)
{
printf("Error publishing (line %d)\n", __LINE__);
}

msg.data++;
osDelay(10);
}
/* USER CODE END StartDefaultTask */
}

上面的代码创建了一个节点和一个发布者,发布一个整型数字,每次循环加一

  1. 编译烧录

配置ros-agent与micoro-ROS通信

  1. 使用SSH连接树莓派

    若忘记IP地址可用Nmap扫描

    1
    nmap -sn 192.168.1.0/24

image.png

  1. 安装ros-agent
1
2
3
4
5
6
7
8
sudo apt-get install -y build-essential
mkdir -p microros_ws/src
cd microros_ws/src
git clone http://github.fishros.org/https://github.com/fishros/micro-ROS-Agent.git -b humble
git clone http://github.fishros.org/https://github.com/micro-ROS/micro_ros_msgs.git -b humble
cd ~/microros_ws/
colcon build
source install/setup.bash
  1. 使用usb转ttl将开发版和树莓派连接

1000027671.jpg

  1. 运行agent
1
ros2 run micro_ros_agent micro_ros_agent serial -b 115200 --dev /dev/ttyUSB0

注意波特率,一般默认是115200,设备号一般是ttyUSB0

按下RST键,通信成功

image.png

image.png

使用foxglove进行可视化

  1. 安装
1
sudo apt install ros-$ROS_DISTRO-foxglove-bridge
  1. Launch
1
ros2 launch foxglove_bridge foxglove_bridge_launch.xml

image.png

注意端口是8756

  1. 打开foxglove建立连接

image.png

image.png

可以看到micro-ROS的话题出现在这里了