2026-06-28 15:04:55 +08:00
|
|
|
using System;
|
|
|
|
|
using System.Numerics;
|
|
|
|
|
using ClumsyCore;
|
|
|
|
|
using ClumsyCore.Interfaces;
|
|
|
|
|
using ClumsyCore.Pilot;
|
2026-06-29 15:59:28 +08:00
|
|
|
using FundamentalLib;
|
2026-06-28 15:04:55 +08:00
|
|
|
using MDCSToolBox.Clumsy.MotionControllers;
|
|
|
|
|
using MDCSToolBox.Clumsy.Movements;
|
|
|
|
|
using MDCSToolBox.Clumsy.Pilot;
|
|
|
|
|
|
|
|
|
|
namespace MultiWheelC;
|
|
|
|
|
|
|
|
|
|
public class ChassisController : MovementDefinition<MultiWheelGeometricController>
|
|
|
|
|
{
|
|
|
|
|
public float BaseSpeed = Configuration.conf.basicSpeed;
|
|
|
|
|
|
2026-06-29 15:59:28 +08:00
|
|
|
private DateTime _sendMotionDbgLast = DateTime.MinValue;
|
|
|
|
|
|
2026-06-28 15:04:55 +08:00
|
|
|
public override MultiWheelGeometricController Get()
|
|
|
|
|
{
|
|
|
|
|
return new MultiWheelGeometricController
|
|
|
|
|
{
|
|
|
|
|
Chassis = BasicPilotBase.Chassis,
|
|
|
|
|
BaseSpeed = BaseSpeed,
|
|
|
|
|
SlowDistance = PilotDefinition.Conf.SlowDistance,
|
|
|
|
|
SlowingPow = PilotDefinition.Conf.SlowingPow,
|
|
|
|
|
FinishDistance = PilotDefinition.Conf.FinishDistance,
|
|
|
|
|
FinishSpeed = PilotDefinition.Conf.FinishSpeed,
|
|
|
|
|
FirstThAccuracy = PilotDefinition.Conf.FirstThAccuracy,
|
|
|
|
|
FirstRotateSpeedFac = PilotDefinition.Conf.FirstRotateSpeedFac,
|
|
|
|
|
FirstRotateMaxSpeed = PilotDefinition.Conf.FirstRotateMaxSpeed,
|
|
|
|
|
NotContinuousAngle = PilotDefinition.Conf.NotContinuousAngle,
|
|
|
|
|
DebugMode = PilotDefinition.Conf.MotionDebugPrint,
|
|
|
|
|
DebugCurvature = PilotDefinition.Conf.DebugCurvature,
|
|
|
|
|
PowerSteeringLookAhead = PilotDefinition.Conf.PowerSteeringLookAhead,
|
|
|
|
|
SpeedLookAhead = PilotDefinition.Conf.SpeedLookAhead,
|
|
|
|
|
SpeedLookAheadCurveDiff = PilotDefinition.Conf.SpeedLookAheadCurveDiff,
|
|
|
|
|
SpeedLookBackCurveDiff = PilotDefinition.Conf.SpeedLookBackCurveDiff,
|
|
|
|
|
SpeedLimitCurveDiffMin = PilotDefinition.Conf.SpeedLimitCurveDiffMin,
|
|
|
|
|
SpeedLimitCurveMin = PilotDefinition.Conf.SpeedLimitCurveMin,
|
|
|
|
|
MaxRotateSpeed = PilotDefinition.Conf.MaxRotateSpeedCurveLimit,
|
|
|
|
|
MaxRotateAcc = PilotDefinition.Conf.MaxRotateAccCurveLimit,
|
|
|
|
|
GcpThetaThreshold = PilotDefinition.Conf.GcpThetaThreshold,
|
|
|
|
|
DthLinearFac = PilotDefinition.Conf.DthLinearFac,
|
|
|
|
|
DthLinearThreshold = PilotDefinition.Conf.DthLinearThreshold,
|
|
|
|
|
BiasFac = PilotDefinition.Conf.BiasFac,
|
|
|
|
|
BiasThreshold = PilotDefinition.Conf.BiasThreshold,
|
|
|
|
|
|
|
|
|
|
MultiVehicleSendMotion = (speed, frontTh, rearTh, idealPos, idealAngle) =>
|
|
|
|
|
{
|
2026-06-29 15:59:28 +08:00
|
|
|
var self = PilotDefinition.Self;
|
|
|
|
|
self.MultiVehicleAutoEnabled = true;
|
|
|
|
|
// A: 用固定锁对象(不再锁会被替换的字段引用)。
|
|
|
|
|
int fleetCnt;
|
|
|
|
|
lock (self.FleetLock)
|
|
|
|
|
fleetCnt = self.MultiVehicleFleet.Count;
|
|
|
|
|
|
|
|
|
|
// 诊断(节流 ~300ms):确认回调被调用、编队是否就绪、是否因数量不符提前 return(导致不下发速度)。
|
|
|
|
|
if ((DateTime.Now - _sendMotionDbgLast).TotalMilliseconds >= 300)
|
2026-06-28 15:04:55 +08:00
|
|
|
{
|
2026-06-29 15:59:28 +08:00
|
|
|
_sendMotionDbgLast = DateTime.Now;
|
|
|
|
|
DLog.Log(
|
|
|
|
|
$"SENDMOTION speed={speed:0.000} fTh={frontTh:0.0} rTh={rearTh:0.0} " +
|
|
|
|
|
$"ideal=({idealPos.X:0},{idealPos.Y:0},{idealAngle:0.0}) " +
|
|
|
|
|
$"editCnt={fleetCnt}/{PilotDefinition.Conf.MultiVehicleFleetNum} " +
|
|
|
|
|
$"earlyReturn={fleetCnt != PilotDefinition.Conf.MultiVehicleFleetNum}",
|
|
|
|
|
"FleetCrabDbg");
|
2026-06-28 15:04:55 +08:00
|
|
|
}
|
|
|
|
|
|
2026-06-29 15:59:28 +08:00
|
|
|
if (fleetCnt != PilotDefinition.Conf.MultiVehicleFleetNum)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self.MultiVehicleAutoVx = speed;
|
|
|
|
|
self.MultiVehicleAutoFrontTh = frontTh;
|
|
|
|
|
self.MultiVehicleAutoRearTh = rearTh;
|
|
|
|
|
// D: 透传路径控制器算出的理想车队中心位姿(此前被丢弃),供各车按 layout 做前馈。
|
|
|
|
|
self.MultiVehicleAutoIdealX = idealPos.X;
|
|
|
|
|
self.MultiVehicleAutoIdealY = idealPos.Y;
|
|
|
|
|
self.MultiVehicleAutoIdealTh = idealAngle;
|
|
|
|
|
self.MultiVehicleAutoHasIdeal = true;
|
|
|
|
|
// B: 标记命令新鲜度。路径结束/早退/卡顿不再刷新此时刻 → 主车超时后清零速度,避免滑行。
|
|
|
|
|
self.MultiVehicleAutoCmdTime = DateTime.Now;
|
2026-06-28 15:04:55 +08:00
|
|
|
},
|
|
|
|
|
|
2026-06-29 15:59:28 +08:00
|
|
|
// G: 读取车队中心原子快照,避免跨线程读到撕裂的 x/y/th 组合。
|
|
|
|
|
MultiVehicleGetFleetPos = () =>
|
2026-06-28 15:04:55 +08:00
|
|
|
{
|
2026-06-29 15:59:28 +08:00
|
|
|
var snap = PilotDefinition.Self.GetFleetCenterSnapshot();
|
|
|
|
|
return new Location
|
|
|
|
|
{
|
|
|
|
|
x = snap.X,
|
|
|
|
|
y = snap.Y,
|
|
|
|
|
th = snap.Th,
|
|
|
|
|
l_step = 1,
|
|
|
|
|
tick = DateTime.Now.Ticks
|
|
|
|
|
};
|
2026-06-28 15:04:55 +08:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|