@liusiyu_alex_nuaa 我吐了啊,我测试了一下我是因为防火墙问题,我是wsl用户。。。。
在任务函数中每段加个检查看看,再在setup函数中加个延迟5s,确保串口能接收到消息。查查看wifi连上没,质量怎么样。此外测试的时候别忘了小车按按复位。
void microros_task(void *args)
{
// 1.设置传输协议并延迟一段时间等待设置的完成。
IPAddress agent_ip; // 用来存储 IP 地址。
agent_ip.fromString("xxxxxxx"); // 电脑/手机当前的IP地址。
set_microros_wifi_transports("xxx", "xxxxxxxx", agent_ip, 8888); // 设置传输协议。告诉机器人连名称为“xxx”的WiFi,密码为“xxxxxxx”。之后去往代理服务器的IP地址为xxxxxxxxx,端口号为8888的地方发消息。
Serial.print("WiFi status: ");
Serial.println(WiFi.status() == WL_CONNECTED ? "Connected" : "Failed"); // 判断wifi是否连接上,ture则"Connected",false则"Failed"。
if (WiFi.status() == WL_CONNECTED) {
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
delay(2000); // 等待2秒,等待wifi连接。
// 2.初始化内存分配器。
allocator = rcl_get_default_allocator(); // 获取默认的内存分配器。
// 3.初始化支持,并检查错误。
if (rclc_support_init(&support, 0, NULL, &allocator) != RCL_RET_OK) { Serial.println("support init failed"); }
// 初始化支持。使用这个默认的内存分配器 allocator(它使用标准的 malloc 和 free),在没有任何命令行参数的情况下,帮我初始化好 ROS 2 客户端库的底层环境,并把所有初始化好的状态信息都保存在 support 这个结构体里,供我后续创建节点使用。
// 4.初始化节点,并检查错误。
if (rclc_node_init_default(&node, "fishbot_motion_control", "", &support) != RCL_RET_OK) { Serial.println("node init failed"); }
// 初始化节点。在由 support 提供的运行环境中,创建一个名为 fishbot_motion_control 的节点,它位于全局命名空间(""),并把这个节点的所有状态信息保存在 node 这个结构体里。
// 5.初始化执行器,并检查错误。
unsigned int num_handles = 1; // 订阅和计时器的数量,注意这是一个要改的参数(句柄的数量)。大概,比如我设置5,它就有了5个槽位,编号0-4。现在比如0-3我填满了(有东西要执行),他就会去依次询问0-3有没有执行(有没有消息),没执行要去执行他们对应的功能(有消息回调)。句柄 = 唯一识别号。
if (rclc_executor_init(&executor, &support.context, 1, &allocator) != RCL_RET_OK) { Serial.println("executor init failed"); }
// 初始化执行器。使用 allocator 这个内存分配器,在 support.context 提供的 ROS 通信上下文里,初始化一个执行器 executor,让它能够管理 num_handles 个句柄(比如x个订阅者或定时器)。
// 6.初始化订阅者,并将其添加到执行器中。
rclc_subscription_init_best_effort(&sub_cmd_vel, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist), "/cmd_vel"); // 订阅者句柄地址,节点句柄地址,消息类型支持(什么类型的消息)(地址),话题名称(订阅哪个话题)。ROSIDL_GET_MSG_TYPE_SUPPORT 是 ROS 2 C语言客户端库(rclc)中一个非常重要的预处理宏,它就像是订阅者与特定消息类型之间的"桥梁"或"身份证"。
rclc_executor_add_subscription(&executor, &sub_cmd_vel, &msg_cmd_vel, twist_callback, ON_NEW_DATA); // 执行器句柄地址,订阅者句柄地址,存放接收到的消息的内存空间的地址(消息缓冲区),回调函数,触发条件:有新数据时触发,一收到消息就执行回调。
// 7.循环执行器。
rclc_executor_spin(&executor); // 循环执行器。它会持续地、反复地检查所有已添加到执行器的句柄(如订阅者、定时器),并处理它们对应的回调函数。只要 ROS 2 的上下文(context)保持有效,这个循环就不会停止.
// // spin 返回说明上下文已失效;不要跑完任务,直接挂起:
// while (1) { vTaskDelay(pdMS_TO_TICKS(1000)); } // 或 vTaskDelete(NULL);
}