using Flyshot.Core.Domain; using Flyshot.Runtime.Fanuc; namespace Flyshot.Core.Tests; /// /// 验证 FANUC 控制器运行在稠密轨迹流式执行与 IO 触发上的行为。 /// public sealed class FanucControllerRuntimeDenseTests { /// /// 验证仿真模式下即使传入稠密路点,也会回退到单点同步更新。 /// [Fact] public void ExecuteTrajectory_WithDenseWaypoints_SimulationMode_FallsBackToSinglePoint() { var runtime = new FanucControllerRuntime(); var robot = TestRobotFactory.CreateRobotProfile(); runtime.ResetRobot(robot, "FANUC_LR_Mate_200iD"); runtime.SetActiveController(sim: true); runtime.Connect("192.168.10.101"); runtime.EnableRobot(bufferSize: 2); var denseTrajectory = new[] { new[] { 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 }, new[] { 0.008, 0.11, 0.21, 0.31, 0.41, 0.51, 0.61 }, new[] { 0.016, 0.12, 0.22, 0.32, 0.42, 0.52, 0.62 } }; var result = new TrajectoryResult( programName: "demo", method: PlanningMethod.Icsp, isValid: true, duration: TimeSpan.FromSeconds(0.016), shotEvents: Array.Empty(), triggerTimeline: Array.Empty(), artifacts: Array.Empty(), failureReason: null, usedCache: false, originalWaypointCount: 4, plannedWaypointCount: 4, denseJointTrajectory: denseTrajectory); runtime.ExecuteTrajectory(result, [0.12, 0.22, 0.32, 0.42, 0.52, 0.62]); var snapshot = runtime.GetSnapshot(); Assert.False(snapshot.IsInMotion); Assert.Equal([0.12, 0.22, 0.32, 0.42, 0.52, 0.62], snapshot.JointPositions); } /// /// 验证 StopMove 在没有任何后台发送任务运行时不会抛出异常。 /// [Fact] public void StopMove_DoesNotThrowWhenNoSendTaskRunning() { var runtime = new FanucControllerRuntime(); var robot = TestRobotFactory.CreateRobotProfile(); runtime.ResetRobot(robot, "FANUC_LR_Mate_200iD"); runtime.SetActiveController(sim: true); runtime.Connect("192.168.10.101"); runtime.EnableRobot(bufferSize: 2); var exception = Record.Exception(() => runtime.StopMove()); Assert.Null(exception); Assert.False(runtime.GetSnapshot().IsInMotion); } /// /// 验证 IO 地址组中的地址号被正确映射为 writeIoValue 的位掩码。 /// [Theory] [InlineData(new[] { 0 }, (ushort)1)] [InlineData(new[] { 7 }, (ushort)128)] [InlineData(new[] { 7, 8 }, (ushort)384)] // 128 + 256 [InlineData(new[] { 15 }, (ushort)32768)] [InlineData(new int[] { }, (ushort)0)] public void ComputeIoValue_MapsAddressesToBitMask(int[] addresses, ushort expected) { var group = new IoAddressGroup(addresses); var actual = FanucControllerRuntime.ComputeIoValue(group); Assert.Equal(expected, actual); } /// /// 验证超过 15 的地址号会被安全忽略,不会溢出位掩码。 /// [Fact] public void ComputeIoValue_IgnoresOutOfRangeAddresses() { var group = new IoAddressGroup([0, 16, 7]); var actual = FanucControllerRuntime.ComputeIoValue(group); Assert.Equal((ushort)(1 | 128), actual); } }