Files
Tutorial/MultiWheel/MultiWheelC/PilotConfig.cs
T
ruifeng.zhouandCursor d3abf0fb02 Fix fleet in-place rotation coordination
- Gate rotate-mode compensation PI by active fleet omega and reset the
  integrator/timer when idle, so releasing the joystick stops the cars
  cleanly instead of drifting/self-rotating from a wound-up integral.
- Add conditional integration anti-windup in RotatePiTerm to reduce the
  startup overshoot after the initial relative-pose spike.
- Raise translational P gain for faster startup correction.
- Superimpose body-frame compensation onto swerve rotation and add
  MultiVehicleDbg / RotateDbg / RotatePoseDbg diagnostics.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-28 19:09:24 +08:00

135 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using ClumsyCore;
using MDCSToolBox.Clumsy.Pilot.MultiWheel;
using Newtonsoft.Json;
namespace MultiWheelC;
public class PilotConfig : MultiWheelPilotConfig
{
// ===== 多车联动(已从 MDCSToolBox 内联回 Tutorial=====
[FieldMember(desc = "[sync] 转向角加速度(deg/s^2)")] public float SyncThAccPerSec = 30f;
[FieldMember(desc = "[sync] 编队车间距(mm)")] public float TestCarSyncDistance = 2400f;
[FieldMember(desc = "[sync] 编队布局偏角(deg)")] public float TestCarSyncTh = 0f;
// 手动遥控 Vx 已是 m/s、Vth 已是转向角(deg),此处系数保持 1(直通),不要再次缩放。
[FieldMember(desc = "[sync] 手动Vx系数")] public float ManualCarSyncVxFac = 1f;
[FieldMember(desc = "[sync] 手动Vy系数(蟹行横向)")] public float ManualCarSyncVyFac = 1f;
[FieldMember(desc = "[sync] 手动Vth系数")] public float ManualCarSyncVthFac = 1f;
[FieldMember(desc = "[sync] 检测中心偏移(mm)")] public float DeltaDetectCenter = 350f;
[FieldMember(desc = "[sync] 是否启用Detour定位")] public bool PosAvailable = true;
[FieldMember(desc = "多车联动:总车数")] public int MultiVehicleFleetNum = 2;
[FieldMember(desc = "联动线程周期(ms)")] public int MultiVehicleSyncInterval = 50;
[FieldMember(desc = "多车联动:主车端点 ip:port/ 表示本车为主车")] public string MultiVehicleMasterEndpoint = "/";
[FieldMember(desc = "多车联动:本车同步 IP")] public string SimpleIp = "127.0.0.1";
[JsonProperty("MultiVehicleMasterIp")]
private string LegacyMasterIpSetter
{
set
{
if (string.IsNullOrEmpty(value) || value == "/") return;
if (MultiVehicleMasterEndpoint == "/")
MultiVehicleMasterEndpoint = value.Contains(":") ? value : $"{value}:8008";
}
}
[FieldMember(desc = "多车联动:启用互识别纠正")] public bool MultiVehicleUseDetect = false;
[FieldMember(desc = "多车联动:SLAM X补偿系数")] public float MultiVehiclePosBiasXFac = 0.5f;
[FieldMember(desc = "多车联动:SLAM Y补偿系数")] public float MultiVehiclePosBiasYFac = 0.5f;
[FieldMember(desc = "多车联动:SLAM Th补偿系数")] public float MultiVehiclePosBiasThFac = 0.5f;
[FieldMember(desc = "多车联动:X补偿阈值(mm)")] public float MultiVehiclePosBiasXThreshold = 50f;
[FieldMember(desc = "多车联动:Y补偿阈值(mm)")] public float MultiVehiclePosBiasYThreshold = 50f;
[FieldMember(desc = "多车联动:Th补偿阈值(deg)")] public float MultiVehiclePosBiasThThreshold = 5f;
[FieldMember(desc = "多车联动:互识别 X补偿系数")] public float MultiVehicleDetectBiasXFac = 0.5f;
[FieldMember(desc = "多车联动:互识别 Y补偿系数")] public float MultiVehicleDetectBiasYFac = 0.5f;
[FieldMember(desc = "多车联动:互识别 Th补偿系数")] public float MultiVehicleDetectBiasThFac = 0.5f;
[FieldMember(desc = "多车联动:互识别 X补偿阈值(mm)")] public float MultiVehicleDetectBiasXThreshold = 50f;
[FieldMember(desc = "多车联动:互识别 Y补偿阈值(mm)")] public float MultiVehicleDetectBiasYThreshold = 50f;
[FieldMember(desc = "多车联动:互识别 Th补偿阈值(deg)")] public float MultiVehicleDetectBiasThThreshold = 5f;
// 原地旋转(mode2)闭环纠偏(PI):把"本车应移动到的位置(dx,dy,mm)/应转角(dth,deg)"作为误差,
// 用 PI 控制器换算成车体系修正速度叠加到绕队心旋转上。纯 P 对抗恒定横向滑移扰动有稳态残差,
// 加积分项把稳态误差拉到 0;积分带限幅(抗 windup),总输出限幅在 Max 内防过冲/振荡。
// Fac=比例增益(mm/s per mm、deg/s per deg)IFac=积分增益(mm/s per mm·s、deg/s per deg·s)Max=总输出上限。
[FieldMember(desc = "原地旋转纠偏:平移比例增益P(mm/s per mm)")] public float MultiVehicleRotateCompXyFac = 1.2f;
[FieldMember(desc = "原地旋转纠偏:平移积分增益I(mm/s per mm·s)")] public float MultiVehicleRotateCompXyIFac = 0.8f;
[FieldMember(desc = "原地旋转纠偏:平移速度上限(mm/s)")] public float MultiVehicleRotateCompXyMax = 150f;
[FieldMember(desc = "原地旋转纠偏:转向比例增益P(deg/s per deg)")] public float MultiVehicleRotateCompThFac = 0.8f;
[FieldMember(desc = "原地旋转纠偏:转向积分增益I(deg/s per deg·s)")] public float MultiVehicleRotateCompThIFac = 0.8f;
[FieldMember(desc = "原地旋转纠偏:转向速度上限(deg/s)")] public float MultiVehicleRotateCompThMax = 15f;
// 仅当车队实际被指令旋转(|fleetOmega|超过此阈值)时才运行纠偏 PI;否则清零并复位积分,
// 避免松开摇杆后积分残留持续驱动车辆"自行旋转停不下来"。
[FieldMember(desc = "原地旋转纠偏:生效的最小角速度阈值(deg/s)")] public float MultiVehicleRotateActiveOmega = 0.5f;
[FieldMember(desc = "单车同步 xy 精度(mm)")] public float SingleCarSyncPrecisionXy = 10f;
[FieldMember(desc = "单车同步 th 精度(deg)")] public float SingleCarSyncPrecisionTh = 0.2f;
[FieldMember(desc = "Playground WebAPI 基地址")]
public string PlaygroundWebApiUrl = "http://localhost:18090";
[FieldMember(desc = "Playground 小车名称(场景 robots[].name")]
public string PlaygroundRobotName = "agv_multi_1";
[FieldMember(desc = "Playground 邻车名称(仅主车用于原地旋转位姿诊断)")]
public string PlaygroundNeighborRobotName = "agv_multi_2";
[FieldMember(desc = "WebAPI 平移测试:平移距离(mm)")]
public float WebApiTranslateMm = 100f;
[FieldMember(desc = "WebAPI 旋转测试:旋转角度(deg)")]
public float WebApiRotateDeg = 5f;
[FieldMember(desc = "原地旋转:目标朝向(世界坐标系, deg)")]
public float InPlaceRotateTargetWorldDeg = 90f;
[FieldMember(desc = "原地旋转:旋转角速度(deg/s)")]
public float InPlaceRotateSpeed = 30f;
[FieldMember(desc = "原地旋转:到位角度精度(deg)")]
public float InPlaceRotateArriveDeg = 1f;
[FieldMember(desc = "原地旋转:起转前舵轮对齐精度(deg)")]
public float InPlaceRotateWheelAlignDeg = 2f;
// ===== 2腿检测(单线雷达识别两腿托盘 / 轮胎)=====
[FieldMember(desc = "2腿检测:雷达名(逗号分隔可多个)")]
public string TwoLegLidarName = "rear_left_lidar_1,rear_right_lidar_1";
[FieldMember(desc = "2腿检测:初始猜测X(mm, 车体坐标系)")]
public float TwoLegGuessX = 2000f;
[FieldMember(desc = "2腿检测:两腿间距(mm)")]
public float TwoLegWidth = 800f;
[FieldMember(desc = "2腿检测:两腿间距允许误差(mm)")]
public float TwoLegWidthErr = 100f;
[FieldMember(desc = "2腿检测:聚类点间距(mm)")]
public float TwoLegBlobDist = 100f;
[FieldMember(desc = "2腿检测:聚类尺寸(mm)")]
public float TwoLegBlobSize = 200f;
[FieldMember(desc = "2腿检测:聚类最小点数")]
public int TwoLegBlobPtCount = 5;
[FieldMember(desc = "2腿检测:聚类 padding")]
public int TwoLegPadding = 5;
[FieldMember(desc = "2腿检测:腿柱搜索范围")]
public int TwoLegPillarFindingScope = 20;
[FieldMember(desc = "2腿检测:方向符号(±1)")]
public int TwoLegSgnDir = 1;
[FieldMember(desc = "2腿检测:中心X偏移(mm)")]
public float TwoLegCenterChangeX = 0f;
[FieldMember(desc = "2腿检测:ROI滤波框长(mm)")]
public float TwoLegFilterLength = 1800f;
[FieldMember(desc = "2腿检测:ROI滤波框宽(mm)")]
public float TwoLegFilterWidth = 600f;
}