feat(fanuc): 统一 speedRatio 执行倍率语义

* 将 speedRatio 前移到规划/准备阶段,运行时只消费已生成的 8ms 队列
* 区分旧格式规划导出与 ActualSend 实发诊断工件
* 补充普通轨迹、MoveJoint、飞拍队列和严格限幅回归测试
This commit is contained in:
2026-05-11 17:21:18 +08:00
parent d82128da4a
commit d120ef2a39
17 changed files with 1395 additions and 534 deletions

View File

@@ -158,6 +158,83 @@ public sealed class RuntimeOrchestrationTests
$"半速规划时长应接近全速的 2 倍,实际 full={fullSpeed.Result.Duration.TotalSeconds}, half={halfSpeed.Result.Duration.TotalSeconds}");
}
/// <summary>
/// 验证飞拍生成轨迹时会把 speed_ratio 折算进有效规划倍率,使倍率乘积相同的配置生成等价轨迹。
/// </summary>
[Fact]
public void ControllerClientTrajectoryOrchestrator_PlanUploadedFlyshot_UsesSpeedRatioAsPlanningScaleFactor()
{
var orchestrator = new ControllerClientTrajectoryOrchestrator();
var robot = TestRobotFactory.CreateRobotProfile();
var uploaded = TestRobotFactory.CreateUploadedTrajectoryWithSingleShot();
var planningSideSlowdown = CreateFlyshotSettings(planningSpeedScale: 0.45, speedRatio: 1.0);
var runtimeSideSlowdown = CreateFlyshotSettings(planningSpeedScale: 0.9, speedRatio: 0.5);
var planningSideBundle = orchestrator.PlanUploadedFlyshot(robot, uploaded, settings: planningSideSlowdown);
var runtimeSideBundle = orchestrator.PlanUploadedFlyshot(robot, uploaded, settings: runtimeSideSlowdown);
Assert.Equal(planningSideBundle.Result.Duration.TotalSeconds, runtimeSideBundle.Result.Duration.TotalSeconds, precision: 6);
Assert.Equal(planningSideBundle.ExecutionTrajectory.WaypointTimes.Count, runtimeSideBundle.ExecutionTrajectory.WaypointTimes.Count);
for (var index = 0; index < planningSideBundle.ExecutionTrajectory.WaypointTimes.Count; index++)
{
Assert.Equal(
planningSideBundle.ExecutionTrajectory.WaypointTimes[index],
runtimeSideBundle.ExecutionTrajectory.WaypointTimes[index],
precision: 6);
}
Assert.Equal(planningSideBundle.Result.DenseJointTrajectory!.Count, runtimeSideBundle.Result.DenseJointTrajectory!.Count);
for (var rowIndex = 0; rowIndex < planningSideBundle.Result.DenseJointTrajectory.Count; rowIndex++)
{
var planningSideRow = planningSideBundle.Result.DenseJointTrajectory[rowIndex];
var runtimeSideRow = runtimeSideBundle.Result.DenseJointTrajectory[rowIndex];
Assert.Equal(planningSideRow.Count, runtimeSideRow.Count);
for (var columnIndex = 0; columnIndex < planningSideRow.Count; columnIndex++)
{
Assert.Equal(planningSideRow[columnIndex], runtimeSideRow[columnIndex], precision: 6);
}
}
}
/// <summary>
/// 验证普通轨迹生成也会把 speed_ratio 折算进规划倍率,避免把限速留到发送阶段处理。
/// </summary>
[Fact]
public void ControllerClientTrajectoryOrchestrator_PlanOrdinaryTrajectory_UsesSpeedRatioAsPlanningScaleFactor()
{
var orchestrator = new ControllerClientTrajectoryOrchestrator();
var robot = TestRobotFactory.CreateRobotProfile();
var waypoints = new[]
{
new[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.001, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.002, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.003, 0.0, 0.0, 0.0, 0.0, 0.0 }
};
var planningSideBundle = orchestrator.PlanOrdinaryTrajectory(
robot,
waypoints,
planningSpeedScale: 0.45);
var runtimeSideBundle = orchestrator.PlanOrdinaryTrajectory(
robot,
waypoints,
planningSpeedScale: 0.9,
speedRatio: 0.5);
Assert.Equal(planningSideBundle.Result.Duration.TotalSeconds, runtimeSideBundle.Result.Duration.TotalSeconds, precision: 6);
Assert.Equal(planningSideBundle.Result.DenseJointTrajectory!.Count, runtimeSideBundle.Result.DenseJointTrajectory!.Count);
for (var rowIndex = 0; rowIndex < planningSideBundle.Result.DenseJointTrajectory.Count; rowIndex++)
{
var planningSideRow = planningSideBundle.Result.DenseJointTrajectory[rowIndex];
var runtimeSideRow = runtimeSideBundle.Result.DenseJointTrajectory[rowIndex];
for (var columnIndex = 0; columnIndex < planningSideRow.Count; columnIndex++)
{
Assert.Equal(planningSideRow[columnIndex], runtimeSideRow[columnIndex], precision: 6);
}
}
}
/// <summary>
/// 验证飞拍缓存键包含规划限速倍率,避免降速验证时误用 100% 速度下的规划结果。
/// </summary>
@@ -314,35 +391,37 @@ public sealed class RuntimeOrchestrationTests
{
var fixture = LoadUttcMs11RuntimeFixture();
var orchestrator = new ControllerClientTrajectoryOrchestrator();
var legacyFitSettings = DisableSmoothStartStopTiming(fixture.Settings);
var bundle = orchestrator.PlanUploadedFlyshot(
fixture.Robot,
fixture.Uploaded,
settings: fixture.Settings);
settings: legacyFitSettings);
var baselineBundle = orchestrator.PlanUploadedFlyshot(
fixture.Robot,
fixture.Uploaded,
settings: EnableSmoothStartStopTiming(fixture.Settings),
planningSpeedScale: 1.0);
var rawDense = TrajectorySampler.SampleJointTrajectory(
bundle.PlannedTrajectory,
var executionDense = TrajectorySampler.SampleJointTrajectory(
bundle.ExecutionTrajectory,
samplePeriod: fixture.Robot.ServoPeriod.TotalSeconds);
Assert.Equal(0.7422771653721995, fixture.Settings.PlanningSpeedScale, precision: 12);
Assert.False(fixture.Settings.SmoothStartStopTiming);
Assert.Equal(0.74227, legacyFitSettings.PlanningSpeedScale, precision: 6);
Assert.False(legacyFitSettings.SmoothStartStopTiming);
Assert.Equal(fixture.Uploaded.Waypoints.Count, bundle.PlannedTrajectory.WaypointTimes.Count);
Assert.Equal(
baselineBundle.PlannedTrajectory.WaypointTimes[^1] / fixture.Settings.PlanningSpeedScale,
baselineBundle.PlannedTrajectory.WaypointTimes[^1] / legacyFitSettings.PlanningSpeedScale,
bundle.PlannedTrajectory.WaypointTimes[^1],
precision: 6);
Assert.Equal(7.403046, bundle.PlannedTrajectory.WaypointTimes[^1], precision: 3);
// 关闭二次时间重映射时,运行时稠密点应直接使用规划样条采样,避免再次改变通用规划时间轴
Assert.Equal(rawDense.Count, bundle.Result.DenseJointTrajectory!.Count);
Assert.Equal(rawDense[1][1], bundle.Result.DenseJointTrajectory[1][1], precision: 12);
// 关闭二次时间重映射时,稠密点应和最终执行时间轴自洽;若离散限幅额外拉长,也要反映在 ExecutionTrajectory 上
Assert.Equal(executionDense.Count, bundle.Result.DenseJointTrajectory!.Count);
Assert.Equal(executionDense[1][1], bundle.Result.DenseJointTrajectory[1][1], precision: 12);
Assert.True(bundle.ExecutionTrajectory.WaypointTimes[^1] >= bundle.PlannedTrajectory.WaypointTimes[^1]);
Assert.True(
Math.Abs(bundle.PlannedTrajectory.WaypointTimes[^1] - bundle.Result.Duration.TotalSeconds) < 1e-6,
$"执行时长应保留规划终点时间planned={bundle.PlannedTrajectory.WaypointTimes[^1]}, result={bundle.Result.Duration.TotalSeconds}");
Math.Abs(bundle.ExecutionTrajectory.WaypointTimes[^1] - bundle.Result.Duration.TotalSeconds) < 1e-6,
$"执行时长应保留最终执行时间轴终点execution={bundle.ExecutionTrajectory.WaypointTimes[^1]}, result={bundle.Result.Duration.TotalSeconds}");
}
/// <summary>
@@ -697,6 +776,54 @@ public sealed class RuntimeOrchestrationTests
Assert.Throws<ArgumentException>(Act);
}
/// <summary>
/// 验证兼容服务执行普通轨迹时会把运行时 speed_ratio 前移到规划阶段。
/// </summary>
[Fact]
public void ControllerClientCompatService_ExecuteTrajectory_PassesSpeedRatioIntoOrdinaryPlanning()
{
var configRoot = CreateTempConfigRoot();
try
{
WriteRobotConfigWithDemoTrajectory(configRoot, planningSpeedScale: 0.9, speedRatio: 1.0);
var options = new ControllerClientCompatOptions { ConfigRoot = configRoot };
var runtime = new RecordingControllerRuntime();
var service = new ControllerClientCompatService(
options,
new ControllerClientCompatRobotCatalog(options, new RobotModelLoader()),
runtime,
new ControllerClientTrajectoryOrchestrator(),
new RobotConfigLoader());
var waypoints = new[]
{
new[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.001, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.002, 0.0, 0.0, 0.0, 0.0, 0.0 },
new[] { 0.003, 0.0, 0.0, 0.0, 0.0, 0.0 }
};
service.SetUpRobot("FANUC_LR_Mate_200iD");
service.SetActiveController(sim: false);
service.Connect("192.168.10.101");
service.EnableRobot(2);
runtime.SetSpeedRatio(0.5);
service.ExecuteTrajectory(waypoints);
var robot = new ControllerClientCompatRobotCatalog(options, new RobotModelLoader())
.LoadProfile("FANUC_LR_Mate_200iD", accLimitScale: 1.0, jerkLimitScale: 1.0);
var expected = new ControllerClientTrajectoryOrchestrator()
.PlanOrdinaryTrajectory(robot, waypoints, planningSpeedScale: 0.45);
var actual = Assert.IsType<TrajectoryResult>(runtime.LastExecutedResult);
Assert.Equal(expected.Result.Duration.TotalSeconds, actual.Duration.TotalSeconds, precision: 6);
Assert.Equal(expected.Result.DenseJointTrajectory!.Count, actual.DenseJointTrajectory!.Count);
}
finally
{
Directory.Delete(configRoot, recursive: true);
}
}
/// <summary>
/// 验证 ExecuteFlyShotTraj(move_to_start=true) 会先执行稠密 PTP 到起点,并等待该段运动完成后再启动飞拍轨迹。
/// </summary>
@@ -706,6 +833,7 @@ public sealed class RuntimeOrchestrationTests
var configRoot = CreateTempConfigRoot();
try
{
WriteRobotConfigWithDemoTrajectory(configRoot);
var options = new ControllerClientCompatOptions
{
ConfigRoot = configRoot
@@ -750,6 +878,7 @@ public sealed class RuntimeOrchestrationTests
var configRoot = CreateTempConfigRoot();
try
{
WriteRobotConfigWithDemoTrajectory(configRoot);
var options = new ControllerClientCompatOptions
{
ConfigRoot = configRoot
@@ -793,6 +922,7 @@ public sealed class RuntimeOrchestrationTests
var configRoot = CreateTempConfigRoot();
try
{
WriteRobotConfigWithDemoTrajectory(configRoot);
var options = new ControllerClientCompatOptions
{
ConfigRoot = configRoot
@@ -960,7 +1090,7 @@ public sealed class RuntimeOrchestrationTests
}
/// <summary>
/// 验证 SaveTrajectoryInfo 会同时导出按 J519 8ms 实发周期重采样的点位,并按执行侧稠密轨迹时长应用当前 speed_ratio。
/// 验证 SaveTrajectoryInfo 会导出按 J519 8ms 实发周期重采样的点位,并保留当前 speed_ratio 诊断信息
/// </summary>
[Fact]
public void ControllerClientCompatService_SaveTrajectoryInfo_ExportsActualSendRowsWithSpeedRatio()
@@ -994,17 +1124,21 @@ public sealed class RuntimeOrchestrationTests
var pointRows = File.ReadAllLines(pointsPath).Select(ParseSpaceSeparatedDoubles).ToArray();
var timingRows = File.ReadAllLines(timingPath).Select(ParseSpaceSeparatedDoubles).ToArray();
var shotEventsJson = File.ReadAllText(shotEventsPath);
var executionDuration = double.Parse(
var planningExportDuration = double.Parse(
File.ReadLines(Path.Combine(outputDir, "JointDetialTraj.txt")).Last().Split(' ')[0],
CultureInfo.InvariantCulture);
var minimumExpectedRows = (int)Math.Ceiling(Math.Max(0.0, (executionDuration / (0.008 * 0.5)) - 1e-9)) + 1;
var planningExportRowsAtServoPeriod = (int)Math.Ceiling(Math.Max(0.0, (planningExportDuration / 0.008) - 1e-9)) + 1;
Assert.Equal(pointRows.Length, timingRows.Length);
Assert.True(pointRows.Length >= minimumExpectedRows, $"最终发送点数应不少于请求倍率的首轮候选值actual={pointRows.Length}, min={minimumExpectedRows}");
Assert.True(
pointRows.Length > planningExportRowsAtServoPeriod,
$"ActualSend 应按当前 speedRatio 的执行视图导出,不能再用旧 JointDetialTraj 规划时长约束点数。actual={pointRows.Length}, planningRows={planningExportRowsAtServoPeriod}");
Assert.Equal(0.0, pointRows[0][0], precision: 6);
Assert.Equal(0.008, pointRows[1][0], precision: 6);
Assert.True(timingRows[1][2] <= 0.004 + 1e-6, $"自动拉长后 trajectory_time 推进不应快于请求倍率actual={timingRows[1][2]:F6}");
Assert.True(timingRows[1][3] <= 0.5 + 1e-6, $"最终采用倍率不应快于请求倍率actual={timingRows[1][3]:F6}");
Assert.Equal(0.008, timingRows[1][2], precision: 6);
Assert.Equal(1.0, timingRows[1][3], precision: 6);
Assert.Equal(0.5, timingRows[1][4], precision: 6);
Assert.Equal(0.0, timingRows[1][5], precision: 6);
Assert.Contains("\"trigger_window_seconds\": 0.1", shotEventsJson);
Assert.Contains("\"selected_sample_index\"", shotEventsJson);
}
@@ -1015,11 +1149,56 @@ public sealed class RuntimeOrchestrationTests
}
/// <summary>
/// 验证 saveTrajectory 导出的 JointDetialTraj.txt 来自执行侧 8ms 稠密轨迹的 16ms 视图,
/// 而不是再次从 PlannedTrajectory 独立重采样。
/// 验证 SaveTrajectoryInfo 的旧格式规划导出只受 planning_speed_scale 影响,不跟随运行时 speed_ratio 改变。
/// </summary>
[Fact]
public void FlyshotTrajectoryArtifactWriter_WriteUploadedFlyshot_JointDetailUsesExecutionDenseDownsample()
public void ControllerClientCompatService_SaveTrajectoryInfo_KeepsLegacyPlanningExportsIndependentFromSpeedRatio()
{
var fullSpeedRoot = CreateTempConfigRoot();
var halfSpeedRoot = CreateTempConfigRoot();
try
{
WriteRobotConfigWithDemoTrajectory(fullSpeedRoot, planningSpeedScale: 0.45, speedRatio: 1.0);
WriteRobotConfigWithDemoTrajectory(halfSpeedRoot, planningSpeedScale: 0.45, speedRatio: 0.5);
SaveDemoTrajectoryInfo(fullSpeedRoot);
SaveDemoTrajectoryInfo(halfSpeedRoot);
var fullSpeedOutput = Path.Combine(fullSpeedRoot, "Data", "demo-flyshot");
var halfSpeedOutput = Path.Combine(halfSpeedRoot, "Data", "demo-flyshot");
AssertNumericFilesEqual(
Path.Combine(fullSpeedOutput, "JointTraj.txt"),
Path.Combine(halfSpeedOutput, "JointTraj.txt"));
AssertNumericFilesEqual(
Path.Combine(fullSpeedOutput, "JointDetialTraj.txt"),
Path.Combine(halfSpeedOutput, "JointDetialTraj.txt"));
AssertNumericFilesEqual(
Path.Combine(fullSpeedOutput, "CartTraj.txt"),
Path.Combine(halfSpeedOutput, "CartTraj.txt"));
AssertNumericFilesEqual(
Path.Combine(fullSpeedOutput, "CartDetialTraj.txt"),
Path.Combine(halfSpeedOutput, "CartDetialTraj.txt"));
var fullSpeedActualSend = File.ReadAllLines(Path.Combine(fullSpeedOutput, "ActualSendJointTraj.txt"));
var halfSpeedActualSend = File.ReadAllLines(Path.Combine(halfSpeedOutput, "ActualSendJointTraj.txt"));
var fullSpeedTiming = File.ReadAllLines(Path.Combine(fullSpeedOutput, "ActualSendTiming.txt"));
var halfSpeedTiming = File.ReadAllLines(Path.Combine(halfSpeedOutput, "ActualSendTiming.txt"));
Assert.NotEqual(fullSpeedActualSend.Length, halfSpeedActualSend.Length);
Assert.NotEqual(fullSpeedTiming.Length, halfSpeedTiming.Length);
}
finally
{
Directory.Delete(fullSpeedRoot, recursive: true);
Directory.Delete(halfSpeedRoot, recursive: true);
}
}
/// <summary>
/// 验证 saveTrajectory 导出的 JointDetialTraj.txt 来自旧规划导出视图的 16ms 明细轨迹,
/// 而不是来自 speed_ratio 后的实发执行视图。
/// </summary>
[Fact]
public void FlyshotTrajectoryArtifactWriter_WriteUploadedFlyshot_JointDetailUsesExportPlanningDenseDownsample()
{
var fixture = LoadUttcMs11RuntimeFixture();
var configRoot = CreateTempConfigRoot();
@@ -1028,20 +1207,26 @@ public sealed class RuntimeOrchestrationTests
var options = new ControllerClientCompatOptions { ConfigRoot = configRoot };
var writer = new FlyshotTrajectoryArtifactWriter(options, new RobotModelLoader());
var orchestrator = new ControllerClientTrajectoryOrchestrator();
var bundle = orchestrator.PlanUploadedFlyshot(
var exportBundle = orchestrator.PlanUploadedFlyshot(
fixture.Robot,
fixture.Uploaded,
settings: EnableSmoothStartStopTiming(fixture.Settings),
planningSpeedScale: 1.0);
var executionBundle = orchestrator.PlanUploadedFlyshot(
fixture.Robot,
fixture.Uploaded,
settings: EnableSmoothStartStopTiming(fixture.Settings),
planningSpeedScale: 1.0,
speedRatio: 0.5);
writer.WriteUploadedFlyshot("UTTC_MS11", fixture.Robot, bundle, speedRatio: 1.0);
writer.WriteUploadedFlyshot("UTTC_MS11", fixture.Robot, exportBundle, executionBundle, speedRatio: 0.5);
var outputDir = Path.Combine(configRoot, "Data", "UTTC_MS11");
var exportedRows = File.ReadAllLines(Path.Combine(outputDir, "JointDetialTraj.txt"))
.Select(ParseSpaceSeparatedDoubles)
.ToArray();
var expectedRows = DownsampleDenseRows(
bundle.Result.DenseJointTrajectory!,
exportBundle.Result.DenseJointTrajectory!,
samplePeriodSeconds: 0.016)
.Select(static row => row.ToArray())
.ToArray();
@@ -1085,16 +1270,21 @@ public sealed class RuntimeOrchestrationTests
/// 写入包含一条飞拍轨迹的最小 RobotConfig.json供兼容服务从统一配置恢复轨迹。
/// </summary>
/// <param name="configRoot">测试运行配置根。</param>
private static void WriteRobotConfigWithDemoTrajectory(string configRoot)
private static void WriteRobotConfigWithDemoTrajectory(
string configRoot,
double planningSpeedScale = 0.45,
double speedRatio = 1.0)
{
File.WriteAllText(
Path.Combine(configRoot, "RobotConfig.json"),
"""
$$"""
{
"robot": {
"use_do": true,
"io_addr": [7, 8],
"io_keep_cycles": 2,
"speed_ratio": {{speedRatio.ToString(CultureInfo.InvariantCulture)}},
"planning_speed_scale": {{planningSpeedScale.ToString(CultureInfo.InvariantCulture)}},
"acc_limit": 1.0,
"jerk_limit": 1.0,
"adapt_icsp_try_num": 5
@@ -1103,9 +1293,9 @@ public sealed class RuntimeOrchestrationTests
"demo-flyshot": {
"traj_waypoints": [
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.1, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.2, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.3, 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]
],
"shot_flags": [false, true, false, false],
"offset_values": [0, 1, 0, 0],
@@ -1116,6 +1306,42 @@ public sealed class RuntimeOrchestrationTests
""");
}
/// <summary>
/// 使用指定运行配置根执行 demo-flyshot 的 SaveTrajectoryInfo。
/// </summary>
private static void SaveDemoTrajectoryInfo(string configRoot)
{
var options = new ControllerClientCompatOptions { ConfigRoot = configRoot };
var service = new ControllerClientCompatService(
options,
new ControllerClientCompatRobotCatalog(options, new RobotModelLoader()),
new RecordingControllerRuntime(),
new ControllerClientTrajectoryOrchestrator(),
new RobotConfigLoader());
service.SetUpRobot("FANUC_LR_Mate_200iD");
service.SaveTrajectoryInfo("demo-flyshot");
}
/// <summary>
/// 按数值逐行比较两个轨迹文本文件,避免纯文本格式差异影响判断。
/// </summary>
private static void AssertNumericFilesEqual(string expectedPath, string actualPath)
{
var expectedRows = File.ReadAllLines(expectedPath).Select(ParseSpaceSeparatedDoubles).ToArray();
var actualRows = File.ReadAllLines(actualPath).Select(ParseSpaceSeparatedDoubles).ToArray();
Assert.Equal(expectedRows.Length, actualRows.Length);
for (var rowIndex = 0; rowIndex < expectedRows.Length; rowIndex++)
{
Assert.Equal(expectedRows[rowIndex].Length, actualRows[rowIndex].Length);
for (var columnIndex = 0; columnIndex < expectedRows[rowIndex].Length; columnIndex++)
{
Assert.Equal(expectedRows[rowIndex][columnIndex], actualRows[rowIndex][columnIndex], precision: 6);
}
}
}
/// <summary>
/// 角度转弧度,供轨迹整形测试构造输入。
/// </summary>
@@ -1183,6 +1409,43 @@ public sealed class RuntimeOrchestrationTests
jerkLimitScale: settings.JerkLimitScale,
adaptIcspTryNum: settings.AdaptIcspTryNum,
planningSpeedScale: settings.PlanningSpeedScale,
speedRatio: settings.SpeedRatio,
smoothStartStopTiming: true);
}
/// <summary>
/// 为 legacy-fit 对比测试显式关闭二次时间重映射。
/// </summary>
private static CompatibilityRobotSettings DisableSmoothStartStopTiming(CompatibilityRobotSettings settings)
{
return new CompatibilityRobotSettings(
useDo: settings.UseDo,
ioAddresses: settings.IoAddresses,
ioKeepCycles: settings.IoKeepCycles,
triggerSampleIndexOffsetCycles: settings.TriggerSampleIndexOffsetCycles,
accLimitScale: settings.AccLimitScale,
jerkLimitScale: settings.JerkLimitScale,
adaptIcspTryNum: settings.AdaptIcspTryNum,
planningSpeedScale: settings.PlanningSpeedScale,
speedRatio: settings.SpeedRatio,
smoothStartStopTiming: false);
}
/// <summary>
/// 构造飞拍倍率测试使用的最小兼容设置。
/// </summary>
private static CompatibilityRobotSettings CreateFlyshotSettings(double planningSpeedScale, double speedRatio)
{
return new CompatibilityRobotSettings(
useDo: true,
ioAddresses: [7, 8],
ioKeepCycles: 2,
triggerSampleIndexOffsetCycles: 7,
accLimitScale: 1.0,
jerkLimitScale: 1.0,
adaptIcspTryNum: 5,
planningSpeedScale: planningSpeedScale,
speedRatio: speedRatio,
smoothStartStopTiming: true);
}
@@ -1555,9 +1818,9 @@ internal static class TestRobotFactory
waypoints:
[
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.1, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.2, 0.0, 0.0, 0.0, 0.0, 0.0],
[0.3, 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]
],
shotFlags: [false, true, false, false],
offsetValues: [0, 1, 0, 0],