💥 feat(planning)!: 拆分 C# ICSP 并默认 Rust
* 新增可选 Flyshot.CSharp.Planning 项目 * 将 icsp 映射到 Rust 后端并拒绝旧 icsp_rust * 补充后端注册、文档、调试页和回归测试 BREAKING CHANGE: method=icsp 现在默认调用 Rust 后端;C# ICSP 改为 method=icsp-csharp,旧 method=icsp_rust 不再作为正式入口。
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Flyshot.ControllerClientCompat;
|
||||
using Flyshot.CSharp.Planning;
|
||||
using Flyshot.Core.Config;
|
||||
using Flyshot.Core.Domain;
|
||||
using Flyshot.Core.Planning;
|
||||
@@ -16,6 +17,19 @@ namespace Flyshot.Core.Tests;
|
||||
/// </summary>
|
||||
public sealed class RuntimeOrchestrationTests
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建显式注册 C# ICSP 后端的编排器,用于验证可选算法 DLL 的行为边界。
|
||||
/// </summary>
|
||||
/// <returns>包含 C# 普通 ICSP 与 self-adapt-icsp 后端的轨迹编排器。</returns>
|
||||
private static ControllerClientTrajectoryOrchestrator CreateOrchestratorWithCSharpBackends()
|
||||
{
|
||||
return new ControllerClientTrajectoryOrchestrator(
|
||||
[
|
||||
new CSharpIcspPlanningBackend(),
|
||||
new SelfAdaptIcspPlanningBackend()
|
||||
]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证真机运行时会把 TCP 10010 状态通道健康度映射为可诊断连接状态。
|
||||
/// </summary>
|
||||
@@ -107,54 +121,10 @@ public sealed class RuntimeOrchestrationTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证普通轨迹使用准确字串 icsp_rust 时会真实调用 Rust DLL,并在结果中标记原生后端。
|
||||
/// 验证普通轨迹默认 icsp 会真实调用 Rust DLL,并在结果中保留正式 icsp 方法标记。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_UsesRustPlanner()
|
||||
{
|
||||
var orchestrator = new ControllerClientTrajectoryOrchestrator();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
|
||||
var bundle = orchestrator.PlanOrdinaryTrajectory(
|
||||
robot,
|
||||
[
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.001, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.002, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.003, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
],
|
||||
new TrajectoryExecutionOptions(method: "icsp_rust"));
|
||||
|
||||
Assert.Equal(PlanningMethod.IcspRust, bundle.PlannedTrajectory.Method);
|
||||
Assert.Equal(PlanningMethod.IcspRust, bundle.Result.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证飞拍轨迹使用准确字串 icsp_rust 时会真实调用 Rust DLL,同时保留触发时间轴。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanUploadedFlyshot_UsesRustPlanner()
|
||||
{
|
||||
var orchestrator = new ControllerClientTrajectoryOrchestrator();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
var uploaded = TestRobotFactory.CreateUploadedTrajectoryWithSingleShot();
|
||||
|
||||
var bundle = orchestrator.PlanUploadedFlyshot(
|
||||
robot,
|
||||
uploaded,
|
||||
new FlyshotExecutionOptions(method: "icsp_rust", useCache: false));
|
||||
|
||||
Assert.Equal(PlanningMethod.IcspRust, bundle.PlannedTrajectory.Method);
|
||||
Assert.Equal(PlanningMethod.IcspRust, bundle.Result.Method);
|
||||
Assert.Single(bundle.Result.ShotEvents);
|
||||
Assert.Single(bundle.Result.TriggerTimeline);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证普通轨迹默认 icsp 仍使用现有 C# 规划器。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_KeepsManagedIcspPlanner()
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_DefaultIcspUsesRustPlanner()
|
||||
{
|
||||
var orchestrator = new ControllerClientTrajectoryOrchestrator();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
@@ -174,12 +144,98 @@ public sealed class RuntimeOrchestrationTests
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 self-adapt-icsp 仍使用 C# 自适应规划器,不切换到 Rust。
|
||||
/// 验证旧的 icsp_rust 字串不再作为正式入口,并提示调用方改用 icsp。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanUploadedFlyshot_KeepsManagedSelfAdaptPlanner()
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_RejectsLegacyIcspRustName()
|
||||
{
|
||||
var orchestrator = new ControllerClientTrajectoryOrchestrator();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
|
||||
var exception = Assert.Throws<ArgumentException>(() => orchestrator.PlanOrdinaryTrajectory(
|
||||
robot,
|
||||
[
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.001, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.002, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.003, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
],
|
||||
new TrajectoryExecutionOptions(method: "icsp_rust")));
|
||||
|
||||
Assert.Contains("icsp", exception.Message);
|
||||
Assert.Contains("icsp_rust", exception.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证未注册 C# 后端时,icsp-csharp 会明确报错而不是静默回退。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_RejectsCSharpIcspWhenBackendIsMissing()
|
||||
{
|
||||
var orchestrator = new ControllerClientTrajectoryOrchestrator();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
|
||||
var exception = Assert.Throws<NotSupportedException>(() => orchestrator.PlanOrdinaryTrajectory(
|
||||
robot,
|
||||
[
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.001, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.002, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.003, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
],
|
||||
new TrajectoryExecutionOptions(method: "icsp-csharp")));
|
||||
|
||||
Assert.Contains("icsp-csharp", exception.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证显式注册 C# 后端后,icsp-csharp 使用拆分后的托管规划器。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_UsesRegisteredCSharpIcspPlanner()
|
||||
{
|
||||
var orchestrator = CreateOrchestratorWithCSharpBackends();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
|
||||
var bundle = orchestrator.PlanOrdinaryTrajectory(
|
||||
robot,
|
||||
[
|
||||
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.001, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.002, 0.0, 0.0, 0.0, 0.0, 0.0],
|
||||
[0.003, 0.0, 0.0, 0.0, 0.0, 0.0]
|
||||
],
|
||||
new TrajectoryExecutionOptions(method: "icsp-csharp"));
|
||||
|
||||
Assert.Equal(PlanningMethod.IcspCSharp, bundle.PlannedTrajectory.Method);
|
||||
Assert.Equal(PlanningMethod.IcspCSharp, bundle.Result.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证未注册 C# 后端时,self-adapt-icsp 会明确报错而不是把行为藏在主服务里。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanUploadedFlyshot_RejectsSelfAdaptWhenBackendIsMissing()
|
||||
{
|
||||
var orchestrator = new ControllerClientTrajectoryOrchestrator();
|
||||
var robot = TestRobotFactory.CreateRobotProfile();
|
||||
var uploaded = TestRobotFactory.CreateUploadedTrajectoryWithSingleShot();
|
||||
|
||||
var exception = Assert.Throws<NotSupportedException>(() => orchestrator.PlanUploadedFlyshot(
|
||||
robot,
|
||||
uploaded,
|
||||
new FlyshotExecutionOptions(method: "self-adapt-icsp", useCache: false)));
|
||||
|
||||
Assert.Contains("self-adapt-icsp", exception.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证显式注册 C# 后端后,self-adapt-icsp 仍使用 C# 自适应规划器。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ControllerClientTrajectoryOrchestrator_PlanUploadedFlyshot_UsesRegisteredManagedSelfAdaptPlanner()
|
||||
{
|
||||
var orchestrator = CreateOrchestratorWithCSharpBackends();
|
||||
var robot = new RobotProfile(
|
||||
name: "ManagedSelfAdaptTestRobot",
|
||||
modelPath: "Models/ManagedSelfAdaptTest.robot",
|
||||
|
||||
Reference in New Issue
Block a user