using System;
using System.Collections.Generic;
using ClumsyCore.Pilot;
using CommonUsage.Chassis;
using MyParking.Shared;
namespace MultiWheelC
{
///
/// 停车并等待四个舵轮稳定回到车体前向0°。
///
public class PrepareWheelsForward : MovementDefinition
{
///
/// 获取或设置本次动作的回正到位容差覆盖值,单位为deg;为空时读取车辆配置。
///
public float? ToleranceDegrees;
///
/// 获取或设置本次动作的稳定确认时间覆盖值,单位为s;为空时读取车辆配置。
///
public float? StableSeconds;
///
/// 获取或设置本次动作的超时覆盖值,单位为s;为空时读取车辆配置,0表示关闭超时。
///
public float? TimeoutSeconds;
public bool Completed { get; private set; }
///
/// 读取一次有效配置并等待全部舵轮在容差内稳定保持车体前向0°。
///
public override IEnumerable Get()
{
var config = PilotDefinition.Conf;
var toleranceDegrees =
ToleranceDegrees ??
config.ParkingWheelForwardToleranceDegrees;
var stableSeconds =
StableSeconds ??
config.ParkingWheelForwardStableSeconds;
var timeoutSeconds =
TimeoutSeconds ??
config.ParkingWheelForwardTimeoutSeconds;
NumericGuard.EnsureFiniteNonNegative(
toleranceDegrees,
nameof(ToleranceDegrees));
NumericGuard.EnsureFiniteNonNegative(
stableSeconds,
nameof(StableSeconds));
NumericGuard.EnsureFiniteNonNegative(
timeoutSeconds,
nameof(TimeoutSeconds));
var chassis =
PilotDefinition.Chassis as MultiWheelChassis;
if (chassis == null)
{
throw new InvalidOperationException(
"当前底盘不是MultiWheelChassis,无法执行舵轮回正。");
}
var adapter = new MultiWheelChassisAdapter(
chassis,
PilotDefinition.Self.CarNum);
adapter.ResetToBodyFrame();
var toleranceRadians =
AngleMath.DegreesToRadians(toleranceDegrees);
var startTime = DateTime.UtcNow;
DateTime? alignedSince = null;
Completed = false;
if (!adapter.PrepareParallelDirection(0.0))
{
throw new InvalidOperationException(
"无法将所有舵轮下发到车体前向0°。");
}
try
{
while (true)
{
var aligned =
adapter.AreParallelWheelsAligned(
0.0,
toleranceRadians);
if (aligned)
{
if (!alignedSince.HasValue)
alignedSince = DateTime.UtcNow;
if ((DateTime.UtcNow -
alignedSince.Value).TotalSeconds >=
stableSeconds)
{
Completed = true;
yield break;
}
}
else
{
alignedSince = null;
}
if (timeoutSeconds > 0f &&
(DateTime.UtcNow - startTime).TotalSeconds >
timeoutSeconds)
{
throw new TimeoutException(
$"舵轮回正超过{timeoutSeconds:F1}s," +
"测试已经取消。");
}
yield return true;
}
}
finally
{
// 只清零驱动速度,保留已经下发的0°舵角。
adapter.StopImmediately();
}
}
}
}