feat: integrate trajectory tracking controller runtime

This commit is contained in:
梁薄云
2026-08-10 13:26:56 +08:00
parent f923affc8f
commit 54ef239231
29 changed files with 5135 additions and 0 deletions
@@ -0,0 +1,104 @@
using System;
using MultiWheelC.Control.Abstractions;
namespace MultiWheelC.Control.Allocation
{
/// <summary>
/// 独立限制前后GCP目标转角并与纵向速度组合成底盘运动命令。
/// </summary>
public sealed class GcpCommandAllocator
{
/// <summary>
/// 创建使用指定前后GCP最大转角的命令分配器。
/// </summary>
public GcpCommandAllocator(double maximumGcpAngleRadians)
{
EnsureFinitePositive(
maximumGcpAngleRadians,
nameof(maximumGcpAngleRadians));
if (maximumGcpAngleRadians >= Math.PI / 2.0)
{
throw new ArgumentOutOfRangeException(
nameof(maximumGcpAngleRadians),
"最大GCP转角必须小于π/2。");
}
MaximumGcpAngleRadians = maximumGcpAngleRadians;
}
/// <summary>
/// 获取前后GCP允许的最大转角绝对值,单位为rad。
/// </summary>
public double MaximumGcpAngleRadians { get; }
/// <summary>
/// 将纵向速度和前后GCP转角组合为底盘运动命令。
/// </summary>
public GcpMotionCommand Allocate(
double speedMetersPerSecond,
LateralControlCommand lateralCommand)
{
EnsureFinite(
speedMetersPerSecond,
nameof(speedMetersPerSecond));
var frontAngleRadians = ClampSymmetric(
lateralCommand.FrontGcpAngleRadians,
MaximumGcpAngleRadians);
var rearAngleRadians = ClampSymmetric(
lateralCommand.RearGcpAngleRadians,
MaximumGcpAngleRadians);
return new GcpMotionCommand(
speedMetersPerSecond,
frontAngleRadians,
rearAngleRadians);
}
/// <summary>
/// 将数值按正负对称方式限制在指定绝对值内。
/// </summary>
private static double ClampSymmetric(
double value,
double maximumAbsoluteValue)
{
return Math.Max(
-maximumAbsoluteValue,
Math.Min(maximumAbsoluteValue, value));
}
/// <summary>
/// 检查参数是否为正有限值。
/// </summary>
private static void EnsureFinitePositive(
double value,
string parameterName)
{
EnsureFinite(value, parameterName);
if (value <= 0.0)
{
throw new ArgumentOutOfRangeException(
parameterName,
"GCP分配参数必须是正有限值。");
}
}
/// <summary>
/// 检查参数或命令是否为有限值。
/// </summary>
private static void EnsureFinite(
double value,
string parameterName)
{
if (double.IsNaN(value) ||
double.IsInfinity(value))
{
throw new ArgumentOutOfRangeException(
parameterName,
"GCP分配参数和命令必须是有限值。");
}
}
}
}
@@ -0,0 +1,67 @@
using System;
namespace MultiWheelC.Control.Allocation
{
/// <summary>
/// 表示发送给旧版多舵轮四轮解算前的有符号速度和前后GCP角度命令。
/// </summary>
public readonly struct GcpMotionCommand
{
/// <summary>
/// 创建统一使用m/s和rad的前后几何控制点运动命令。
/// </summary>
public GcpMotionCommand(
double speedMetersPerSecond,
double frontAngleRadians,
double rearAngleRadians)
{
EnsureFinite(
speedMetersPerSecond,
nameof(speedMetersPerSecond));
EnsureFinite(
frontAngleRadians,
nameof(frontAngleRadians));
EnsureFinite(
rearAngleRadians,
nameof(rearAngleRadians));
SpeedMetersPerSecond =
speedMetersPerSecond;
FrontAngleRadians =
frontAngleRadians;
RearAngleRadians =
rearAngleRadians;
}
/// <summary>
/// 获取准备交给底盘的有符号纵向速度,单位为m/s,正值表示前进。
/// </summary>
public double SpeedMetersPerSecond { get; }
/// <summary>
/// 获取前几何控制点相对车体X轴的目标方向,单位为rad,逆时针为正。
/// </summary>
public double FrontAngleRadians { get; }
/// <summary>
/// 获取后几何控制点相对车体X轴的目标方向,单位为rad,逆时针为正。
/// </summary>
public double RearAngleRadians { get; }
/// <summary>
/// 检查底盘中间命令是否为有限值。
/// </summary>
private static void EnsureFinite(
double value,
string parameterName)
{
if (double.IsNaN(value) ||
double.IsInfinity(value))
{
throw new ArgumentOutOfRangeException(
parameterName,
"GCP运动命令必须由有限值组成。");
}
}
}
}