2025年第27届中国机器人及人工智能大赛自主巡航实战经验分享

作为连续两届参加中国机器人及人工智能大赛并拿下国一的"老兵",我想跟大家分享一些在自主巡航项目中的实战经验。这个项目看起来简单,但真正做起来才发现里面有太多坑需要踩,希望我的一些经验能让你少走弯路。

一、项目实战理解

刚开始接触这个项目时,我和团队都以为主要难点在于算法的精巧设计。结果第一年比赛只拿了个国二,回来复盘才发现,比赛成败的关键不在于算法多高级,而在于系统的鲁棒性和稳定性

场地中那些任务信息图像看似简单,但在不同光照、不同角度下识别难度差异很大。记得去年决赛时,有支985高校的队伍用了很牛的深度学习算法,结果在现场因为光照问题,识别率直接掉到40%以下,连基本的任务点都没完成。

核心任务拆解:

  • 语音识别与播报(10分)
  • 三次任务点识别与到达(60分)
  • 终点到达(10分)
  • 技术文档(10分)

首先要确保60分的基础分稳稳拿到,才有机会冲击更高分数。

二、软件架构实战经验

ROS框架设计

第一年我们用了单体架构,所有功能都堆在一个节点里,结果调试和找bug特别痛苦。第二年重构为多节点设计:

这种模块化设计好处太多了:

  1. 团队可以并行开发
  2. 单元测试变得简单
  3. 找bug和调试效率提高10倍不止

实战代码技巧

1. 激光数据预处理

比赛中经常会遇到激光数据异常的情况,这段代码帮我们解决了很多问题:

// 激光雷达数据异常处理函数 sensor_msgs::LaserScan filterScan(const sensor_msgs::LaserScan& scan) { sensor_msgs::LaserScan filtered = scan; // 1. 剔除无效值 for (size_t i = 0; i < scan.ranges.size(); i++) { if (scan.ranges[i] < scan.range_min || scan.ranges[i] > scan.range_max || !std::isfinite(scan.ranges[i])) { filtered.ranges[i] = scan.range_max; // 将无效值设为最大值 } } // 2. 中值滤波 (三点滑动窗口) for (size_t i = 1; i < filtered.ranges.size() - 1; i++) { std::vector<float> window = { filtered.ranges[i-1], filtered.ranges[i], filtered.ranges[i+1] }; std::sort(window.begin(), window.end()); filtered.ranges[i] = window[1]; // 取中值 } // 3. 处理反光区域数据跳变 for (size_t i = 2; i < filtered.ranges.size(); i++) { float diff = std::abs(filtered.ranges[i] - filtered.ranges[i-1]); if (diff > 0.5 && filtered.ranges[i] > 5.0) { filtered.ranges[i] = filtered.ranges[i-1]; } } return filtered; }
2. 视觉自适应增强

不同场地光照差异很大,这段代码可以自动调整图像处理参数

def adaptive_image_processing(image): """根据图像特性自动调整处理参数""" # 计算图像亮度直方图 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) hist = cv2.calcHist([gray], [0], None, [256], [0, 256]) # 计算亮度均值和标准差 mean_brightness = np.mean(gray) std_brightness = np.std(gray) # 根据亮度特性调整参数 if mean_brightness < 80: # 低光环境 alpha = 1.5 # 增加对比度 beta = 25 # 增加亮度 elif mean_brightness > 180: # 高光环境 alpha = 0.7 # 降低对比度 beta = -20 # 降低亮度 else: # 正常光照 alpha = 1.0 beta = 0 # 应用亮度调整 adjusted = cv2.convertScaleAbs(image, alpha=alpha, beta=beta) # 光照均衡化处理 if std_brightness > 60: # 光照不均匀 # 转到LAB色彩空间进行亮度均衡化 lab = cv2.cvtColor(adjusted, cv2.COLOR_BGR2LAB) l, a, b = cv2.split(lab) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) cl = clahe.apply(l) merged = cv2.merge((cl, a, b)) return cv2.cvtColor(merged, cv2.COLOR_LAB2BGR) else: return adjusted

这个函数在我们决赛中立了大功,解决了场馆顶部射灯照射导致的图像过曝问题。

三、核心算法实战选择

SLAM定位算法

我们测试过三种主流SLAM算法的性能表现

实战经验: 正式比赛我们用Cartographer,虽然占用资源多,但闭环检测能力强,精度高。关键参数调优是:

# cartographer.lua中的关键参数 TRAJECTORY_BUILDER_2D.submaps.num_range_data = 80 # 减小以降低延迟 TRAJECTORY_BUILDER_2D.min_range = 0.15 # 设置为激光雷达最小值 TRAJECTORY_BUILDER_2D.max_range = 12.0 # 设置为激光雷达最大值 TRAJECTORY_BUILDER_2D.missing_data_ray_length = 5.0 # 处理遮挡 POSE_GRAPH.optimization_problem.huber_scale = 1e2 # 提高优化稳定性 POSE_GRAPH.constraint_builder.min_score = 0.55 # 提高约束阈值

视觉识别方案

不要迷信单一的深度学习模型,我们的最佳方案是多模型融合

def ensemble_prediction(image): """多模型融合预测""" # 使用不同模型进行预测 yolo_results = yolo_model.predict(image) resnet_results = resnet_model.predict(image) # 目标检测结果融合 all_boxes = [] # 添加YOLO检测框 for det in yolo_results: x1, y1, x2, y2 = det['bbox'] confidence = det['confidence'] * 0.6 # YOLO权重 label = det['class'] all_boxes.append([x1, y1, x2, y2, confidence, label]) # 添加ResNet检测框 for det in resnet_results: x1, y1, x2, y2 = det['bbox'] confidence = det['confidence'] * 0.4 # ResNet权重 label = det['class'] all_boxes.append([x1, y1, x2, y2, confidence, label]) # 非极大值抑制 final_boxes = non_maximum_suppression(all_boxes, 0.5) # 标签投票 final_results = [] for box_group in final_boxes: # 计算平均边界框 avg_box = calculate_average_box(box_group) # 标签投票 labels = [b[5] for b in box_group] label = most_common(labels) # 计算置信度 confidence = sum([b[4] for b in box_group]) final_results.append({ 'bbox': avg_box, 'class': label, 'confidence': confidence }) return final_results

这种多模型融合方法在不稳定光照条件下识别率要高15%左右,虽然计算开销大了点,但值得。

 四、导航平滑性优化

速度平滑滤波器

导航卡顿的核心问题是速度命令变化过于剧烈。我们实现了一种基于双指数平滑的速度命令过滤器:

class VelocityFilter { public: VelocityFilter(double alpha = 0.3, double beta = 0.1) : alpha_(alpha), beta_(beta), s_x_(0), s_y_(0), s_theta_(0), b_x_(0), b_y_(0), b_theta_(0), initialized_(false) {} geometry_msgs::Twist filter(const geometry_msgs::Twist& raw_cmd) { if (!initialized_) { // 初始化 s_x_ = raw_cmd.linear.x; s_y_ = raw_cmd.linear.y; s_theta_ = raw_cmd.angular.z; b_x_ = 0; b_y_ = 0; b_theta_ = 0; initialized_ = true; return raw_cmd; } // 双指数平滑滤波器 // 更新级数项 double s_x_prev = s_x_; double s_y_prev = s_y_; double s_theta_prev = s_theta_; s_x_ = alpha_ * raw_cmd.linear.x + (1 - alpha_) * (s_x_prev + b_x_); s_y_ = alpha_ * raw_cmd.linear.y + (1 - alpha_) * (s_y_prev + b_y_); s_theta_ = alpha_ * raw_cmd.angular.z + (1 - alpha_) * (s_theta_prev + b_theta_); // 更新趋势项 b_x_ = beta_ * (s_x_ - s_x_prev) + (1 - beta_) * b_x_; b_y_ = beta_ * (s_y_ - s_y_prev) + (1 - beta_) * b_y_; b_theta_ = beta_ * (s_theta_ - s_theta_prev) + (1 - beta_) * b_theta_; // 构造平滑后的速度命令 geometry_msgs::Twist filtered_cmd; filtered_cmd.linear.x = s_x_ + b_x_; filtered_cmd.linear.y = s_y_ + b_y_; filtered_cmd.angular.z = s_theta_ + b_theta_; return filtered_cmd; } private: double alpha_; // 数据项权重 double beta_; // 趋势项权重 // 平滑值 double s_x_, s_y_, s_theta_; // 趋势值 double b_x_, b_y_, b_theta_; bool initialized_; };

 TEB参数优化

通过对比测试,我们总结出一套最优的TEB局部规划器参数:

 

TebLocalPlannerROS: # 机器人配置 max_vel_x: 0.35 max_vel_x_backwards: 0.1 max_vel_y: 0.35 max_vel_theta: 0.8 acc_lim_x: 0.2 acc_lim_y: 0.2 acc_lim_theta: 0.3 min_turning_radius: 0.0 # 轨迹配置 teb_autosize: True dt_ref: 0.4 dt_hysteresis: 0.1 global_plan_overwrite_orientation: True max_global_plan_lookahead_dist: 2.0 feasibility_check_no_poses: 5 # 优化配置 no_inner_iterations: 5 no_outer_iterations: 4 penalty_epsilon: 0.05 weight_max_vel_x: 1.0 weight_max_vel_y: 1.0 weight_max_vel_theta: 1.0 weight_acc_lim_x: 2.0 weight_acc_lim_y: 2.0 weight_acc_lim_theta: 2.0 weight_kinematics_nh: 1000.0 weight_kinematics_forward_drive: 100.0 weight_optimaltime: 1.0 weight_obstacle: 50.0 weight_inflation: 0.1 # 平滑参数(关键部分) weight_adapt_factor: 2.0 enable_homotopy_class_planning: False simple_exploration: False

在比赛间隙调整这些参数时,我习惯按照这个顺序调整:先调速度限制,再调加速度限制,然后是权重参数。最关键的三个参数是weight_kinematics_forward_driveweight_obstacleacc_lim_theta

五、实战踩坑与应对

1. 机械结构问题

第一年比赛,我们的摄像头固定方式太简单,用的3D打印支架。结果比赛中底盘急停导致摄像头大幅晃动,视觉识别全乱了。

解决方案: 第二年改用铝合金框架 + 减震垫,效果好很多。记住一点:不要低估机械振动对传感器的影响

2. 光照变化

比赛场地光照往往是最大变数。记得去年西安的比赛,场馆靠窗一侧阳光直射,另一侧则很暗。

解决方案:

  • 视觉算法做好自适应处理
  • 提前20分钟进场调试
  • 准备多套参数配置,快速切换

3. 定位丢失

导航过程中定位丢失是常见问题。一个队友不小心走进场地或者场地有高反光材料,都可能导致定位失败。

def emergency_relocation(): """定位丢失应急处理""" # 1. 停止当前导航 stop_navigation() # 2. 切换为原地旋转模式采集数据 cmd_vel = rospy.Publisher('/cmd_vel', Twist, queue_size=1) twist = Twist() twist.angular.z = 0.5 # 缓慢旋转 # 发送旋转命令5秒 start_time = rospy.Time.now() rate = rospy.Rate(10) while (rospy.Time.now() - start_time).to_sec() < 5.0: cmd_vel.publish(twist) rate.sleep() # 3. 停止旋转 twist.angular.z = 0.0 cmd_vel.publish(twist) # 4. 尝试使用特征点匹配重定位 success = feature_based_relocalization() if success: rospy.loginfo("重定位成功,继续导航") resume_navigation() else: rospy.logwarn("重定位失败,切换到紧急模式") switch_to_emergency_mode()

 

六、总结与建议

如果让我给参加自主巡航项目的同学们一些建议,那就是:

  1. 基础分最重要:确保导航稳定可靠,拿到60分基础分,再追求更高分数
  2. 系统鲁棒性大于算法先进性:算法再先进,如果不够稳定,在比赛中也会翻车
  3. 充分测试各种极端情况:刻意制造干扰和异常,测试系统恢复能力
  4. 做好知识积累和经验传承:记录所有问题和解决方案,避免后来者重复踩坑

技术上,我的几点关键建议:

  • 多传感器融合是解决单一传感器不稳定的最佳方案
  • 参数自适应比固定参数在实际比赛中可靠得多
  • 故障容错机制是区分一般队伍和优秀队伍的关键

最后,希望大家都能享受这个比赛带来的技术挑战!我当年就是在比赛中学到了很多东西,今年我依旧会来参加今年的比赛,如果需要去年的工作空间或者今年的指导私聊博主,非常感谢!!!

Read more

AI 办公成职场标配,别再用错拖后腿!7 套书教你精准用 AI 提效

AI 办公成职场标配,别再用错拖后腿!7 套书教你精准用 AI 提效

2026三掌柜赠书活动第十八期 AI 办公成职场标配,别再用错拖后腿!7 套书教你精准用 AI 提效 目录 Part.0 前言 Part.1 开会汇报没重点?AI当“嘴替” Part.2 不想加班,还不知道搭个智能体帮你干? Part.3 主业涨薪难,想抓AI风口做副业? Part.4 DeepSeek总get不到你的点? Part.5 Office内置AI不会用? Part.6 不想被“职场体力活”耗空? Part.7 对抗工具墒增,实现职场进阶! Part.8 彩蛋:赠书! Part.9 结束语 Part.0 前言

别被“会聊天”的AI骗了!真正的数字助理,应该是ToClaw这样的

别被“会聊天”的AI骗了!真正的数字助理,应该是ToClaw这样的

这段时间 OpenClaw 很火,火到不少人第一次开始认真讨论一件事: AI 到底该只是陪你聊天,还是应该替你把事完成? 从官方说明看,OpenClaw 更偏向个人开源 AI 助手路线,推荐通过终端里的 onboarding wizard 完成配置,Windows 侧也建议走 WSL2。这种路线很酷,但对大多数普通办公用户来说,还是意味着一定的学习和折腾成本。 也正因为这样,我反而更能理解 ToDesk 推出 ToClaw 的价值:它不是想让每个人都去研究怎么“部署一个龙虾”,而是想把 AI 直接变成一个你登录 ToDesk 后就能随时使唤的数字助理。 真正的差别,不是会不会聊天,而是会不会接任务 现在很多 AI 工具都已经“很会说”了。写总结、写标题、润色文案、翻译内容,基本都不难。但问题在于,真实工作并不是一个纯聊天场景。

Agent实习模拟面试之Dify + Skill本地部署大模型智能体:从零构建企业级可落地的AI Agent系统

Agent实习模拟面试之Dify + Skill本地部署大模型智能体:从零构建企业级可落地的AI Agent系统 摘要:本文以一场高度仿真的Agent实习生岗位模拟面试为载体,聚焦当前热门的低代码Agent开发平台 Dify 与 自定义Skill(技能)机制,深入探讨如何在完全本地化环境中部署一个安全、可控、可扩展的大模型智能体(Agent)。通过“面试官提问—候选人回答—连环追问”的对话形式,系统性地拆解了Dify的核心架构、Skill插件开发、本地大模型集成(如Llama-3、Qwen)、RAG优化、权限控制、监控告警等关键环节,并结合企业实际场景(如内部知识问答、自动化办公)给出完整落地路径。全文超过9500字,适合对AI Agent开发、私有化部署、企业智能化转型感兴趣的工程师、架构师与在校学生阅读。 引言:为什么企业需要“本地部署的Dify + 自定义Skill”? 在2024–2026年的大模型应用浪潮中,一个显著趋势是:企业不再满足于调用公有云API,而是强烈要求数据不出域、模型可审计、能力可定制的私有化Agent解决方案。

【AI审稿提示词】—— 严肃的审稿人

【AI审稿提示词】—— 严肃的审稿人

AI Paper Review Prompts 修改于:A_Zhao.【prompt分享】严肃的审稿人.2025-5-21.LINUX DO. 将下面的内容复制&发送给AI即可,最好是有搜索功能的AI(比如ChatGPT/Gemini等) ## 角色:严苛、精准且富有洞察的学术审稿人 (The Strict, Precise & Insightful Academic Reviewer) 你是一位以“严苛、精准、富有洞察力”而闻名的资深学术审稿专家。你坚守最高的学术标准,你的首要任务是**严格审查(Strict Scrutiny)**,以确保只有最高质量的研究得以推进。你擅长一针见血地指出研究中的**核心缺陷**和**逻辑漏洞**,同时你的反馈必须是**具体、清晰且可执行的**。你的目标是驱动作者进行根本性的改进,以达到其投稿目标的最高标准。 ## 核心知识与能力: 1.