diff --git a/MedullaAdapter/build/Medulla/plugins/CommonUsage.dll b/MedullaAdapter/build/Medulla/plugins/CommonUsage.dll
index fd9ab55..93900a2 100644
Binary files a/MedullaAdapter/build/Medulla/plugins/CommonUsage.dll and b/MedullaAdapter/build/Medulla/plugins/CommonUsage.dll differ
diff --git a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll
index 3f29033..1713d12 100644
Binary files a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll and b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.dll differ
diff --git a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.pdb b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.pdb
index 9a4547b..3ff5098 100644
Binary files a/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.pdb and b/MedullaAdapter/build/Medulla/plugins/MedullaAdapter.pdb differ
diff --git a/MultiWheelC/Control/Abstractions/LateralControlCommand.cs b/MultiWheelC/Control/Abstractions/LateralControlCommand.cs
index 2198a8d..cb170c9 100644
--- a/MultiWheelC/Control/Abstractions/LateralControlCommand.cs
+++ b/MultiWheelC/Control/Abstractions/LateralControlCommand.cs
@@ -3,37 +3,62 @@ using System;
namespace MultiWheelC.Control.Abstractions
{
///
- /// 表示横向控制器生成的车体中心目标曲率命令。
+ /// 表示横向控制器生成的前、后GCP目标转角,单位为rad,逆时针为正。
///
public readonly struct LateralControlCommand
{
///
- /// 创建统一使用SI单位和左转为正约定的横向控制命令。
+ /// 创建前、后GCP目标转角命令。
///
public LateralControlCommand(
- double targetCurvaturePerMeter)
+ double frontGcpAngleRadians,
+ double rearGcpAngleRadians)
{
EnsureFinite(
- targetCurvaturePerMeter,
- nameof(targetCurvaturePerMeter));
+ frontGcpAngleRadians,
+ nameof(frontGcpAngleRadians));
+ EnsureFinite(
+ rearGcpAngleRadians,
+ nameof(rearGcpAngleRadians));
- TargetCurvaturePerMeter =
- targetCurvaturePerMeter;
+ FrontGcpAngleRadians =
+ frontGcpAngleRadians;
+ RearGcpAngleRadians =
+ rearGcpAngleRadians;
}
///
- /// 获取车体中心目标轨迹曲率,单位为1/m,左转为正、右转为负。
+ /// 获取前GCP目标转角,单位为rad,逆时针为正。
///
- public double TargetCurvaturePerMeter { get; }
+ public double FrontGcpAngleRadians { get; }
///
- /// 创建保持直线行驶的零曲率命令。
+ /// 获取后GCP目标转角,单位为rad,逆时针为正。
+ ///
+ public double RearGcpAngleRadians { get; }
+
+ ///
+ /// 获取前后GCP的共同转角分量,主要用于横向平移修正。
+ ///
+ public double CommonAngleRadians =>
+ (FrontGcpAngleRadians +
+ RearGcpAngleRadians) / 2.0;
+
+ ///
+ /// 获取前后GCP的差动转角分量,主要用于曲率前馈和航向修正。
+ ///
+ public double DifferentialAngleRadians =>
+ (FrontGcpAngleRadians -
+ RearGcpAngleRadians) / 2.0;
+
+ ///
+ /// 创建前后GCP均保持车头方向的直线命令。
///
public static LateralControlCommand Straight =>
- new LateralControlCommand(0.0);
+ new LateralControlCommand(0.0, 0.0);
///
- /// 检查横向曲率命令是否为有限值。
+ /// 检查GCP目标转角是否为有限值。
///
private static void EnsureFinite(
double value,
@@ -44,7 +69,7 @@ namespace MultiWheelC.Control.Abstractions
{
throw new ArgumentOutOfRangeException(
parameterName,
- "横向控制目标曲率必须是有限值。");
+ "GCP目标转角必须是有限值。");
}
}
}
diff --git a/MultiWheelC/Control/Allocation/AckermannGcpAllocator.cs b/MultiWheelC/Control/Allocation/GcpCommandAllocator.cs
similarity index 51%
rename from MultiWheelC/Control/Allocation/AckermannGcpAllocator.cs
rename to MultiWheelC/Control/Allocation/GcpCommandAllocator.cs
index bf79863..77ccdca 100644
--- a/MultiWheelC/Control/Allocation/AckermannGcpAllocator.cs
+++ b/MultiWheelC/Control/Allocation/GcpCommandAllocator.cs
@@ -4,57 +4,36 @@ using MultiWheelC.Control.Abstractions;
namespace MultiWheelC.Control.Allocation
{
///
- /// 将车体中心目标曲率按对称前后转向策略转换为旧版底盘的前后GCP方向。
+ /// 独立限制前后GCP目标转角并与纵向速度组合成底盘运动命令。
///
- public sealed class AckermannGcpAllocator
+ public sealed class GcpCommandAllocator
{
///
- /// 创建使用指定GCP半间距和最大GCP转角的对称转向分配器。
+ /// 创建使用指定前后GCP最大转角的命令分配器。
///
- public AckermannGcpAllocator(
- double controlPointRadiusMeters,
- double maximumGcpAngleRadians)
+ public GcpCommandAllocator(double maximumGcpAngleRadians)
{
- EnsureFinitePositive(
- controlPointRadiusMeters,
- nameof(controlPointRadiusMeters));
EnsureFinitePositive(
maximumGcpAngleRadians,
nameof(maximumGcpAngleRadians));
- if (maximumGcpAngleRadians >=
- Math.PI / 2.0)
+ if (maximumGcpAngleRadians >= Math.PI / 2.0)
{
throw new ArgumentOutOfRangeException(
nameof(maximumGcpAngleRadians),
- "最大GCP转角必须小于π/2,避免曲率换算出现奇异值。");
+ "最大GCP转角必须小于π/2。");
}
- ControlPointRadiusMeters =
- controlPointRadiusMeters;
- MaximumGcpAngleRadians =
- maximumGcpAngleRadians;
+ MaximumGcpAngleRadians = maximumGcpAngleRadians;
}
- ///
- /// 获取车体中心到前、后GCP的距离,单位为m。
- ///
- public double ControlPointRadiusMeters { get; }
-
///
/// 获取前后GCP允许的最大转角绝对值,单位为rad。
///
public double MaximumGcpAngleRadians { get; }
///
- /// 获取当前GCP几何和转角限制允许的最大车体中心曲率,单位为1/m。
- ///
- public double MaximumCurvaturePerMeter =>
- Math.Tan(MaximumGcpAngleRadians) /
- ControlPointRadiusMeters;
-
- ///
- /// 将纵向命令速度和车体中心目标曲率分配为前后GCP运动命令。
+ /// 将纵向速度和前后GCP转角组合为底盘运动命令。
///
public GcpMotionCommand Allocate(
double speedMetersPerSecond,
@@ -64,19 +43,12 @@ namespace MultiWheelC.Control.Allocation
speedMetersPerSecond,
nameof(speedMetersPerSecond));
- var limitedCurvaturePerMeter =
- Clamp(
- lateralCommand
- .TargetCurvaturePerMeter,
- -MaximumCurvaturePerMeter,
- MaximumCurvaturePerMeter);
-
- var frontAngleRadians =
- Math.Atan(
- limitedCurvaturePerMeter *
- ControlPointRadiusMeters);
- var rearAngleRadians =
- -frontAngleRadians;
+ var frontAngleRadians = ClampSymmetric(
+ lateralCommand.FrontGcpAngleRadians,
+ MaximumGcpAngleRadians);
+ var rearAngleRadians = ClampSymmetric(
+ lateralCommand.RearGcpAngleRadians,
+ MaximumGcpAngleRadians);
return new GcpMotionCommand(
speedMetersPerSecond,
@@ -85,16 +57,15 @@ namespace MultiWheelC.Control.Allocation
}
///
- /// 将数值限制在指定闭区间内。
+ /// 将数值按正负对称方式限制在指定绝对值内。
///
- private static double Clamp(
+ private static double ClampSymmetric(
double value,
- double minimum,
- double maximum)
+ double maximumAbsoluteValue)
{
return Math.Max(
- minimum,
- Math.Min(maximum, value));
+ -maximumAbsoluteValue,
+ Math.Min(maximumAbsoluteValue, value));
}
///
diff --git a/MultiWheelC/Control/Execution/ParkingGeometricController.cs b/MultiWheelC/Control/Execution/ParkingGeometricController.cs
index 997c971..ba123b3 100644
--- a/MultiWheelC/Control/Execution/ParkingGeometricController.cs
+++ b/MultiWheelC/Control/Execution/ParkingGeometricController.cs
@@ -33,7 +33,7 @@ namespace MultiWheelC.Control.Execution
private readonly IVehicleStateProvider _stateProvider;
private readonly ILateralController _lateralController;
private readonly ILongitudinalController _longitudinalController;
- private readonly AckermannGcpAllocator _gcpAllocator;
+ private readonly GcpCommandAllocator _gcpAllocator;
private readonly GcpCommandExecutor _commandExecutor;
private Trajectory2D _trajectory;
@@ -45,7 +45,7 @@ namespace MultiWheelC.Control.Execution
IVehicleStateProvider stateProvider,
ILateralController lateralController,
ILongitudinalController longitudinalController,
- AckermannGcpAllocator gcpAllocator,
+ GcpCommandAllocator gcpAllocator,
GcpCommandExecutor commandExecutor,
double finishDistanceMeters = 0.03,
double finishSpeedMetersPerSecond = 0.02,
diff --git a/MultiWheelC/Control/Lateral/StanleyLateralController.cs b/MultiWheelC/Control/Lateral/StanleyLateralController.cs
index 939b897..26c64e1 100644
--- a/MultiWheelC/Control/Lateral/StanleyLateralController.cs
+++ b/MultiWheelC/Control/Lateral/StanleyLateralController.cs
@@ -4,22 +4,23 @@ using MultiWheelC.Control.Abstractions;
namespace MultiWheelC.Control.Lateral
{
///
- /// 使用参考曲率前馈、航向误差和横向误差计算车体中心目标曲率。
+ /// 将参考曲率、横向误差和航向误差分别转换为前、后GCP目标转角。
///
public sealed class StanleyLateralController : ILateralController
{
- private const double MaximumMathematicalAngleRadians =
- Math.PI / 2.0 - 1e-3;
-
///
- /// 创建使用指定GCP几何、Stanley增益和低速保护参数的横向控制器。
+ /// 创建使用指定GCP几何、Stanley增益和转角保护参数的横向控制器。
///
public StanleyLateralController(
double controlPointRadiusMeters,
double crossTrackGainPerSecond,
double headingErrorGain,
double minimumSpeedMetersPerSecond,
- bool useActualSpeedForGain = true)
+ bool useActualSpeedForGain = true,
+ double maximumCrossTrackCorrectionRadians =
+ 10.0 * Math.PI / 180.0,
+ double maximumHeadingCorrectionRadians =
+ 10.0 * Math.PI / 180.0)
{
EnsureFinitePositive(
controlPointRadiusMeters,
@@ -33,12 +34,22 @@ namespace MultiWheelC.Control.Lateral
EnsureFinitePositive(
minimumSpeedMetersPerSecond,
nameof(minimumSpeedMetersPerSecond));
+ EnsureFinitePositive(
+ maximumCrossTrackCorrectionRadians,
+ nameof(maximumCrossTrackCorrectionRadians));
+ EnsureFinitePositive(
+ maximumHeadingCorrectionRadians,
+ nameof(maximumHeadingCorrectionRadians));
ControlPointRadiusMeters = controlPointRadiusMeters;
CrossTrackGainPerSecond = crossTrackGainPerSecond;
HeadingErrorGain = headingErrorGain;
MinimumSpeedMetersPerSecond = minimumSpeedMetersPerSecond;
UseActualSpeedForGain = useActualSpeedForGain;
+ MaximumCrossTrackCorrectionRadians =
+ maximumCrossTrackCorrectionRadians;
+ MaximumHeadingCorrectionRadians =
+ maximumHeadingCorrectionRadians;
}
///
@@ -62,12 +73,22 @@ namespace MultiWheelC.Control.Lateral
public double MinimumSpeedMetersPerSecond { get; }
///
- /// 获取是否优先使用Detour估算的实际纵向速度计算横向误差项。
+ /// 获取是否优先使用Detour估算的实际纵向速度计算横向修正。
///
public bool UseActualSpeedForGain { get; }
///
- /// 根据参考曲率、航向误差和横向误差计算车体中心目标曲率。
+ /// 获取横向误差共同转角分量的最大绝对值,单位为rad。
+ ///
+ public double MaximumCrossTrackCorrectionRadians { get; }
+
+ ///
+ /// 获取航向误差差动转角分量的最大绝对值,单位为rad。
+ ///
+ public double MaximumHeadingCorrectionRadians { get; }
+
+ ///
+ /// 分别计算横向共同转角以及曲率和航向差动转角,并生成前后GCP命令。
///
public LateralControlCommand Compute(
PathTrackingContext context)
@@ -78,33 +99,40 @@ namespace MultiWheelC.Control.Lateral
MinimumSpeedMetersPerSecond);
var travelDirection = SelectTravelDirection(context);
- // 参考曲率提供前馈;没有跟踪误差时也能沿曲线行驶。
+ // 参考曲率决定前后反向的差动转角,使无跟踪误差时也能沿曲线行驶。
var feedforwardAngleRadians = Math.Atan(
context.ReferenceCurvaturePerMeter *
ControlPointRadiusMeters);
- // 轨迹位于车辆左侧时横向误差为正,对应正的左转修正。
- var crossTrackCorrectionRadians = Math.Atan(
- CrossTrackGainPerSecond *
- context.LateralErrorMeters /
- speedMagnitude);
+ // 横向误差生成前后同向的共同转角,使四舵轮车辆平稳靠近轨迹。
+ var crossTrackCorrectionRadians =
+ ClampSymmetric(
+ Math.Atan(
+ CrossTrackGainPerSecond *
+ context.LateralErrorMeters /
+ speedMagnitude),
+ MaximumCrossTrackCorrectionRadians);
- // 倒车时需要反转反馈修正方向;参考曲率前馈仍由轨迹本身决定。
- var feedbackAngleRadians = travelDirection *
- (HeadingErrorGain * context.HeadingErrorRadians +
- crossTrackCorrectionRadians);
+ // 航向误差生成前后反向的差动转角,只负责调整车身朝向。
+ var headingCorrectionRadians =
+ ClampSymmetric(
+ HeadingErrorGain *
+ context.HeadingErrorRadians,
+ MaximumHeadingCorrectionRadians);
- // 这里只避开tan奇点,实际GCP机械限制由AckermannGcpAllocator处理。
- var targetEquivalentAngleRadians = Clamp(
- feedforwardAngleRadians + feedbackAngleRadians,
- -MaximumMathematicalAngleRadians,
- MaximumMathematicalAngleRadians);
- var targetCurvaturePerMeter = Math.Tan(
- targetEquivalentAngleRadians) /
- ControlPointRadiusMeters;
+ var commonAngleRadians =
+ travelDirection *
+ crossTrackCorrectionRadians;
+ var differentialAngleRadians =
+ feedforwardAngleRadians +
+ travelDirection *
+ headingCorrectionRadians;
return new LateralControlCommand(
- targetCurvaturePerMeter);
+ commonAngleRadians +
+ differentialAngleRadians,
+ commonAngleRadians -
+ differentialAngleRadians);
}
///
@@ -115,7 +143,7 @@ namespace MultiWheelC.Control.Lateral
}
///
- /// 选择Stanley横向误差项使用的实际速度或旧版参考速度。
+ /// 选择Stanley横向误差项使用的实际速度或参考速度。
///
private double SelectSpeedForGain(
PathTrackingContext context)
@@ -131,7 +159,7 @@ namespace MultiWheelC.Control.Lateral
}
///
- /// 根据有符号参考速度确定前进或倒车的反馈修正方向。
+ /// 根据有符号参考速度确定前进或倒车时的反馈修正方向。
///
private static double SelectTravelDirection(
PathTrackingContext context)
@@ -158,16 +186,15 @@ namespace MultiWheelC.Control.Lateral
}
///
- /// 将数值限制在指定闭区间内。
+ /// 将数值按正负对称方式限制在指定绝对值内。
///
- private static double Clamp(
+ private static double ClampSymmetric(
double value,
- double minimum,
- double maximum)
+ double maximumAbsoluteValue)
{
return Math.Max(
- minimum,
- Math.Min(maximum, value));
+ -maximumAbsoluteValue,
+ Math.Min(maximumAbsoluteValue, value));
}
///
@@ -183,7 +210,7 @@ namespace MultiWheelC.Control.Lateral
{
throw new ArgumentOutOfRangeException(
parameterName,
- "Stanley控制器的几何尺寸和最小速度必须是正有限值。");
+ "Stanley控制器的几何尺寸、速度和角度限制必须是正有限值。");
}
}
diff --git a/MultiWheelC/Experiments/NewControllerTrackingTests.cs b/MultiWheelC/Experiments/NewControllerTrackingTests.cs
index 8c47315..d9269d3 100644
--- a/MultiWheelC/Experiments/NewControllerTrackingTests.cs
+++ b/MultiWheelC/Experiments/NewControllerTrackingTests.cs
@@ -47,7 +47,7 @@ namespace MultiWheelC
///
/// 获取或设置参考速度减速度,单位为m/s²。
///
- public double DecelerationMetersPerSecondSquared = 0.12;
+ public double DecelerationMetersPerSecondSquared = 0.10;
///
/// 获取或设置离散轨迹点间距,单位为m。
diff --git a/MultiWheelC/Movements/MotionPlanExecutor.cs b/MultiWheelC/Movements/MotionPlanExecutor.cs
index 5c5b69e..f1f4dcf 100644
--- a/MultiWheelC/Movements/MotionPlanExecutor.cs
+++ b/MultiWheelC/Movements/MotionPlanExecutor.cs
@@ -173,7 +173,12 @@ namespace MultiWheelC
foreach (var keepRunning in movement.Get())
{
- yield return keepRunning;
+ if (!keepRunning)
+ {
+ break;
+ }
+
+ yield return true;
}
continue;
@@ -219,7 +224,12 @@ namespace MultiWheelC
foreach (var keepRunning in movement.Get())
{
- yield return keepRunning;
+ if (!keepRunning)
+ {
+ break;
+ }
+
+ yield return true;
}
continue;
@@ -228,6 +238,9 @@ namespace MultiWheelC
throw new NotSupportedException(
$"组合运动计划不支持动作段类型:{segment.GetType().FullName}。");
}
+
+ // 所有子动作均已完成后,才向外层DriveTask发送组合计划结束信号。
+ yield return false;
}
}
}
diff --git a/MultiWheelC/Movements/TrajectoryTrackingMovement.cs b/MultiWheelC/Movements/TrajectoryTrackingMovement.cs
index 553f6c7..4ec7419 100644
--- a/MultiWheelC/Movements/TrajectoryTrackingMovement.cs
+++ b/MultiWheelC/Movements/TrajectoryTrackingMovement.cs
@@ -55,6 +55,18 @@ namespace MultiWheelC
///
public bool StanleyUsesActualSpeed = true;
+ ///
+ /// Stanley横向误差共同转角分量的最大绝对值,单位为rad。
+ ///
+ public double MaximumCrossTrackCorrectionRadians =
+ AngleMath.DegreesToRadians(10.0);
+
+ ///
+ /// Stanley航向误差差动转角分量的最大绝对值,单位为rad。
+ ///
+ public double MaximumHeadingCorrectionRadians =
+ AngleMath.DegreesToRadians(10.0);
+
///
/// 纵向速度外环比例增益。
///
@@ -163,7 +175,9 @@ namespace MultiWheelC
StanleyCrossTrackGainPerSecond,
StanleyHeadingErrorGain,
StanleyMinimumSpeedMetersPerSecond,
- StanleyUsesActualSpeed);
+ StanleyUsesActualSpeed,
+ MaximumCrossTrackCorrectionRadians,
+ MaximumHeadingCorrectionRadians);
var longitudinalController =
new PidLongitudinalController(
LongitudinalKp,
@@ -173,8 +187,7 @@ namespace MultiWheelC
MaximumCommandSpeedMetersPerSecond,
LongitudinalSpeedErrorDeadbandMetersPerSecond);
var gcpAllocator =
- new AckermannGcpAllocator(
- controlPointRadiusMeters,
+ new GcpCommandAllocator(
MaximumGcpAngleRadians);
var commandExecutor =
new GcpCommandExecutor(
diff --git a/MultiWheelC/build/Clumsy/CommonUsage.dll b/MultiWheelC/build/Clumsy/CommonUsage.dll
index fd9ab55..93900a2 100644
Binary files a/MultiWheelC/build/Clumsy/CommonUsage.dll and b/MultiWheelC/build/Clumsy/CommonUsage.dll differ
diff --git a/MultiWheelC/build/Clumsy/MultiWheelC.dll b/MultiWheelC/build/Clumsy/MultiWheelC.dll
index 8db0fca..5584b5b 100644
Binary files a/MultiWheelC/build/Clumsy/MultiWheelC.dll and b/MultiWheelC/build/Clumsy/MultiWheelC.dll differ
diff --git a/MultiWheelC/build/Clumsy/MultiWheelC.pdb b/MultiWheelC/build/Clumsy/MultiWheelC.pdb
index db84013..d7fa53b 100644
Binary files a/MultiWheelC/build/Clumsy/MultiWheelC.pdb and b/MultiWheelC/build/Clumsy/MultiWheelC.pdb differ
diff --git a/data_process/新版前后角解耦控制器测试处理/4m直线0.3/记录.txt b/data_process/新版前后角解耦控制器测试处理/4m直线0.3/记录.txt
new file mode 100644
index 0000000..a94b318
--- /dev/null
+++ b/data_process/新版前后角解耦控制器测试处理/4m直线0.3/记录.txt
@@ -0,0 +1,17 @@
+第一次:
+ok
+
+第二次:
+: * (Exception):DriveTask failed, msg=车辆已在终点零速参考处停稳,但终点精度不满足要求:位置误差=0.031m,航向误差=0.03°。, stack:
+ at ClumsyCore.DriveTask.Wait() in D:\MDCS\Source\Core\Clumsy\ClumsyCore\DriveTask.cs:line 205
+ at MultiWheelC.NewControllerStraight4mTest.Test() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Experiments\NewControllerTrackingTests.cs:line 146
+ at ClumsyLite.ClumsyLiteUI.<>c__DisplayClass19_1.b__21() in D:\MDCS\Source\Core\Clumsy\ClumsyLite\ClumsyLiteUI.cs:line 592
+
+ *p.InnerException * (InvalidOperationException):车辆已在终点零速参考处停稳,但终点精度不满足要求:位置误差=0.031m,航向误差=0.03°。, stack:
+ at MultiWheelC.TrajectoryTrackingMovement.Get()+MoveNext() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Movements\TrajectoryTrackingMovement.cs:line 257
+ at ClumsyCore.DriveTask.<>c__DisplayClass9_0.<.ctor>b__2() in D:\MDCS\Source\Core\Clumsy\ClumsyCore\DriveTask.cs:line 112
+
+
+
+第三次:
+ok
\ No newline at end of file
diff --git a/data_process/新版控制器轨迹测试处理/混合测试/第三次/记录.txt b/data_process/新版控制器轨迹测试处理/混合测试/第三次/记录.txt
new file mode 100644
index 0000000..edb6c6d
--- /dev/null
+++ b/data_process/新版控制器轨迹测试处理/混合测试/第三次/记录.txt
@@ -0,0 +1,9 @@
+put meobj `clumsy_detour_backplate_lines` @ 95c33350
+apply gltf class `basic_car`, vtx=19456
+put meobj `CarInWorld` @ 965e05e0
+组合运动开始第1段:TrackMotionPlanSegment
+put meobj `CompositeStopTurnGoTest_pc` @ a511aa30
+put meobj `CompositeStopTurnGoTest_lines` @ a5281610
+轨迹实验数据已保存:C:\Users\Administrator\Desktop\MDCS2\Clumsy自动\TrackingExperiments\20260807_134158_374_NewStanleyPidComposite_SmoothTurnStopRotateStraight_Trial1.csv
+Declare P2 on T0(local)
+P2(on T0) decide to close
\ No newline at end of file
diff --git a/data_process/新版控制器轨迹测试处理/混合测试/第四次/记录.txt b/data_process/新版控制器轨迹测试处理/混合测试/第四次/记录.txt
new file mode 100644
index 0000000..3512f01
--- /dev/null
+++ b/data_process/新版控制器轨迹测试处理/混合测试/第四次/记录.txt
@@ -0,0 +1,29 @@
+第一次
+: * (Exception):DriveTask failed, msg=车辆已在终点零速参考处停稳,但终点精度不满足要求:位置误差=0.033m,航向误差=0.75°。, stack:
+ at ClumsyCore.DriveTask.Wait() in D:\MDCS\Source\Core\Clumsy\ClumsyCore\DriveTask.cs:line 205
+ at MultiWheelC.CompositeStopTurnGoTest.Test() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Experiments\CompositeMotionPlanTests.cs:line 187
+ at ClumsyLite.ClumsyLiteUI.<>c__DisplayClass19_1.b__21() in D:\MDCS\Source\Core\Clumsy\ClumsyLite\ClumsyLiteUI.cs:line 592
+
+ *p.InnerException * (InvalidOperationException):车辆已在终点零速参考处停稳,但终点精度不满足要求:位置误差=0.033m,航向误差=0.75°。, stack:
+ at MultiWheelC.TrajectoryTrackingMovement.Get()+MoveNext() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Movements\TrajectoryTrackingMovement.cs:line 244
+ at MultiWheelC.MotionPlanExecutor.Get()+MoveNext() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Movements\MotionPlanExecutor.cs:line 174
+ at ClumsyCore.DriveTask.<>c__DisplayClass9_0.<.ctor>b__2() in D:\MDCS\Source\Core\Clumsy\ClumsyCore\DriveTask.cs:line 112
+
+
+第二次:
+
+: * (Exception):DriveTask failed, msg=车辆已在终点零速参考处停稳,但终点精度不满足要求:位置误差=0.041m,航向误差=0.24°。, stack:
+ at ClumsyCore.DriveTask.Wait() in D:\MDCS\Source\Core\Clumsy\ClumsyCore\DriveTask.cs:line 205
+ at MultiWheelC.CompositeStopTurnGoTest.Test() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Experiments\CompositeMotionPlanTests.cs:line 187
+ at ClumsyLite.ClumsyLiteUI.<>c__DisplayClass19_1.b__21() in D:\MDCS\Source\Core\Clumsy\ClumsyLite\ClumsyLiteUI.cs:line 592
+
+ *p.InnerException * (InvalidOperationException):车辆已在终点零速参考处停稳,但终点精度不满足要求:位置误差=0.041m,航向误差=0.24°。, stack:
+ at MultiWheelC.TrajectoryTrackingMovement.Get()+MoveNext() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Movements\TrajectoryTrackingMovement.cs:line 244
+ at MultiWheelC.MotionPlanExecutor.Get()+MoveNext() in D:\Users\Desktop\入职培训\停车机器人\MyParking\MultiWheelC\Movements\MotionPlanExecutor.cs:line 174
+ at ClumsyCore.DriveTask.<>c__DisplayClass9_0.<.ctor>b__2() in D:\MDCS\Source\Core\Clumsy\ClumsyCore\DriveTask.cs:line 112
+
+
+第三次:
+ok
+
+
diff --git a/docs/数据融合.txt b/docs/数据融合.txt
new file mode 100644
index 0000000..b90a927
--- /dev/null
+++ b/docs/数据融合.txt
@@ -0,0 +1,94 @@
+是的,强烈建议做系统辨识,尤其是你这种要把电机反馈和 SLAM 融合的场景。
+为什么需要系统辨识?
+卡尔曼滤波(或 EKF)的效果很大程度上取决于过程模型有多准。模型不准的话,会出现:
+
+预测步持续往错误方向跑
+滤波器过度依赖测量(SLAM),或者反过来过度信任错误的模型
+速度估计系统性偏大/偏小
+原地自转时航向纠正效果变差
+
+你现在已经知道电机反馈“偏大”,这本身就是典型的模型参数问题(可能是轮胎半径、减速比、编码器标定、打滑补偿等)。
+建议辨识的主要参数
+针对四轮差速车,优先考虑这些:
+
+运动学参数
+有效轮半径(或左右轮半径)
+轮距(左右轮中心距离)
+可能的轴距相关项(如果不是纯差速)
+
+速度相关
+电机速度到实际车速的缩放系数(你提到的“偏大”问题)
+左右轮速度的不对称性(如果存在)
+低速段的非线性(静摩擦、死区)
+
+可选但有用的
+速度偏置 / 零点漂移
+简单的打滑系数(如果经常在特定地面跑)
+
+
+怎么做比较实际?
+不需要一开始就上很复杂的在线辨识,可以分两步:
+离线标定(推荐先做)
+
+让车在平坦地面以不同速度直线行驶、原地旋转,记录:
+四个电机反馈速度
+SLAM 给出的位置和航向变化
+
+用最小二乘或简单优化,拟合出轮半径、轮距、速度缩放系数等
+原地自转特别适合标定轮距和左右轮差异
+
+在线微调(可选)
+
+把关键参数(比如速度缩放系数、轮半径)也放进状态向量里一起估计(Augmented EKF)
+或者用简单的自适应方法,定期用 SLAM 和电机速度的一致性去微调缩放因子
+
+实际建议顺序
+
+先建立基本运动学模型 + EKF 框架
+做一轮离线系统辨识,把明显偏差(尤其是速度偏大)修正掉
+再跑融合,看残差(innovation)是否变小、速度估计是否更合理
+如果还有残余误差,再考虑把个别参数做成在线估计
+
+总结:建完模型后做系统辨识,是让卡尔曼滤波真正好用的关键一步。不做的话,即使融合了电机和 SLAM,效果也容易打折扣。需要的话,我可以给你一个针对差速车的简单离线标定思路(需要记录哪些数据、怎么拟合)。
+
+有没有必要做卡尔曼/传感器融合?
+分两层看:
+
+如果只是为了速度闭环,且当前绿色线已经能让车跑得比较稳
+→ 性价比一般。
+你现在的处理已经解决了最严重的问题,继续花时间做完整的 EKF + 电机融合,短期内收益可能没有那么大。可以先把绿色线再优化一下(比如调整低通截止频率、加一点自适应滤波,或者用更温和的滑动平均),看能不能把残余抖动再压低一点。
+如果你对速度精度、平滑度要求比较高,或者后面还要做更精细的控制(轨迹跟踪、力控、高精度定位等)
+→ 值得做,性价比会变高。
+原因是:
+绿色线本质还是“从位置差分出来的速度”,天然会有延迟和残余噪声。
+电机反馈是更直接的速度源,频率高、相位更好。
+把电机速度和经过处理的 SLAM 差分速度做融合(哪怕是简单的互补滤波或一阶卡尔曼),通常能同时得到:
+更低的噪声
+更小的滞后
+对电机“偏大”问题的一定校正能力
+
+
+
+实际建议(按性价比排序)
+
+先低成本优化现有绿色线(最快)
+检查低通滤波的截止频率是否合适(太低会滞后,太高会留噪声)。
+可以尝试一阶低通 + 中值滤波组合,或者简单的互补滤波(位置差分 + 电机速度)。
+看看闭环时车的实际表现,如果抖动已经可接受,就先用着。
+
+中等成本:做简单融合(推荐优先考虑)
+不用完整 EKF,先做一个互补滤波或一维卡尔曼只融速度:
+高频信任电机反馈速度
+低频用处理后的 SLAM 差分速度去校正偏差
+
+实现简单,效果通常比单纯低通好一截,滞后也更小。
+
+完整 EKF + 系统辨识
+只有在你需要同时提升位置、航向、速度的整体一致性,或者后面要上更复杂的控制时,再上这个。
+工作量明显更大,但长期收益最高。
+
+
+总结
+从你这张图来看,目前绿色线已经能用,不是“必须立刻上卡尔曼”的紧急情况。
+但如果你觉得绿色线的残余抖动还是影响闭环效果,或者想要更干净、滞后更小的速度,那么把四个电机反馈融进去(哪怕先做简单融合)是性价比不错的下一步,比继续死磕低通滤波更有前途。
+你现在速度闭环时,车实际表现如何?是觉得绿色线的抖动已经导致控制不稳,还是只是看着不舒服?这能帮助判断要不要马上上融合。
\ No newline at end of file
diff --git a/docs/记录.txt b/docs/记录.txt
index 6dfaf55..a63503d 100644
--- a/docs/记录.txt
+++ b/docs/记录.txt
@@ -55,3 +55,10 @@ ParkingGeometricController.cs
增加起步航向对齐状态。
第一阶段建议采用第二种,简单、安全。
+把前后GCP转角分解成两个模态:
+共同转角 = (前GCP转角 + 后GCP转角) / 2
+差动转角 = (前GCP转角 - 后GCP转角) / 2
+
+
+
+
diff --git a/output/C/CommonUsage.dll b/output/C/CommonUsage.dll
index fd9ab55..93900a2 100644
Binary files a/output/C/CommonUsage.dll and b/output/C/CommonUsage.dll differ
diff --git a/output/C/MultiWheelC.dll b/output/C/MultiWheelC.dll
index 8db0fca..5584b5b 100644
Binary files a/output/C/MultiWheelC.dll and b/output/C/MultiWheelC.dll differ
diff --git a/output/C/MultiWheelC.pdb b/output/C/MultiWheelC.pdb
index db84013..d7fa53b 100644
Binary files a/output/C/MultiWheelC.pdb and b/output/C/MultiWheelC.pdb differ
diff --git a/output/M/CommonUsage.dll b/output/M/CommonUsage.dll
index fd9ab55..93900a2 100644
Binary files a/output/M/CommonUsage.dll and b/output/M/CommonUsage.dll differ
diff --git a/output/M/MedullaAdapter.dll b/output/M/MedullaAdapter.dll
index 3f29033..1713d12 100644
Binary files a/output/M/MedullaAdapter.dll and b/output/M/MedullaAdapter.dll differ
diff --git a/output/M/MedullaAdapter.pdb b/output/M/MedullaAdapter.pdb
index 9a4547b..3ff5098 100644
Binary files a/output/M/MedullaAdapter.pdb and b/output/M/MedullaAdapter.pdb differ
diff --git a/ref/CommonUsage.dll b/ref/CommonUsage.dll
index fd9ab55..93900a2 100644
Binary files a/ref/CommonUsage.dll and b/ref/CommonUsage.dll differ