机器人自主导航:navigate、PurePursuit 与区域漫游
自主导航最容易写成“先定位,再规划,最后控制”。这个项目确实有这三层,但真正的工作量在三层之间的边界:什么时候允许出发,什么时候必须停,定位掉了怎么办,点云断了怎么办,到了目标点怎么才算真正对准。 navigate 是一个组合 Skillnav.navigate 不是把所有逻辑都写在同一个类里。它通过 ROS2 Action 组合平台里已经存在的能力: localization.pose 提供 /skill/pose。 motion.gait 负责切步态。 motion.move 和共享 MotionController 负责最终下发轴指令。 perception.freespace 提供前方障碍、负障和扇区距离。 live 点云作为避障兜底。 Skill 之间不直接调内部实现,只走 Action 和 topic。这样导航、站立、检测都暴露成同一种契约,将来 VLM 或上层编...
机器人路径规划:Costmap、A* 与路网模式
这个项目有两种路径来源:没有路网时,用点云建 Costmap,再跑全局 A*;有路网时,直接拿着路网边的中心线走。两者看起来都是“给一条折线”,但计算路径的位置完全不同。 Costmap:把点云变成可搜索的栅格点到点导航的目标是地图坐标。要跑 A*,必须先把点云转换成 2D 占据栅格。navigate 在执行线程里按需调用建图逻辑。 关键不是简单地把点投影到网格,而是处理几个工程问题。 首先是密度阈值。RSAIRY 是稀疏固态雷达,单点噪声多。只有某个 cell 内的点数达到阈值,才认为它是障碍。否则一两个飞点就会把地图点得到处是墙。 其次是障碍膨胀。机器人不是质点,有外接半径。障碍 cell 会按机体半径向外膨胀,让路径保持安全距离。 然后是轨迹雕刻。狗走过的 trajectory 是真实可通行路径,即使它看起来离障碍很近,也应该被强制保留为可走。没有这一步,窄走廊会先被膨胀封...
机器人路网是怎么实现的:从建图轨迹到可编辑图模型
路网看起来只是一张带节点和边的图,但真正难的地方不是画线,而是想清楚它和地图的关系、它怎么生成、怎么编辑、怎么和云端同步。这个项目把路网当成独立于地图的语义资产,核心判断只有一句话:地图回答“这里长什么样”,路网回答“可以怎么走”。 路网为什么不能塞进地图同一张图,巡逻路线可能今天改、明天加;同一条路网,底图也可能换一张重新扫描。如果把路网做成地图的一个字段,任何一次路线调整都会牵连地图资产。 所以项目把两者拆开: 地图资产 MapAsset 负责点云和定位。 路网资产 NetworkAsset 通过 map_refs 单向引用地图。 地图不知道谁在引用它。 消费路网时,坐标系必须取 primary 底图的 global_frame。如果拿 A 图的路网在 B 图上跑,节点坐标看起来正常,实际却是跨帧规划。因此 navigate 里加了帧守卫,导航图和定位当前图不一致时直接拒...
机器人点云渲染:从 RSAIRY 组播到 Three.js 浏览器
这台机器人的点云链路不是“厂商发一个 ROS 话题,前端直接订阅”。厂商的 Fast DDS 数据面和我们通用的 ROS2 客户端不互通,所以项目在传感器侧自己接雷达,在后端把点云打包成浏览器可读的数据,再在前端用 Three.js 画出来。整条链路分成三段,每一段都藏着一个容易踩的坑。 传感器侧:绕开厂商 DDS 自建 rslidar_sdkM20Pro 前后各有一颗 RSAIRY 雷达。厂商进程会把点云发到 /LIDAR/POINTS,但这个话题只在发现层可见,通用 ROS2 客户端读不到数据。项目没有继续和厂商 DDS 较劲,而是直接收雷达组播。 链路大致是这样: 前雷达组播 224.10.10.201,后雷达组播 224.10.10.202。 在 106 主机上编译标准 rslidar_sdk,用平台自己的 SHM DDS 环境运行。 输出到 /skill/pointc...
Java 后端常见坑:Spring 事务、异步与 MyBatis
框架帮我们少写了很多代码,也把一些错误悄悄藏了起来。Spring 事务和 MyBatis 动态 SQL 的坑,多数不是“不会用”,而是“看起来生效,实际没生效”。 Spring 事务同类自调用会绕过事务代理现象orderService.create() 调用了同一个类里的 saveOrder(),但 saveOrder() 抛异常后数据库没有回滚。 123456789101112@Servicepublic class OrderService { public void create(Order order) { saveOrder(order); } @Transactional public void saveOrder(Order order) { // 数据库操作 ...
Java 数值、字符串与时间:金额少一分和日期串一天怎么查
金额、字符串和日期都属于“看起来简单,出了错很难查”的类型。它们的坑通常藏在精度、正则语义、索引边界和时区这些细节里。 BigDecimal 与金额不要用 new BigDecimal(double)现象金额计算出现 0.30000000000000004 这类结果,或者对账时少一分钱。 123BigDecimal amount = new BigDecimal(0.1);System.out.println(amount);// 0.1000000000000000055511151231257827021181583404541015625 根因double 本身不能精确表示很多十进制小数。new BigDecimal(double) 会保留 double 的二进制近似值,所以精度并没有变好。 正确写法优先用字符串构造,或者用 BigDecimal.valueOf: 12B...
Java 并发与线程池的坑:任务失败、线程串号和 CPU 飙高
并发问题最麻烦的地方在于,它不一定每次都失败。很多代码在压测时能过,生产流量一大才暴露。这里整理的是我在后端系统里反复见到的线程池和共享状态问题。 线程池配置不要无脑用 Executors.newFixedThreadPool现象某个异步任务越来越多,服务开始频繁 Full GC,最后内存溢出。翻代码发现用的是: 1ExecutorService pool = Executors.newFixedThreadPool(200); 根因newFixedThreadPool 使用无界的 LinkedBlockingQueue。线程数最多 200,但任务队列没有上限。如果生产速度长期高于消费速度,任务会在队列里无限堆积,最终耗尽堆内存。 newCachedThreadPool 则相反,队列没有容量,空闲线程可回收,但线程数上限是 Integer.MAX_VALUE。请求一多就可能创建...
Java 集合与常用 API 的坑:从线上事故到正确写法
集合是最容易被“会用”两个字掩盖细节的部分。很多事故不是代码逻辑写得不对,而是对返回类型、重载规则、可变性和并发语义判断错了。这篇文章只记录我实际遇到或复盘过的坑。 不可变与可变集合Arrays.asList 不是一个普通 ArrayList现象下面的代码在本地跑得很顺,一上线就抛 UnsupportedOperationException: 12List<Integer> nums = Arrays.asList(1, 2, 3);nums.add(4); 根因Arrays.asList 返回的是 Arrays 内部的定长 ArrayList,它继承了 AbstractList,但没有实现 add、remove、clear 这些修改方法。调用它们时,会走 AbstractList 里直接抛异常的默认实现。 它允许 set 修改元素,但不允许改变列表长度。很多人只记...
架构笔记:Monorepo、微前端、SSR、PWA、监控与 DevOps
项目与架构设计关注经验是否可复用、可扩展、能落地,而不只是技术名词。本文整理 Monorepo、微前端、渲染模式、监控与 DevOps 实践。 应用架构MonorepoMonorepo 适合多应用、多包协作。关键能力是 workspace 管理、依赖约束、任务编排、缓存、版本发布和代码边界。 Monorepo 最大收益:跨包修改可以一次提交,复用工具链和组件更方便,依赖版本更统一。但要配合构建缓存和清晰边界,否则仓库会变慢变乱。 微前端微前端把大型前端拆成多个可独立开发、构建、部署的子应用。常见方案有 iframe、qiankun、Module Federation、Web Components。 微前端需要解决的隔离问题:样式隔离、JS 沙箱、路由隔离、状态通信、依赖冲突、公共资源加载和权限统一。 渲染与跨端SSR、SSG 与 CSRCSR 由浏览器渲染,交互灵活但首屏和 SE...
AI 笔记:Transformer、Prompt、RAG、Agent、MCP 与工程化
前端接入 AI 的重点不是训练大模型,而是理解 LLM 能力边界,并能把 AI 能力稳定接入产品。本文整理 Transformer、Prompt、RAG、Agent 与工程化实践。 大模型基础Transformer、Token 与 AttentionToken 是模型处理文本的基本单位,可能是字、词或词片段。Transformer 通过 Attention 建模上下文关系,让模型判断哪些 token 对当前生成更重要。 上下文窗口是模型一次能处理的 token 数量上限。超过窗口的内容不能全部被模型直接看到,需要摘要、检索或分段处理。 EmbeddingEmbedding 把文本、图片等内容转成向量,让语义相近的内容在向量空间里距离更近。RAG、推荐、聚类、相似搜索都常用 embedding。 与关键词搜索相比,Embedding 看语义相似而非字面匹配。比如「如何提升首屏速度」...
