1. 环境搭建与Hello World
任务目标
在ESP32开发板上搭建micro-ROS环境,实现一个发布节点,周期性地向ROS 2主机发送包含"Hello World"字符串的自定义消息,并在主机端通过ros2 topic echo验证接收。
环境与依赖
- 硬件:ESP32开发板(如ESP32-DevKitC)、USB转串口线
- 主机:Ubuntu 22.04,已安装ROS 2 Humble
- 固件框架:ESP-IDF v5.1(需预先安装)
- micro-ROS组件:
micro_ros_espidf_component(v2.0.0及以上)
实现步骤
在ESP-IDF工程中通过组件管理器添加micro-ROS依赖,编写发布节点代码,配置Wi-Fi连接与agent地址,编译烧录后运行。
关键完整代码
// main.c
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "micro_ros_espidf_component.h"
static const char *TAG = "micro_ros_node";
// 自定义消息类型(与主机端一致)
#include "std_msgs/msg/string.h"
// Wi-Fi配置
#define WIFI_SSID "YOUR_SSID"
#define WIFI_PASS "YOUR_PASSWORD"
// micro-ROS agent IP与端口
#define ROS_AGENT_IP "192.168.1.100"
#define ROS_AGENT_PORT 8888
static void wifi_init(void) {
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
wifi_config_t wifi_config = {
.sta = {
.ssid = WIFI_SSID,
.password = WIFI_PASS,
},
};
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
ESP_ERROR_CHECK(esp_wifi_connect());
}
static void micro_ros_task(void *arg) {
// 初始化micro-ROS
micro_ros_espidf_component_init();
// 创建发布者
rcl_publisher_t publisher = rcl_get_zero_initialized_publisher();
std_msgs__msg__String msg;
std_msgs__msg__String__init(&msg);
const char *node_name = "esp32_hello_publisher";
const char *topic_name = "hello_world_topic";
// 创建节点
rcl_node_t node = rcl_get_zero_initialized_node();
rcl_allocator_t allocator = rcl_get_default_allocator();
rclc_support_t support;
rcl_ret_t rc = rclc_support_init(&support, 0, NULL, allocator);
if (rc != RCL_RET_OK) {
ESP_LOGE(TAG, "rclc_support_init failed: %d", rc);
vTaskDelete(NULL);
}
rc = rclc_node_init_default(&node, node_name, "", &support);
if (rc != RCL_RET_OK) {
ESP_LOGE(TAG, "rclc_node_init_default failed: %d", rc);
vTaskDelete(NULL);
}
rc = rclc_publisher_init_default(
&publisher,
&node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, String),
topic_name
);
if (rc != RCL_RET_OK) {
ESP_LOGE(TAG, "rclc_publisher_init_default failed: %d", rc);
vTaskDelete(NULL);
}
// 周期发布
char hello_msg[50];
int count = 0;
while (1) {
snprintf(hello_msg, sizeof(hello_msg), "Hello World from ESP32 #%d", count++);
msg.data.data = hello_msg;
msg.data.size = strlen(hello_msg);
msg.data.capacity = sizeof(hello_msg);
rc = rcl_publish(&publisher, &msg, NULL);
if (rc == RCL_RET_OK) {
ESP_LOGI(TAG, "Published: %s", hello_msg);
} else {
ESP_LOGE(TAG, "Publish failed: %d", rc);
}
vTaskDelay(pdMS_TO_TICKS(1000)); // 1Hz
}
// 清理(实际不会到达)
rcl_publisher_fini(&publisher, &node);
rcl_node_fini(&node);
vTaskDelete(NULL);
}
void app_main(void) {
wifi_init();
xTaskCreate(micro_ros_task, "micro_ros_task", 8192, NULL, 5, NULL);
}
工程配置
在idf_component.yml中添加依赖:
dependencies:
micro_ros_espidf_component:
version: "*"
git: https://github.com/micro-ROS/micro_ros_espidf_component.git
运行与验证
- 在主机启动micro-ROS Agent:
ros2 run micro_ros_agent micro_ros_agent udp4 --port 8888 - 编译烧录:
idf.py build flash monitor - 在主机新终端执行:
ros2 topic echo /hello_world_topic std_msgs/msg/String
通过条件:主机终端每秒显示一条data: Hello World from ESP32 #N(N为递增序号),且ESP32串口日志同步输出Published: Hello World from ESP32 #N,即表示micro-ROS通信链路正常。
常见问题
- Wi-Fi连接失败:确认SSID/密码正确,ESP32与主机在同一网段。
- Agent无法发现设备:检查主机防火墙是否放行UDP 8888端口,确认Agent先于设备启动。
- 编译报错找不到micro_ros头文件:执行
idf.py reconfigure重新解析组件依赖。