feat(*): 添加 J519 实发重采样与 JSON 机型模型

* 新增 J519 实发采样器,按 8ms 周期生成 timing/jerk 诊断行并完成 rad->deg 转换
* 兼容层产物导出补充 speedRatio,规划编排补齐 smoothStartStopTiming 与日志透传
* 配置与机型加载切换到运行目录 JSON 模型,并补齐 7L 展开模型与相关单元测试
This commit is contained in:
2026-05-07 17:08:32 +08:00
parent 70b0ccd414
commit c6829d214a
26 changed files with 1417 additions and 409 deletions

View File

@@ -237,9 +237,9 @@ public sealed class FanucControllerRuntimeDenseTests
var bundle = orchestrator.PlanUploadedFlyshot(
fixture.Robot,
fixture.Uploaded,
settings: fixture.Settings,
planningSpeedScale: 1.0);
var outputRoot = Path.Combine(AppContext.BaseDirectory, "Config", "Data", bundle.Result.ProgramName);
settings: fixture.Settings);
var result = WithUniqueProgramName(bundle.Result, $"UTTC_MS11_legacyfit_{Guid.NewGuid():N}");
var outputRoot = Path.Combine(AppContext.BaseDirectory, "Config", "Data", result.ProgramName);
var denseSendRoot = Path.Combine(outputRoot, "DenseSend");
var beforeRunDirectories = Directory.Exists(denseSendRoot)
? Directory.GetDirectories(denseSendRoot).ToHashSet(StringComparer.OrdinalIgnoreCase)
@@ -249,7 +249,7 @@ public sealed class FanucControllerRuntimeDenseTests
j519Client.EnableCommandHistoryForTests();
ForceRealModeEnabled(runtime, speedRatio: 1.0);
runtime.ExecuteTrajectory(bundle.Result, bundle.Result.DenseJointTrajectory![0].Skip(1).ToArray());
runtime.ExecuteTrajectory(result, result.DenseJointTrajectory![0].Skip(1).ToArray());
WaitUntilIdle(runtime);
var runDirectory = GetNewDenseSendRunDirectory(outputRoot, beforeRunDirectories);
@@ -269,6 +269,8 @@ public sealed class FanucControllerRuntimeDenseTests
Assert.NotEmpty(pointsLines);
Assert.NotEmpty(timingLines);
Assert.NotEmpty(jerkLines);
Assert.Equal(927, pointsLines.Length);
Assert.Equal(927, timingLines.Length);
var firstPoint = ParseColumns(pointsLines[0]);
var secondPoint = ParseColumns(pointsLines[1]);
@@ -282,7 +284,7 @@ public sealed class FanucControllerRuntimeDenseTests
const double windowHalfWidth = 0.024;
var summaryLines = new List<string>
{
$"program={bundle.Result.ProgramName}",
$"program={result.ProgramName}",
$"send_time_target_seconds={targetSendTime:F6}",
$"window_half_width_seconds={windowHalfWidth:F6}",
$"points_path={pointsPath}",
@@ -1121,16 +1123,8 @@ public sealed class FanucControllerRuntimeDenseTests
/// </summary>
private static UttcMs11RuntimeFixture LoadUttcMs11RuntimeFixture()
{
var configPath = Path.Combine(
TestRobotFactory.GetReplacementRoot(),
"src",
"Flyshot.Server.Host",
"bin",
"Debug",
"net8.0",
"Config",
"RobotConfig.json");
var configRoot = Path.GetDirectoryName(configPath)!;
var configRoot = TestRobotFactory.GetConfigRoot();
var configPath = Path.Combine(configRoot, "RobotConfig.json");
var loaded = new RobotConfigLoader().Load(configPath, configRoot);
var program = loaded.Programs["UTTC_MS11"];
var uploaded = new ControllerClientCompatUploadedTrajectory(
@@ -1149,6 +1143,26 @@ public sealed class FanucControllerRuntimeDenseTests
return new UttcMs11RuntimeFixture(configRoot, loaded.Robot, uploaded, robot);
}
/// <summary>
/// 复制一份结果并替换程序名,让 DenseSend 调试文件写入唯一目录,避免测试之间复用旧目录权限。
/// </summary>
private static TrajectoryResult WithUniqueProgramName(TrajectoryResult result, string programName)
{
return new TrajectoryResult(
programName: programName,
method: result.Method,
isValid: result.IsValid,
duration: result.Duration,
shotEvents: result.ShotEvents,
triggerTimeline: result.TriggerTimeline,
artifacts: result.Artifacts,
failureReason: result.FailureReason,
usedCache: result.UsedCache,
originalWaypointCount: result.OriginalWaypointCount,
plannedWaypointCount: result.PlannedWaypointCount,
denseJointTrajectory: result.DenseJointTrajectory);
}
/// <summary>
/// 解析空格分隔的纯文本数值列。
/// </summary>