From 5da31a6c40dba965437c3d5dd4cd0e442ed106ba Mon Sep 17 00:00:00 2001 From: shenyuxiang Date: Fri, 31 Jul 2026 15:34:11 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=90=E5=88=B6=E5=8D=95=E8=BD=A6=E8=87=AA?= =?UTF-8?q?=E8=BD=AC=E8=A7=92=E9=80=9F=E5=BA=A6=E5=B9=B6=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E5=BA=95=E7=9B=98=E9=85=8D=E7=BD=AE=E4=B8=8E=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../obj/Debug/ClumsyPilot.AssemblyInfo.cs | 2 +- .../ClumsyPilot.AssemblyInfoInputs.cache | 2 +- ....GeneratedMSBuildEditorConfig.editorconfig | 2 +- .../obj/Debug/ClumsyPilot.assets.cache | Bin 1890 -> 1890 bytes ...ClumsyPilot.csproj.AssemblyReference.cache | Bin 68784 -> 73075 bytes MedullaAdapter/DiverCartDefinition.cs | 18 +- .../build/Medulla/plugins/MedullaAdapter.dll | Bin 71680 -> 71680 bytes .../build/Medulla/plugins/MedullaAdapter.pdb | Bin 34220 -> 34324 bytes README.md | 285 ++++++++++++------ README_en.md | 285 ++++++++++++------ chassis.json | 50 +++ 测试方案.txt | 5 +- 12 files changed, 453 insertions(+), 196 deletions(-) create mode 100644 chassis.json diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs index 5160759..4f4d0a5 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("ClumsyPilot")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+7e05ff098e34d47e777a6809a99952fdb24bf5a2")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")] [assembly: System.Reflection.AssemblyProductAttribute("ClumsyPilot")] [assembly: System.Reflection.AssemblyTitleAttribute("ClumsyPilot")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache index 1e9a110..8fb9fb2 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.AssemblyInfoInputs.cache @@ -1 +1 @@ -ad10c8964b21ff4923ef175481b5fc5b35f6275f95224074d0c26f781df45851 +5d77794fa0720c6591db5b06ac60427413c18989a6f7b64420ccb07d122d85bc diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig b/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig index 8ce14cc..a3aa451 100644 --- a/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig +++ b/ClumsyPilot/obj/Debug/ClumsyPilot.GeneratedMSBuildEditorConfig.editorconfig @@ -1,6 +1,6 @@ is_global = true build_property.RootNamespace = MultiWheelC -build_property.ProjectDir = D:\MyParking\ClumsyPilot\ +build_property.ProjectDir = D:\Users\Desktop\入职培训\停车机器人\MyParking\ClumsyPilot\ build_property.EnableComHosting = build_property.EnableGeneratedComInterfaceComImportInterop = build_property.CsWinRTUseWindowsUIXamlProjections = false diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.assets.cache index 2afc373a72dd7c4cc9ae9022b09c26509b095312..3d28e6fb1b5b420d1ca767798115b725bd6c3ced 100644 GIT binary patch delta 49 zcmV-10M7s74&n|dP)kQa3;+NC@HzeA-&3!0r8Q+hU=vEt*yPups$yDEymP>{bk|}j Hu_!tR4a*i6 delta 49 zcmV-10M7s74&n|dP)kQa3;+NCb>$CsqqYzfmhP&rJo2QHDNfQkvm^e&8ZC0{N#grl Hu_!tR=z$e2 diff --git a/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache b/ClumsyPilot/obj/Debug/ClumsyPilot.csproj.AssemblyReference.cache index 95684d222b9c01c41dea21480e9ee2e14423347d..2e310ac272b0d5354a49a5011ed65851ccf59f64 100644 GIT binary patch delta 3420 zcmcImUu+ab7{9rH{iB%HN^LBfBa{b?-D^`hv6z^8*9R+m9KDu;9&Lu+v@G4-x$N#0 zFT@}rK1pIO8zfCgs1FogN>E4|nh@W7(gzcK(1=eKFCqRRsEH4XGqZngxZT6v87JAv z?(Fw{^L@Yh&2Q%FQuzLQcvlpZ0)YU?r-pNrI@0u93h4_5F61`ezgRhSX5+$*%9YjJ z#;Nm_n=5zDuWu|}{$YLH909%MowA9~w)LlmKo}Yr8hizS$A$FhMAm?69%^|I zq*kOoup0<~sm&J^vZ_)NGjo!RhU4*g!*!Xrz~Kn!ASv*L_0gOjSr`CMpZlbpbicKO zPKE<>ao#xJtFO(R?EJcY*bNB)*g8Iz%m`VeNl?yU&Bz)Wf(k<;Oza#~s0(etC+y7h ziNfcX#Jlu=51Wp}-I9cwF*0jNi_pLt0A@MZMHlLM7KL_pRn80Xc}zt4qAbHC)=<@> zr)q1};&_-JhIcsYzne3n>p%9Se5U)G+dJH068?$oQK%JC2Ze)gsD+{dSbZd~oe^W#{Qll@ zru**d$L=t3@8;kWM&B`zs!Leat4P-Bfd@&8r;X{sp@#LK*PIDv6R=rLC`Fi<{Rce| zDQdL&ZCpP+c*bVXIGU3Y*}hm6L}b7`G+>nnF&2?_))ILFJ;a9?v!k75?cqZ?JxHaY z31UYb($ucESN{QcR+MHntm8RDNJ(&B#kxV*EsPgcLsAFf-e|N6{IXv)jMm|M2BpdPSIqJG;r zBl=34wdo!@u==e(Jlzi6T^dn zO=_MDZmGv#bklQJ4M$ZliT8p^@5ryLKRG*vXH~0 z$Ax_g!SeKWsy%!fG&XJj4sIQ6-)somoLI`hm$e0QUgtD4m*XxPLSB{`C%P|o{kZMt z?_29#L^_{x(tVwCH~#>8B7o`{kNE$6ql}6BCni*Kf2f|zf(TV|Z^|cS38~h_i}Ij_ zJZtn8W;eeD{Oi!#kqbg%Y?j(M`q5%f!Kkq5NVS0)JEVB&8F!Ph1jH*n%%IMe^kt1% P{$=tsj;`S-7>WJ^w_r)< delta 198 zcmeyoi)F)17A`i%3I+xSMoSl~$)^RRCkEtjJEmpkq+03g>jQ=Id8H@wGL}ycl@?&u zfhd_A%oN0Jf~MvhQ!H4G9$1as&A+X_WaZu3+@X-1HO$qs*mn~lV`8;LVIvH<{*?mBk> diff --git a/MedullaAdapter/DiverCartDefinition.cs b/MedullaAdapter/DiverCartDefinition.cs index f78a75b..67c4f6e 100644 --- a/MedullaAdapter/DiverCartDefinition.cs +++ b/MedullaAdapter/DiverCartDefinition.cs @@ -70,6 +70,8 @@ namespace MedullaAdapter [AsInitParam(desc = "手动控制夹臂速度系数")] public float ManualArmSpeedFac = 1.0f; [AsInitParam(desc = "遥控转弯舵角同步限速宽度,单位为度")] public float ManualSteeringAlignmentSigmaDegrees = 8.0f; + [AsInitParam(desc = "自转最大角速度,单位deg/s")] + public float MaxSpinAngularSpeedDegreesPerSecond = 30f; [AsInitParam(desc = "轮速诊断日志相对目录")] public string WheelSpeedDiagnosticDirectory = @"logs\wheel-speed"; @@ -335,10 +337,24 @@ namespace MedullaAdapter // 自转时speed表示最外侧舵轮中心的目标切向速度, // 根据v=omega*r换算为SendXYThSpeed需要的角速度。 - var spinOmegaRadiansPerSecond = + var requestedSpinOmegaRadiansPerSecond = speed / adapter.MaximumWheelRadiusMeters; + // 对半径换算结果做正负对称限幅,防止遥控速度参数误设后自转过快。 + var maximumSpinOmegaRadiansPerSecond = + Math.Max( + 0f, + MaxSpinAngularSpeedDegreesPerSecond) * + Math.PI / 180.0; + + var spinOmegaRadiansPerSecond = + Math.Max( + -maximumSpinOmegaRadiansPerSecond, + Math.Min( + maximumSpinOmegaRadiansPerSecond, + requestedSpinOmegaRadiansPerSecond)); + // 普通安全版SendXYThSpeed只下发角速度, // 四轮实际舵角未到位时不会开放驱动速度。 if (!adapter.Send( diff --git a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll index ac14237a8c7a905551f65f25a5ea7a83e6df49e3..c6d3e08cbd81560099155d5e69afc61f08fb9247 100644 GIT binary patch delta 16054 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 UIK=O=G^_VEyHk8G8gh*P0}AMPu>b%7 diff --git a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.pdb b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.pdb index 500cf0cdf910d59b3c399a68f4e9a537d1cffc21..89e8e0c581228fd44d91e181b28aad1ddb9bd47d 100644 GIT binary patch delta 4465 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 diff --git a/README.md b/README.md index a34ae9b..65cc54c 100644 --- a/README.md +++ b/README.md @@ -2,167 +2,262 @@ [简体中文](README.md) | [English](README_en.md) -## 重写说明 +## 重写路线与当前状态 -本仓库是停车机器人控制软件的重写版本。当前不以一次性恢复全部旧功能为目标,而是按以下顺序重新建立可验证、可维护的能力: +本仓库是停车机器人控制软件的重写版本,研发顺序保持为: 1. 先实现单台停车机器人小车的基本功能; 2. 在单车闭环稳定后逐步增加停车作业功能; -3. 再优化轨迹跟踪方法及其稳定性; -4. 最后评估并实现多车通信、编队与协同控制。 +3. 基于仿真、台架和实车数据优化轨迹跟踪方法; +4. 最后再考虑多车通信、编队和协同控制。 -**当前处于第 1 阶段,开发重点是单车基本功能。** `PilotConfig.cs` 中由 `#if false` 包围的钻车、夹抱和多车参数仅作为历史代码或设计参考,不参与当前编译,也不表示相关功能已经可用。 +当前工作仍以**单车**为主,已经从基础框架搭建进入底盘联调、功能补充和跟踪实验阶段。多车配置仍位于 `PilotConfig.cs` 的 `#if false` 区域,`Shared/FleetKinematics.cs` 仍是占位文件,不能视为多车能力已经实现。 + +| 阶段 | 当前状态 | 说明 | +| --- | --- | --- | +| 1. 单车基本功能 | 联调中 | 已接入运动控制、MCU 通信、轮组反馈、急停 IO、电池、灯光、遥控和诊断代码,仍需持续实车验证 | +| 2. 增加停车功能 | 部分开展 | 已提供夹臂控制、限位、报警和测试入口;轮胎识别、钻车和完整停车流程尚未实现 | +| 3. 优化跟踪方法 | 已启动 | 已加入直线、圆弧、S 型、蟹行测试、实验 CSV 记录和 Python 绘图工具 | +| 4. 多车场景 | 暂不实施 | 多车参数和预研内容未参与当前编译,当前版本不提供多车联动 | ## 项目简介 -MyParking 是一个面向多轮停车机器人底盘的 C# 控制工程。仓库包含上层运动控制插件 `ClumsyPilot` 和下层硬件适配插件 `MedullaAdapter`,用于建立从单车运动指令到 MCU 串口桥、CAN/串口端口的基础链路。 +MyParking 是一个面向多轮停车机器人底盘的 C# 工程,覆盖上层运动动作、共享运动学、底层硬件适配、离线 Web 仿真和实验数据分析。 -当前代码已经包含单车终点直线跟踪、前进/后退测试、PID 原地旋转、停止保护,以及 MCU 串口桥的托管封装和初始化流程。完整停车作业所需的驱动器协议、反馈解析、安全报警、夹抱执行和感知流程仍待实现或接入。 +核心代码分为: -## 当前范围 +- `ClumsyPilot`:Clumsy 上层动作、轨迹跟踪和人工测试; +- `MedullaAdapter`:Medulla 下层 MCU、CAN、串口、轮组、夹臂、遥控和报警适配; +- `Shared`:统一的二维坐标、底盘命令、坐标变换和多轮底盘适配; +- `CommonUsage-MultiVehicleSync/commonusage`:仓库内的 `CommonUsage` 底盘公共库源码; +- `Simulation`:基于 ASP.NET Core 的单车 Web 仿真器; +- `data_process`:轨迹实验 CSV 的 Python 分析工具。 -| 范围 | 状态 | 说明 | -| --- | --- | --- | -| 单车几何控制器 | 已接入 | 根据公共配置创建 `MultiWheelGeometricController` | -| 单车终点跟踪 | 已实现基础版本 | 使用直线路径,可测试前进和后退,到达或退出时发送零速度 | -| 单车原地旋转 | 已实现基础版本 | 读取定位朝向并通过 PID 输出角速度,到位后停车 | -| MCU 串口桥 | 已封装 | 支持打开、复位、状态/版本查询、端口配置、IO、串口与 CAN 收发/回调 | -| MCU 初始化 | 已实现基础流程 | 默认使用 `COM4`、1 路 CAN 和 3 路串口配置 | -| 驱动反馈与安全链路 | 待实现 | 驱动协议、轮速/舵角反馈、电池、急停和报警例程目前没有实际逻辑 | -| 停车作业功能 | 待实现 | 钻车、轮胎识别、夹抱等旧参数当前被条件编译禁用 | -| 多车能力 | 暂不实施 | 多车参数当前被条件编译禁用,待单车及跟踪能力稳定后再设计 | +仓库中没有 ROS/ROS 2 或 Docker 配置。 -## 软件结构 +## 当前已接入能力 + +| 模块 | 当前代码能力 | +| --- | --- | +| 单车运动 | 直线、圆弧、S 型轨迹,前进、蟹行和原地旋转 | +| 底盘命令 | `SendMotion`、`SendXYThSpeed` 和虚拟阿克曼测试后端 | +| 模式切换 | 正常、蟹行、自转模式;切换时先停车、预转舵轮并等待到位 | +| 跟踪控制 | 终点跟踪、直线跟踪、基于 Detour 的直线跟踪和蟹行运动坐标系跟踪 | +| 夹臂 | 左右夹臂速度命令、位置反馈、软限位、驱动报警、实体/虚拟遥控和目标位置动作 | +| MCU 通信 | 串口桥打开、复位、版本/状态查询、数字 IO、CAN/串口同步收发和异步回调 | +| 驱动与反馈 | 8 个驱动电机和 4 个舵轮的命令、速度/位置/舵角反馈及远程帧状态 | +| 车辆状态 | 急停、启停、抱闸、灯光、电池 SOC/SOH 和驱动使能状态 | +| 诊断 | CAN 轮速事件与周期快照 CSV、轨迹实验 CSV、控制命令和 Detour 位姿记录 | +| 仿真 | 浏览器二维车辆显示、模式按钮、手动控制、车辆配置、复位和 REST API | + +以上表示代码和测试入口已经存在,不等同于所有工况均已完成实车验收。 + +## 软件架构 ```text -上层 Clumsy 运行环境 - │ - ▼ -ClumsyPilot:单车动作、轨迹跟踪、测试入口 - │ 底盘速度指令 - ▼ -Medulla 运行环境 / MedullaAdapter - │ P/Invoke - ▼ -mcu_serial_bridge.dll → MCU → CAN / Serial / Digital IO +Clumsy 宿主 + │ + ▼ +ClumsyPilot ───────────────┐ + │ │ + ▼ │ 实验 CSV +Shared / CommonUsage ├──────────► data_process + │ │ + ▼ │ +Medulla 宿主 │ + │ │ + ▼ │ +MedullaAdapter │ + │ P/Invoke │ + ▼ │ +mcu_serial_bridge.dll │ + │ │ + ▼ │ +MCU ─► CAN / Serial / IO ──┘ + +Simulation ─► Shared 数据类型 ─► 浏览器仿真界面 ``` -两个工程均生成类库,仓库中没有独立的可执行入口: - -- `ClumsyPilot`:上层单车运动控制,目标框架为 .NET Standard 2.0; -- `MedullaAdapter`:下层 MCU 和底盘适配,目标框架为 .NET 8.0。 +`ClumsyPilot` 和 `MedullaAdapter` 生成插件类库,需要由对应宿主加载;`Simulation` 是可以独立启动的 ASP.NET Core Web 项目。 ## 目录说明 ```text MyParking/ -├── ParkingRobot.sln # Visual Studio 解决方案 -├── ClumsyPilot/ -│ ├── AGV.cs # 上层 AGV 接口 -│ ├── ChassisController.cs # 单车几何控制器配置 -│ ├── Movements.cs # 终点跟踪、等待、原地旋转动作 -│ ├── MovementTests.cs # Clumsy 环境中的人工动作测试 -│ ├── PilotConfig.cs # 当前单车配置及禁用的历史/预研配置 -│ ├── PilotDefinition.cs # 车型尺寸和车号定义 -│ └── ref/ # 上层框架引用程序集 -└── MedullaAdapter/ - ├── DiverCartDefinition.cs # 车型 IO、监控字段及 MCU 初始化 - ├── MCUSerialBridgeCLR.cs # 原生 MCU 串口桥的 C# 封装 - ├── MCUSerialBridgeError.cs # 错误码与诊断说明 - ├── AlarmRoutine.cs # 安全报警例程占位 - ├── MCURoutine.cs # MCU IO/反馈例程占位 - ├── MotorRoutine.cs # 电机控制例程占位 - ├── Remote.cs # 遥控例程占位 - └── ref/ # 下层框架引用程序集 +├── ParkingRobot.sln +├── ClumsyPilot/ # 上层动作、跟踪、测试和实验记录 +├── MedullaAdapter/ # MCU、CAN、轮组、夹臂、遥控和报警 +├── Shared/ # 共享命令、坐标变换和底盘适配 +├── CommonUsage-MultiVehicleSync/ +│ └── commonusage/ # CommonUsage 公共底盘库源码 +├── Simulation/ # .NET 8 Web 仿真器 +│ ├── Commands/ # 可由特性自动发现的仿真动作 +│ ├── Core/ # 仿真车辆、舵轮、时钟和世界 +│ ├── Models/ # Web API DTO +│ └── wwwroot/ # 浏览器界面 +├── data_process/ # Python 实验绘图脚本 +├── ref/ # 两个插件共同使用的 CommonUsage.dll +├── 测试方案.txt # 单车轨迹实验方案 +├── 记录.txt # 项目调试记录 +└── 电机记录.txt # 电机调试记录 ``` +根目录的 `ParkingRobot.sln` 当前只包含 `ClumsyPilot` 和 `MedullaAdapter`;`CommonUsage` 与 `Simulation` 需要分别构建。 + ## 开发环境与依赖 -- Windows 开发/运行环境;当前硬件接入使用 COM 端口和原生 DLL; -- Visual Studio 2022,或能够构建 .NET 8.0 与 .NET Standard 2.0 项目的 .NET SDK; -- NuGet 包:`Newtonsoft.Json 13.0.3`、`System.Numerics.Vectors 4.6.1`; -- `ClumsyPilot/ref` 和 `MedullaAdapter/ref` 中的内部框架程序集; -- 实机运行所需的 `mcu_serial_bridge.dll`;该文件当前未包含在仓库中; -- 能够加载 `ClumsyPilot.dll` 与 `MedullaAdapter.dll` 的 Clumsy/Medulla 宿主环境;宿主程序和部署配置当前未包含在仓库中。 +- Windows 开发/实机运行环境; +- Visual Studio 2022,或支持 .NET 8.0 和 .NET Standard 2.0 的 .NET SDK; +- Python 环境,用于可选的实验数据绘图; +- Clumsy/Medulla 内部框架程序集,位于各项目的 `ref` 目录; +- 实机所需的 `mcu_serial_bridge.dll`,当前仓库中未包含该文件; +- 能够加载 `ClumsyPilot.dll` 和 `MedullaAdapter.dll` 的匹配版本宿主程序,当前仓库中未包含宿主。 -仓库中未发现 ROS/ROS 2、Docker 或独立仿真启动配置。 +主要 NuGet/Python 依赖: + +- `ClumsyPilot`:`Newtonsoft.Json 13.0.3`、`System.Numerics.Vectors 4.6.1`; +- `CommonUsage`:`MQTTnet 4.3.7.1207`、`Newtonsoft.Json 13.0.3` 等; +- `data_process`:NumPy、pandas、Matplotlib、SciPy。 ## 编译 -在仓库根目录执行: +### 1. 构建 CommonUsage + +修改公共底盘库后,先执行: + +```powershell +dotnet restore CommonUsage-MultiVehicleSync\commonusage\CommonUsage.csproj +dotnet build CommonUsage-MultiVehicleSync\commonusage\CommonUsage.csproj -c Debug +``` + +该项目的构建目标会把生成的 `CommonUsage.dll` 复制到根目录 `ref`。 + +### 2. 构建实车插件 ```powershell dotnet restore ParkingRobot.sln dotnet build ParkingRobot.sln -c Debug ``` -主要输出位置: +主要输出: ```text ClumsyPilot/build/Clumsy/ClumsyPilot.dll MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll ``` -当前源码已通过解决方案编译。现有警告为 `DiverCartDefinition.TransmitterLastTime` 尚未赋值,不影响程序集生成。 +### 3. 构建 Web 仿真器 -## 运行与配置 +```powershell +dotnet restore Simulation\MyParking.Simulation.csproj +dotnet build Simulation\MyParking.Simulation.csproj -c Debug +``` -本仓库只生成插件类库,不能通过 `dotnet run` 独立启动。需要由匹配版本的 Clumsy/Medulla 宿主加载上述程序集。具体宿主版本、目录复制方式、配置文件位置和启动命令尚未随仓库提供,待补充。 +## 启动 Web 仿真 -当前能够从代码确认的 MCU 默认初始化参数如下: +```powershell +dotnet run --project Simulation\MyParking.Simulation.csproj --launch-profile http +``` + +浏览器访问: + +```text +http://localhost:5203 +``` + +仿真界面提供正常、左蟹行、右蟹行、自转、前进、后退、左转、右转、停止和复位动作,并可修改车辆布局及手动控制输入。主要 API 包括: + +- `GET /api/vehicles` +- `GET /api/actions` +- `GET/POST /api/configuration` +- `POST /api/vehicles/{vehicleId}/commands/{command}` +- `POST /api/vehicles/{vehicleId}/manual-control` +- `POST /api/reset` + +`Simulation/Commands/MySimulationTests.cs` 给出了自定义仿真动作示例;为静态方法添加 `SimulationAction` 特性后,调度器会自动发现并在网页生成对应动作。 + +## 实车运行与 MCU 配置 + +实车插件不能通过 `dotnet run` 独立启动。需要由匹配版本的 Clumsy/Medulla 宿主加载两个 DLL。宿主版本、部署目录和完整启动步骤尚未随仓库提供,待补充。 + +当前源码中的 MCU 默认参数: | 参数 | 默认值 | | --- | --- | | MCU 端口 | `COM4` | | MCU 连接波特率 | `1000000` | -| CAN 通道 | 1 路,`500000 bit/s`,重试时间 `10 ms` | -| 串口通道 | 3 路,`9600 bit/s`,接收帧时间 `10 ms` | +| CAN | 1 路,`500000 bit/s`,重试时间 `10 ms` | +| 串口 | 3 路,`9600 bit/s`,接收帧时间 `10 ms` | +| 电池通信端口索引 | `3` | +| 自转最大角速度 | `30 deg/s` | +| 轮速诊断目录 | `logs\wheel-speed` | -实机启动前应在宿主参数界面或对应配置中确认端口和硬件参数。首次调试建议架空驱动轮或使用安全测试区域,并准备可靠的急停手段;当前安全报警与急停反馈逻辑尚未完成,不能将软件停车作为唯一安全措施。 +当前工作区存在 `chassis.json` 底盘参数样例,但源码中尚未发现自动加载该文件的入口;实车参数仍应以宿主实际配置为准。 -## 单车功能验证 +实机测试前必须确认端口、车号、舵轮零位与限位、速度单位、驱动方向、夹臂限位和急停链路。建议先架空驱动轮或在隔离区域低速测试,并保留独立可靠的物理急停,不能只依赖软件停车。 -`MovementTests.cs` 向 Clumsy 测试界面注册了以下人工测试: +## 单车测试入口 -- `测试终点跟踪动作-前进`:选取起点和终点后执行前向直线跟踪; -- `测试终点跟踪动作-后退`:以 180° 车身方向偏置执行后退跟踪; -- `底盘旋转测试`:输入世界坐标系目标角度后执行 PID 原地旋转。 +`ClumsyPilot/MovementTests.cs` 当前注册: -这些是宿主环境内的动作测试,并非 `dotnet test` 自动化测试。实机验证前需要先确认定位数据、底盘速度接口、舵轮方向、速度单位和急停链路。 +- `准备:四个舵轮与车头方向一致` +- `SendMotion:连续前进4m` +- `SendXYThSpeed:原地自转90°` +- `SendXYThSpeed:原地自转180°` +- `SendMotion:左转90°半径2m圆弧` +- `SendMotion:蟹行直线4m` +- `SendMotion:蟹行左转90°半径2m圆弧` +- `SendMotion:4m S型曲线` +- `夹臂关闭测试` +- `夹臂启动测试` -## 开发路线 +这些测试由 Clumsy 宿主的测试界面执行,并不是 `dotnet test` 自动化测试。运动测试会按配置记录实验编号、参考轨迹、Detour 位姿和控制命令。 -### 阶段 1:单车基本功能(当前) +## 实验数据分析 -- 打通上层动作、底盘控制、Medulla 适配和 MCU 通信链路; -- 完成单车启停、直线前进/后退、原地旋转和停止保护; -- 补齐驱动器命令、轮速与舵角反馈、IO、电池、急停和报警处理; -- 建立可重复的仿真/台架/实车验证方法。 +轨迹记录器默认把 CSV 保存到宿主程序目录下的: -### 阶段 2:增加停车作业功能 +```text +TrackingExperiments/ +``` -- 在单车基础控制稳定后,逐项接入遥控、感知、钻车、夹抱和退出车辆等功能; -- 每项功能分别完成参数定义、异常处理和实车验证,不直接启用旧的禁用代码。 +Medulla 的轮速诊断可通过 `StartWheelSpeedDiagnostic` / `StopWheelSpeedDiagnostic` 操作按钮控制,默认输出到: -### 阶段 3:优化跟踪方法 +```text +logs/wheel-speed/ +``` -- 根据单车测试数据改进路径跟踪、速度规划、转向控制和到位判定; -- 完善曲线、倒车、低速近目标等工况,并补充可复现的回归测试; -- 在安全性、稳定性和可诊断性达到要求后冻结单车接口。 +在自行管理的 Python 环境中安装依赖: -### 阶段 4:考虑多车场景 +```powershell +python -m pip install -r data_process\requirements.txt +``` -- 在单车接口稳定的前提下设计车辆身份、通信、心跳、超时和失联降级; -- 再实现编队、同步动作、车间位姿校正和多车安全策略; -- 多车预研参数需要重新评审,不以当前 `#if false` 代码作为完成依据。 +对一份或多份轨迹 CSV 同时生成轨迹对比、跟踪误差、速度响应和角速度命令图: + +```powershell +python data_process\run_all_plots.py "路径\实验1.csv" "路径\实验2.csv" --output-dir "路径\plots" +``` + +不传 CSV 路径时,脚本会查找 `data_process` 目录中的 CSV。默认重采样频率为 `20 Hz`,滤波窗口为 `0.55 s`,可通过 `--frequency` 和 `--window` 调整。 + +## 尚未完成或需要继续验证 + +- 雷达点云、轮胎识别、自动钻车、车辆释放和完整停车作业状态机; +- 当前运动和夹臂功能的完整实车验收、故障注入及长期稳定性测试; +- 舵轮软限位预测和自动车身重定向;`SteeringConstraintManager.cs` 当前主要是设计记录; +- 自动化单元测试和持续集成; +- 多车通信、编队、同步和安全降级;`FleetKinematics.cs` 当前仅为占位; +- 宿主版本、插件部署目录、配置文件位置和发布流程。 ## 参与开发 -1. 修改前确认所属阶段,当前提交优先服务于单车基本功能; -2. 保持 `ClumsyPilot` 与 `MedullaAdapter` 的职责边界,避免在上层动作中直接实现硬件协议; -3. 新增硬件参数时注明单位、默认值、适用车型和安全范围; -4. 提交前至少执行 `dotnet build ParkingRobot.sln`,并记录宿主测试或实车测试条件; -5. 分支、代码评审和发布流程待项目团队补充。 +1. 当前改动优先服务于单车闭环、停车功能和跟踪质量,不提前启用多车代码; +2. 保持上层动作、共享运动学、底层硬件协议和仿真模块的边界; +3. 新增参数时注明坐标系、单位、默认值、车型和安全范围; +4. 提交前构建受影响的项目,并记录仿真、台架或实车验证条件; +5. 修改 `CommonUsage` 后同步更新根目录 `ref/CommonUsage.dll`; +6. 分支、评审和发布流程待团队补充。 ## 许可证 diff --git a/README_en.md b/README_en.md index fb63642..569b7a8 100644 --- a/README_en.md +++ b/README_en.md @@ -2,167 +2,262 @@ [简体中文](README.md) | [English](README_en.md) -## Rewrite Notice +## Rewrite Roadmap and Current Status -This repository is a rewrite of the parking-robot control software. The goal is not to restore every legacy feature at once. Development follows this sequence: +This repository is a rewrite of the parking-robot control software. Development follows this order: 1. Implement the basic functions of one parking robot first; 2. Add parking-operation features after the single-robot loop is stable; -3. Improve the tracking method and its robustness; -4. Evaluate and implement multi-robot communication, formation, and coordination last. +3. Improve tracking with simulation, bench, and physical-vehicle data; +4. Consider multi-robot communication, formation, and coordination last. -**The project is currently in Stage 1 and focuses on basic single-robot functions.** The vehicle-entry, clamping, and multi-robot parameters enclosed by `#if false` in `PilotConfig.cs` are retained only as legacy or design references. They are excluded from the current build and do not indicate available features. +The current work remains focused on the **single robot** and has progressed from framework construction to chassis integration, feature development, and tracking experiments. Multi-robot settings remain inside the `#if false` section of `PilotConfig.cs`, while `Shared/FleetKinematics.cs` is still a placeholder. These files do not represent an implemented multi-robot system. + +| Stage | Current status | Notes | +| --- | --- | --- | +| 1. Basic single-robot functions | Integration in progress | Motion control, MCU communication, wheel feedback, emergency-stop I/O, battery, lights, remote control, and diagnostics are connected in code; physical validation is ongoing | +| 2. Add parking functions | Partially started | Clamp control, limits, alarms, and test entries exist; tire recognition, vehicle entry, and the complete parking workflow are not implemented | +| 3. Improve tracking | Started | Straight, arc, S-curve, and crab tests, experiment CSV recording, and Python plotting tools are available | +| 4. Multi-robot scenarios | Deferred | Multi-robot R&D settings are excluded from the build, and the current version provides no fleet coordination | ## Overview -MyParking is a C# control project for a multi-wheel parking-robot chassis. It contains an upper-layer motion-control plugin, `ClumsyPilot`, and a lower-layer hardware adapter, `MedullaAdapter`. Together, they establish the basic path from single-robot motion commands to an MCU serial bridge and its CAN, serial, and digital-I/O ports. +MyParking is a C# project for a multi-wheel parking-robot chassis. It covers upper-layer actions, shared kinematics, lower-layer hardware adaptation, an offline Web simulator, and experiment-data analysis. -The current code includes basic straight-line destination tracking, forward and reverse tests, PID-based in-place rotation, stop-on-exit handling, a managed wrapper for the MCU bridge, and its initialization sequence. Driver protocols, feedback parsing, safety alarms, clamping actuators, perception, and the complete parking workflow still need to be implemented or integrated. +The main components are: -## Current Scope +- `ClumsyPilot`: Clumsy actions, tracking, and manual tests; +- `MedullaAdapter`: Medulla MCU, CAN, serial, wheel, clamp, remote-control, and alarm adaptation; +- `Shared`: common 2D coordinates, chassis commands, frame transforms, and multi-wheel adaptation; +- `CommonUsage-MultiVehicleSync/commonusage`: in-repository source for the `CommonUsage` chassis library; +- `Simulation`: an ASP.NET Core single-robot Web simulator; +- `data_process`: Python tools for tracking-experiment CSV files. -| Area | Status | Notes | -| --- | --- | --- | -| Single-robot geometric controller | Integrated | Creates a `MultiWheelGeometricController` from shared configuration | -| Destination tracking | Basic version implemented | Tracks a straight path forward or backward and sends zero speed when finished or interrupted | -| In-place rotation | Basic version implemented | Reads the localization heading and produces angular speed through a PID controller | -| MCU serial bridge | Wrapped | Supports open/reset, state/version queries, port configuration, I/O, serial, CAN, and callbacks | -| MCU initialization | Basic flow implemented | Defaults to `COM4`, one CAN channel, and three serial channels | -| Driver feedback and safety chain | To be implemented | Driver protocol, wheel/steering feedback, battery, emergency-stop, and alarm routines contain no operational logic yet | -| Parking-operation features | To be implemented | Vehicle entry, tire recognition, and clamping parameters are currently excluded by conditional compilation | -| Multi-robot features | Deferred | Multi-robot parameters are excluded and will be reconsidered after single-robot tracking is stable | +No ROS/ROS 2 or Docker configuration is present. -## Software Structure +## Currently Integrated Capabilities + +| Module | Current code capability | +| --- | --- | +| Single-robot motion | Straight, arc, and S-curve paths; forward, crab, and in-place rotation | +| Chassis commands | `SendMotion`, `SendXYThSpeed`, and a virtual-Ackermann test backend | +| Mode switching | Normal, crab, and spin modes; stop, pre-steer, and wait for wheel alignment before motion | +| Tracking | Destination tracking, line tracking, Detour-based line tracking, and crab motion-frame tracking | +| Clamp | Left/right speed commands, position feedback, soft limits, driver alarms, physical/virtual remote control, and target-position actions | +| MCU communication | Bridge open/reset, version/state queries, digital I/O, synchronous serial/CAN access, and asynchronous callbacks | +| Drive and feedback | Commands and speed/position/steering feedback for eight drive motors and four steer modules, plus remote-frame state | +| Vehicle state | Emergency stop, start/stop, brake, lights, battery SOC/SOH, and drive-enable state | +| Diagnostics | CAN wheel-speed events, periodic snapshot CSVs, tracking CSVs, command recording, and Detour pose recording | +| Simulation | Browser-based 2D display, mode actions, manual control, vehicle configuration, reset, and REST APIs | + +The presence of code and test entries does not mean every operating condition has passed physical acceptance testing. + +## Software Architecture ```text -Upper-layer Clumsy runtime - │ - ▼ -ClumsyPilot: single-robot actions, tracking, and test entries - │ chassis velocity commands - ▼ -Medulla runtime / MedullaAdapter - │ P/Invoke - ▼ -mcu_serial_bridge.dll → MCU → CAN / Serial / Digital IO +Clumsy host + │ + ▼ +ClumsyPilot ───────────────┐ + │ │ + ▼ │ experiment CSV +Shared / CommonUsage ├──────────► data_process + │ │ + ▼ │ +Medulla host │ + │ │ + ▼ │ +MedullaAdapter │ + │ P/Invoke │ + ▼ │ +mcu_serial_bridge.dll │ + │ │ + ▼ │ +MCU ─► CAN / Serial / IO ──┘ + +Simulation ─► Shared data types ─► browser simulator ``` -Both projects build as libraries; this repository contains no standalone executable entry point: - -- `ClumsyPilot`: upper-layer single-robot motion control targeting .NET Standard 2.0; -- `MedullaAdapter`: lower-layer MCU and chassis adapter targeting .NET 8.0. +`ClumsyPilot` and `MedullaAdapter` build as plugin libraries that require their respective hosts. `Simulation` is an independently runnable ASP.NET Core Web project. ## Repository Layout ```text MyParking/ -├── ParkingRobot.sln # Visual Studio solution -├── ClumsyPilot/ -│ ├── AGV.cs # Upper-layer AGV interface -│ ├── ChassisController.cs # Single-robot geometric-controller setup -│ ├── Movements.cs # Destination tracking, delay, and rotation actions -│ ├── MovementTests.cs # Manual action tests in the Clumsy runtime -│ ├── PilotConfig.cs # Active single-robot and disabled legacy/R&D settings -│ ├── PilotDefinition.cs # Vehicle dimensions and vehicle-number definition -│ └── ref/ # Upper-layer framework assemblies -└── MedullaAdapter/ - ├── DiverCartDefinition.cs # Vehicle I/O, monitoring fields, and MCU initialization - ├── MCUSerialBridgeCLR.cs # C# wrapper for the native MCU serial bridge - ├── MCUSerialBridgeError.cs # Error codes and diagnostic descriptions - ├── AlarmRoutine.cs # Placeholder for safety and alarm routines - ├── MCURoutine.cs # Placeholder for MCU I/O and feedback routines - ├── MotorRoutine.cs # Placeholder for motor-control routines - ├── Remote.cs # Placeholder for remote-control routines - └── ref/ # Lower-layer framework assemblies +├── ParkingRobot.sln +├── ClumsyPilot/ # Upper-layer actions, tracking, tests, and recording +├── MedullaAdapter/ # MCU, CAN, wheel, clamp, remote, and alarms +├── Shared/ # Shared commands, frame transforms, and chassis adapter +├── CommonUsage-MultiVehicleSync/ +│ └── commonusage/ # CommonUsage chassis-library source +├── Simulation/ # .NET 8 Web simulator +│ ├── Commands/ # Attribute-discovered simulation actions +│ ├── Core/ # Vehicles, steer wheels, clock, and world +│ ├── Models/ # Web API DTOs +│ └── wwwroot/ # Browser UI +├── data_process/ # Python experiment-plotting scripts +├── ref/ # CommonUsage.dll shared by both plugins +├── 测试方案.txt # Single-robot tracking experiment plan +├── 记录.txt # Project debugging notes +└── 电机记录.txt # Motor debugging notes ``` +The root `ParkingRobot.sln` currently contains only `ClumsyPilot` and `MedullaAdapter`. Build `CommonUsage` and `Simulation` separately. + ## Development Environment and Dependencies -- Windows development/runtime environment; current hardware access uses a COM port and a native DLL; -- Visual Studio 2022, or a .NET SDK capable of building .NET 8.0 and .NET Standard 2.0 projects; -- NuGet packages: `Newtonsoft.Json 13.0.3` and `System.Numerics.Vectors 4.6.1`; -- Internal framework assemblies under `ClumsyPilot/ref` and `MedullaAdapter/ref`; -- `mcu_serial_bridge.dll` for physical-hardware operation; it is not currently included in this repository; -- A compatible Clumsy/Medulla host capable of loading `ClumsyPilot.dll` and `MedullaAdapter.dll`. The host application and deployment configuration are not included. +- Windows development and physical-runtime environment; +- Visual Studio 2022, or a .NET SDK supporting .NET 8.0 and .NET Standard 2.0; +- A Python environment for optional experiment plotting; +- Internal Clumsy/Medulla framework assemblies under each project's `ref` directory; +- `mcu_serial_bridge.dll` for physical operation; this file is not currently in the repository; +- Compatible hosts capable of loading `ClumsyPilot.dll` and `MedullaAdapter.dll`; the hosts are not included. -No ROS/ROS 2, Docker, or standalone simulation launch configuration was found in the repository. +Primary NuGet/Python dependencies: + +- `ClumsyPilot`: `Newtonsoft.Json 13.0.3` and `System.Numerics.Vectors 4.6.1`; +- `CommonUsage`: `MQTTnet 4.3.7.1207`, `Newtonsoft.Json 13.0.3`, and related packages; +- `data_process`: NumPy, pandas, Matplotlib, and SciPy. ## Build -Run from the repository root: +### 1. Build CommonUsage + +After changing the common chassis library, run: + +```powershell +dotnet restore CommonUsage-MultiVehicleSync\commonusage\CommonUsage.csproj +dotnet build CommonUsage-MultiVehicleSync\commonusage\CommonUsage.csproj -c Debug +``` + +The project includes a build target that copies the generated `CommonUsage.dll` to the root `ref` directory. + +### 2. Build Physical-Robot Plugins ```powershell dotnet restore ParkingRobot.sln dotnet build ParkingRobot.sln -c Debug ``` -Primary output locations: +Primary outputs: ```text ClumsyPilot/build/Clumsy/ClumsyPilot.dll MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll ``` -The current source builds successfully. The remaining warning reports that `DiverCartDefinition.TransmitterLastTime` is never assigned; it does not prevent assembly generation. +### 3. Build the Web Simulator -## Runtime and Configuration +```powershell +dotnet restore Simulation\MyParking.Simulation.csproj +dotnet build Simulation\MyParking.Simulation.csproj -c Debug +``` -This repository produces plugin libraries and cannot be started independently with `dotnet run`. A compatible Clumsy/Medulla host must load the assemblies above. The exact host version, copy locations, configuration-file paths, and startup command have not been provided and remain to be documented. +## Run the Web Simulator -MCU defaults confirmed from the current source are: +```powershell +dotnet run --project Simulation\MyParking.Simulation.csproj --launch-profile http +``` + +Open: + +```text +http://localhost:5203 +``` + +The UI provides normal, left-crab, right-crab, spin, forward, backward, left-turn, right-turn, stop, and reset actions. It also supports vehicle-layout configuration and manual-control input. Main APIs include: + +- `GET /api/vehicles` +- `GET /api/actions` +- `GET/POST /api/configuration` +- `POST /api/vehicles/{vehicleId}/commands/{command}` +- `POST /api/vehicles/{vehicleId}/manual-control` +- `POST /api/reset` + +`Simulation/Commands/MySimulationTests.cs` contains an example custom action. Add the `SimulationAction` attribute to a static method to have it discovered by the dispatcher and exposed in the Web UI. + +## Physical Runtime and MCU Configuration + +The physical-robot plugins cannot be started independently with `dotnet run`. Compatible Clumsy/Medulla hosts must load both DLLs. The required host versions, deployment directories, and complete startup procedure have not yet been provided. + +MCU defaults confirmed from the current source: | Setting | Default | | --- | --- | | MCU port | `COM4` | | MCU connection baud rate | `1000000` | -| CAN channels | One at `500000 bit/s`, with a `10 ms` retry time | -| Serial channels | Three at `9600 bit/s`, with a `10 ms` receive-frame time | +| CAN | One channel at `500000 bit/s`, with a `10 ms` retry time | +| Serial | Three channels at `9600 bit/s`, with a `10 ms` receive-frame time | +| Battery port index | `3` | +| Maximum spin rate | `30 deg/s` | +| Wheel-speed diagnostic directory | `logs\wheel-speed` | -Confirm the port and hardware parameters in the host configuration before physical operation. For initial tests, lift the drive wheels or use a controlled safety area and provide a reliable physical emergency stop. The alarm and emergency-stop feedback logic is incomplete, so software stop commands must not be the only safety measure. +A `chassis.json` chassis-parameter example is present in the current workspace, but no automatic loader for it was found in the source. Treat the actual host configuration as authoritative. -## Single-Robot Validation +Before physical testing, verify the port, vehicle ID, steering zero and limits, speed units, motor direction, clamp limits, and emergency-stop chain. Begin with lifted drive wheels or a segregated low-speed test area and retain an independent physical emergency stop; never rely on software stopping alone. -`MovementTests.cs` registers these manual tests in the Clumsy test interface: +## Single-Robot Test Entries -- `测试终点跟踪动作-前进`: select a source and destination for forward straight-line tracking; -- `测试终点跟踪动作-后退`: track backward with a 180-degree vehicle-direction offset; -- `底盘旋转测试`: enter a target world-frame heading and run PID-based in-place rotation. +`ClumsyPilot/MovementTests.cs` currently registers: -These are host-integrated action tests, not an automated `dotnet test` suite. Before physical testing, verify localization data, the chassis velocity interface, steering direction, speed units, and the emergency-stop chain. +- `准备:四个舵轮与车头方向一致` +- `SendMotion:连续前进4m` +- `SendXYThSpeed:原地自转90°` +- `SendXYThSpeed:原地自转180°` +- `SendMotion:左转90°半径2m圆弧` +- `SendMotion:蟹行直线4m` +- `SendMotion:蟹行左转90°半径2m圆弧` +- `SendMotion:4m S型曲线` +- `夹臂关闭测试` +- `夹臂启动测试` -## Development Roadmap +These are run through the Clumsy host's test interface and are not an automated `dotnet test` suite. Motion tests record the experiment number, reference path, Detour pose, and control commands according to their configuration. -### Stage 1: Basic Single-Robot Functions (Current) +## Experiment Data Analysis -- Connect upper-layer actions, chassis control, the Medulla adapter, and MCU communication; -- Complete single-robot start/stop, straight forward/reverse motion, in-place rotation, and stop protection; -- Implement driver commands, wheel and steering feedback, I/O, battery, emergency-stop, and alarm handling; -- Establish repeatable simulation, bench, and physical-vehicle validation procedures. +The tracking recorder saves CSV files under the host application's: -### Stage 2: Add Parking-Operation Features +```text +TrackingExperiments/ +``` -- After basic single-robot control is stable, integrate remote control, perception, vehicle entry, clamping, and vehicle-exit functions one at a time; -- Define parameters, exception handling, and physical validation for each feature instead of directly enabling legacy disabled code. +Medulla wheel-speed diagnostics can be controlled with the `StartWheelSpeedDiagnostic` and `StopWheelSpeedDiagnostic` utility buttons. Their default output directory is: -### Stage 3: Improve Tracking +```text +logs/wheel-speed/ +``` -- Use single-robot test data to improve path tracking, speed planning, steering control, and arrival detection; -- Cover curves, reverse motion, and low-speed near-target conditions, with reproducible regression tests; -- Freeze the single-robot interfaces only after safety, stability, and diagnostics meet project requirements. +Install dependencies in a Python environment managed by your team: -### Stage 4: Consider Multi-Robot Scenarios +```powershell +python -m pip install -r data_process\requirements.txt +``` -- Once the single-robot interfaces are stable, design vehicle identity, communication, heartbeats, timeouts, and disconnect fallback behavior; -- Then implement formation control, synchronized actions, relative-pose correction, and multi-robot safety policies; -- Re-review all legacy multi-robot parameters; the current `#if false` block is not evidence of completed functionality. +Generate trajectory comparison, tracking error, speed response, and angular-command plots for one or more CSV files: + +```powershell +python data_process\run_all_plots.py "path\trial1.csv" "path\trial2.csv" --output-dir "path\plots" +``` + +When no CSV path is supplied, the scripts search the `data_process` directory. The default resampling frequency is `20 Hz`, and the default filter window is `0.55 s`; use `--frequency` and `--window` to change them. + +## Incomplete or Pending Validation + +- Lidar point clouds, tire recognition, automatic vehicle entry, vehicle release, and the complete parking-operation state machine; +- Full physical acceptance, fault injection, and long-duration testing for current motion and clamp functions; +- Steering soft-limit prediction and automatic body reorientation; `SteeringConstraintManager.cs` currently contains mainly design notes; +- Automated unit tests and continuous integration; +- Multi-robot communication, formation, synchronization, and safety fallback; `FleetKinematics.cs` is currently only a placeholder; +- Host versions, plugin deployment directories, configuration-file locations, and the release process. ## Contributing -1. Confirm the applicable roadmap stage before making a change; current contributions should prioritize basic single-robot functions. -2. Preserve the boundary between `ClumsyPilot` and `MedullaAdapter`; hardware protocols should not be implemented directly in upper-layer actions. -3. Document units, defaults, applicable vehicle types, and safe ranges for new hardware parameters. -4. Run at least `dotnet build ParkingRobot.sln` before submitting and record the host or physical-test conditions used. -5. The team still needs to document its branch, code-review, and release processes. +1. Prioritize single-robot closed-loop behavior, parking functions, and tracking quality; do not enable multi-robot code prematurely. +2. Preserve the boundaries between upper-layer actions, shared kinematics, hardware protocols, and simulation. +3. Document coordinate frames, units, defaults, applicable vehicle types, and safe ranges for new parameters. +4. Build every affected project before submission and record the simulation, bench, or physical-test conditions. +5. After changing `CommonUsage`, update the root `ref/CommonUsage.dll`. +6. The team still needs to document its branch, review, and release processes. ## License diff --git a/chassis.json b/chassis.json new file mode 100644 index 0000000..4a35c9f --- /dev/null +++ b/chassis.json @@ -0,0 +1,50 @@ +{ + "WheelConfig": { + "LeftFront": { + "Position": { + "X": 525.0, + "Y": 200.0 + }, + "WheelDistance": 85.0, + "AngleLowerLimit": -128.0, + "AngleUpperLimit": 172.0, + "IsDiffWheel": true + }, + "RightFront": { + "Position": { + "X": 525.0, + "Y": -200.0 + }, + "WheelDistance": 85.0, + "AngleLowerLimit": -128.0, + "AngleUpperLimit": 172.0, + "IsDiffWheel": true + }, + "LeftRear": { + "Position": { + "X": -525.0, + "Y": 200.0 + }, + "WheelDistance": 85.0, + "AngleLowerLimit": -126.0, + "AngleUpperLimit": 174.0, + "IsDiffWheel": true + }, + "RightRear": { + "Position": { + "X": -525.0, + "Y": -200.0 + }, + "WheelDistance": 85.0, + "AngleLowerLimit": -130.0, + "AngleUpperLimit": 170.0, + "IsDiffWheel": true + } + }, + "MinimumTurningAngleForAckermann": 60.0, + "ControlPointRadius": 500.0, + "MaxSpeed": 1.0, + "AccPerSecond": 0.3, + "DeAccPerSecond": 1.0, + "MinTurnSpeedFac": 0.25 +} \ No newline at end of file diff --git a/测试方案.txt b/测试方案.txt index d58d491..9a0046a 100644 --- a/测试方案.txt +++ b/测试方案.txt @@ -2,8 +2,8 @@ ### 测试对象 单台停车机器人(+50kg负载) ### 测试曲线 -1. 直线:前进/后退2m、速度0.3m/s、起点终点静止 -2. 转弯:左转/右转组合前进/后退、转弯半径1m、曲率1.0、速度0.3m/s +1. 直线:前进/后退4m、速度0.3m/s、起点终点静止 +2. 转弯:左转/右转组合前进/后退、转弯半径2m、曲率1.0、速度0.3m/s 3. 原地自转:±90°/±180°、角速度10°/s、20°/s、起点终点静止 ### 评价指标 @@ -17,6 +17,7 @@ 归一化状态/控制量:一般Q、R初始选择对应控制量最大值的平方的倒数 或者使用Bryson’s Rule来给 Q、R 一个很好的初始猜测 贝叶斯优化在仿真中自动调节Q、R参数 + ALQR:在线估计最新参数实时重新求解 ---------------------------------------- 不调参:学习式