当前位置: 首页 > news >正文

“慧视“导航功能开发博客 1:先把“能跑起来“做稳,再谈智能

这篇写的是导航功能的第一阶段。我一开始最想做的就是那种酷炫的导航页——地图上画条线,实时显示位置,最好还能语音播报。但实现的时候才发现,地图、定位、后端会话、实时推送这几块根本不是拼在一起就能跑的。我没有一个清晰的项目结构,也不知道数据该从哪流到哪。

所以第一阶段我强迫自己收回来,先不做花哨的东西,只做一件事:前端有页面,后端有接口,会话有状态,数据能来回跑。这听起来没什么技术含量,但我后来发现,后面所有功能——地图渲染、实时播报、偏航判断——能不能顺利接上,全看这一步拆得清不清楚。

一、导航功能为什么不能只写一个页面

最初我觉得导航页就是"输入目的地 → 地图画路线 → 开始导航",一个页面搞定。真动手之后才发现它至少得拆四层:

  1. 页面层:目的地输入、定位、状态显示、停止导航
  2. 业务层:启动导航、更新位置、偏航判断、到达判断
  3. 数据层:会话持久化、设置管理、路线和当前位置
  4. 实时层:WebSocket 推送,失败后要能降级到轮询

一开始我没拆,所有逻辑堆在navigation.js里,页面里到处都是 request 调用和 if-else 状态判断,改一个地方三个地方跟着崩。后来我花了一整个下午重构,把导航相关代码拆成了前端页面和后端模块两大块:

  • 前端:miniprogram/pages/navigation/navigation.*
  • 后端:routers/navigation.pyservices/navigation_service.pystate/navigation_store.pyschemas/navigation.py

拆完之后调试和写后续功能舒服多了,最大的变化是:我不用每次改一个状态判断就满页面找哪里还依赖了它。

二、导航页的第一版:先让状态可见

第一版的导航页长得很朴素,没有酷炫的地图效果,但我在每个位置都考虑了"用户怎么知道系统现在在干嘛"这个问题:

  • 顶部放返回按钮和标题
  • 搜索面板里放目的地输入框、定位按钮、当前位置文字、连接状态标签
  • 中间放导航提示区——"未开始导航"还是"导航中"还是"已偏航"
  • 下面才是地图组件
  • 最底部放路线信息和停止按钮

这些看起来是 UI 布局,但实际背后是一个更本质的问题:导航是一个持续状态机,不是一次性动作。如果页面上只有一个"开始导航"按钮,用户根本不知道系统是在定位、在规划路线、在连 WebSocket,还是已经在轮询了。我在真机上测试的时候就踩过这个坑:点完开始导航之后页面毫无反应,等了十秒路线才出来,中间用户完全不知道发生了什么。后来加上navigationStateconnectionHint这两个显示字段,体验立马不一样了。

三、JS 里的状态设计:把"系统在干嘛"变成数据

navigation.jsdata里,我花了不少时间设计状态字段。最终留下了这些:

destination — 用户输入的目的地 isNavigating — 是否处于导航中 navigationState — "未开始 / 导航中 / 已到达 / 已偏航" routeHint — 当前提示语 sessionId — 后端会话 id markers / polyline — 地图点位和路线 connectionMode — 实时通道状态(ws / polling / idle) wsConnected — WebSocket 是否连接

这里sessionId是一个容易忽略但特别重要的字段。一开始我没把它存到 data 里,而是用了一个局部变量,结果页面重新渲染之后会话 id 就丢了,导航状态再也查不回来。后来改成存在 data 里,配合onShow做状态恢复,才算解决这个问题。

这些字段不是为了"数据多",而是每个字段都对应一个用户能感知到的界面变化。navigationState变了,提示区的文字和颜色要跟着变;connectionMode变了,连接状态标签要更新;isNavigating变了,停止按钮的显示隐藏要切换。状态字段是视图的驱动力,不是附属品。

四、后端先做会话,不做地图

导航后端我第一个写的不是路线规划接口,而是会话管理。这个选择一开始看着有点反直觉——为什么不先把地图功能跑通再说?

因为导航不是一条静态数据。它是一个动态过程:用户会走,位置会变,路线要跟着更新,可能偏航,可能到达,也可能随时被手动停止。如果后端没有一个地方统一存这些变化中的信息,每来一个请求都得从零算起,逻辑会很散,也容易出不一致的 bug。

所以我在navigation_store.py里先定义了NavigationSession

@dataclass class NavigationSession: session_id: str origin_lat: float origin_lng: float destination_name: str destination_lat: float destination_lng: float mode: str = 'walk' is_navigating: bool = True current_lat: float = 0.0 current_lng: float = 0.0 current_instruction: str = '正在规划路线' is_off_route: bool = False arrived: bool = False current_step_index: int = 0 route_summary: Optional[RouteSummary] = None settings: NavigationSettings = field(default_factory=NavigationSettings) updated_at: int = field(default_factory=lambda: int(time.time()))

其中settings字段的设计是后来加的。一开始偏航阈值和到达阈值我是写死在代码里的,后来做偏航判断的时候发现不同场景需要的阈值差很多——校园里步行 15 米偏航就算多了,但空旷环境可能 30 米还算正常。于是我把它抽成了NavigationSettings,通过配置控制,默认值从环境变量读。

写完这个 dataclass 之后我意识到一件事:导航系统的核心不是地图,是状态管理。地图只是状态的展示层,状态才是导航的灵魂。这个认知转变对我后面的开发方向影响很大。

五、这一阶段留下的接口和还没做的事

到这一阶段结束,后端的接口骨架已经定了:

接口用途
POST /start创建会话 + 规划路线
POST /location上报位置 + 更新状态
GET /status查询当前导航状态
POST /stop停止导航

但还有不少没做完的东西:语音播报没接入导航流程,偏航只有检测没有恢复策略,UI 动效基本为零,多地图源切换也没做。我不觉得这些是缺点——项目本来就应该从骨架开始,现在至少有一个可以持续扩展的主干。

http://www.cnnetsun.cn/news/2063533.html

相关文章:

  • 基于大数据和马尔可夫链的工况合成算法源程序
  • 快速解锁图表数据:WebPlotDigitizer完整指南
  • Legacy-iOS-Kit深度解析:旧款iOS设备系统降级与性能优化的完整技术方案
  • STM32F103 SDIO驱动SD卡,从硬件飞线到软件延时,我踩过的那些坑(附完整代码)
  • Vue3 + Element-Plus 实战:手把手教你封装一个带清空功能的文件上传组件
  • 3步轻松掌握Ai2Psd:从AI到PSD的无损矢量转换终极指南
  • 在 Cursor 中使用 Claude 生态的 Skills
  • 别再只会用printf了!STM32串口发送字符串的两种实用方法对比(含源码)
  • 思源宋体CN终极指南:免费开源专业中文字体的完整解决方案
  • 第47篇:AI提示工程高级技巧——思维链、少样本学习与角色扮演(操作教程)
  • 别再傻傻分不清了!Node.js里module.exports和exports到底有啥区别?一个例子讲明白
  • 从Java全栈开发到技术面试实战:一次真实的对话
  • 别再问float的最大值了!手把手带你从IEEE 754标准推导出单精度浮点数的极限
  • 一文读懂免费 WiFi 陷阱,学会远离黑客窃密攻击
  • 别再写Flask了!用Gradio 5分钟给你的AI模型做个网页Demo(附ResNet18图像分类实战)
  • RuoYi-Vue 3.8.6 项目瘦身实战:不用Redis,改用ConcurrentHashMap做本地缓存(附完整代码)
  • Instant-NGP的哈希编码到底怎么工作的?用PyTorch代码带你一步步拆解
  • 避开这3个坑!用ROBOGUIDE做FANUC机器人离线编程的效率翻倍技巧
  • 完整配置指南:3步高效掌握DLSS Swapper游戏性能优化工具
  • AssetRipper高效数据存储架构:深入解析Unity资产提取工具的核心设计
  • 为什么92%的C项目不敢升级?2026规范成本陷阱识别图谱(含GCC 14.2/Clang 18.1兼容性速查表)
  • AXI4总线协议实战解析:从Lite、Full到Stream的芯片设计选型指南
  • SECO COM Express Type 6模块:工业级AI边缘计算解决方案
  • 别再只算成功率了!用二项分布检验,给你的Python用户留存分析加个‘显著性’Buff
  • 从手动保存到智能批量:抖音内容采集的技术突围之路
  • 手把手教你用VFR为UEFI BIOS定制一个漂亮的启动菜单界面
  • NVIDIA GB200 NVL72与Kubernetes多节点NVLink编排实战
  • CH344Q vs CH344L怎么选?一文讲透高速USB转多串口芯片的选型、配置与避坑指南
  • 3分钟快速掌握Chrome图片格式转换:右键一键保存PNG/JPG/WebP终极指南
  • 2026年主流文档生成工具大盘点:企业怎么选看这篇就够了