140 lines
4.2 KiB
C#
140 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using MyParking.Shared;
|
|
|
|
namespace MultiWheelC.Tests
|
|
{
|
|
internal static class FleetKinematicsTests
|
|
{
|
|
private const double Tolerance = 1e-9;
|
|
|
|
public static void Run()
|
|
{
|
|
var layout = CreateTailToTailLayout();
|
|
|
|
VerifyTranslation(layout);
|
|
VerifyRotationAroundFleetCenter(layout);
|
|
VerifyRotationAroundFirstVehicle(layout);
|
|
VerifyStop(layout);
|
|
|
|
Console.WriteLine(
|
|
"FleetKinematics刚体速度分配测试通过。共4个场景。");
|
|
}
|
|
|
|
private static FleetLayout CreateTailToTailLayout()
|
|
{
|
|
return new FleetLayout(
|
|
new[]
|
|
{
|
|
new VehicleLayout(
|
|
1,
|
|
new Pose2D(1.0, 0.0, 0.0)),
|
|
new VehicleLayout(
|
|
2,
|
|
new Pose2D(-1.0, 0.0, Math.PI))
|
|
});
|
|
}
|
|
|
|
private static void VerifyTranslation(FleetLayout layout)
|
|
{
|
|
var commands = FleetKinematics.Decompose(
|
|
layout,
|
|
new FleetMotionCommand(
|
|
Point2D.Zero,
|
|
new Twist2D(0.4, 0.0, 0.0)));
|
|
|
|
AssertTwist(Find(commands, 1), 0.4, 0.0, 0.0);
|
|
AssertTwist(Find(commands, 2), -0.4, 0.0, 0.0);
|
|
}
|
|
|
|
private static void VerifyRotationAroundFleetCenter(
|
|
FleetLayout layout)
|
|
{
|
|
var commands = FleetKinematics.Decompose(
|
|
layout,
|
|
FleetMotionCommand.RotateAround(
|
|
Point2D.Zero,
|
|
0.2));
|
|
|
|
AssertTwist(Find(commands, 1), 0.0, 0.2, 0.2);
|
|
AssertTwist(Find(commands, 2), 0.0, 0.2, 0.2);
|
|
}
|
|
|
|
private static void VerifyRotationAroundFirstVehicle(
|
|
FleetLayout layout)
|
|
{
|
|
var commands = FleetKinematics.Decompose(
|
|
layout,
|
|
FleetMotionCommand.RotateAround(
|
|
new Point2D(1.0, 0.0),
|
|
0.2));
|
|
|
|
AssertTwist(Find(commands, 1), 0.0, 0.0, 0.2);
|
|
AssertTwist(Find(commands, 2), 0.0, 0.4, 0.2);
|
|
}
|
|
|
|
private static void VerifyStop(FleetLayout layout)
|
|
{
|
|
var commands = FleetKinematics.Decompose(
|
|
layout,
|
|
FleetMotionCommand.Stop());
|
|
|
|
AssertTwist(Find(commands, 1), 0.0, 0.0, 0.0);
|
|
AssertTwist(Find(commands, 2), 0.0, 0.0, 0.0);
|
|
}
|
|
|
|
private static FleetMemberCommand Find(
|
|
IReadOnlyList<FleetMemberCommand> commands,
|
|
int vehicleId)
|
|
{
|
|
for (var index = 0; index < commands.Count; index++)
|
|
{
|
|
if (commands[index].VehicleId == vehicleId)
|
|
{
|
|
return commands[index];
|
|
}
|
|
}
|
|
|
|
throw new InvalidOperationException(
|
|
$"没有找到车辆{vehicleId}的分配命令。");
|
|
}
|
|
|
|
private static void AssertTwist(
|
|
FleetMemberCommand command,
|
|
double expectedVx,
|
|
double expectedVy,
|
|
double expectedOmega)
|
|
{
|
|
AssertNear(
|
|
command.TwistInVehicleBody.VxMetersPerSecond,
|
|
expectedVx,
|
|
command.VehicleId,
|
|
"Vx");
|
|
AssertNear(
|
|
command.TwistInVehicleBody.VyMetersPerSecond,
|
|
expectedVy,
|
|
command.VehicleId,
|
|
"Vy");
|
|
AssertNear(
|
|
command.TwistInVehicleBody.OmegaRadiansPerSecond,
|
|
expectedOmega,
|
|
command.VehicleId,
|
|
"Omega");
|
|
}
|
|
|
|
private static void AssertNear(
|
|
double actual,
|
|
double expected,
|
|
int vehicleId,
|
|
string valueName)
|
|
{
|
|
if (Math.Abs(actual - expected) > Tolerance)
|
|
{
|
|
throw new InvalidOperationException(
|
|
$"车辆{vehicleId}的{valueName}错误:" +
|
|
$"actual={actual:F9}, expected={expected:F9}。");
|
|
}
|
|
}
|
|
}
|
|
}
|