✨ feat(fanuc): 添加直角坐标点动功能与相关接口
* 新增 `MovePose` 方法,支持以直角坐标执行点到点移动。 * 引入 `LegacyCartesianPoseRequest` 类,处理直角位姿请求体的解析与验证。 * 更新 `LegacyHttpApiController`,实现 `/move_pose/` 路由以支持新功能。 * 增强状态快照元数据,提供机器人初始化状态与已上传轨迹信息。 * 更新前端状态页面,增加直角坐标点动控制面板与步长设置选项。 * 相关文档与测试用例同步更新,确保新功能的完整性与稳定性。
This commit is contained in:
@@ -44,6 +44,28 @@ public sealed class DebugConsoleEndpointTests(FlyshotServerFactory factory) : IC
|
||||
Assert.Contains("/api/debug/config", script, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 调试页应当为 MovePose 提供可直接发送的六字段请求体模板。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task GetDebugScript_ContainsMovePoseRequestSample()
|
||||
{
|
||||
using var configuredFactory = CreateFactoryWithSwaggerEnabled(true);
|
||||
using var client = configuredFactory.CreateClient();
|
||||
|
||||
using var scriptResponse = await client.GetAsync("/assets/debug.js");
|
||||
Assert.Equal(HttpStatusCode.OK, scriptResponse.StatusCode);
|
||||
|
||||
var script = await scriptResponse.Content.ReadAsStringAsync();
|
||||
Assert.Contains("/move_pose/", script, StringComparison.Ordinal);
|
||||
Assert.Contains("x: 100.0", script, StringComparison.Ordinal);
|
||||
Assert.Contains("y: 200.0", script, StringComparison.Ordinal);
|
||||
Assert.Contains("z: 300.0", script, StringComparison.Ordinal);
|
||||
Assert.Contains("w: 0.0", script, StringComparison.Ordinal);
|
||||
Assert.Contains("p: 45.0", script, StringComparison.Ordinal);
|
||||
Assert.Contains("r: 0.0", script, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当 Swagger 启用时,调试配置 API 应当返回实际 Swagger JSON 地址。
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Flyshot.Server.IntegrationTests;
|
||||
@@ -131,6 +132,13 @@ public sealed class LegacyHttpApiCompatibilityTests(FlyshotServerFactory factory
|
||||
Assert.Equal("robot moved", moveJointJson.RootElement.GetProperty("status").GetString());
|
||||
}
|
||||
|
||||
using (var movePoseResponse = await client.PostAsJsonAsync("/move_pose/", new { x = 100.0, y = 200.0, z = 300.0, w = 1.0, p = 2.0, r = 3.0 }))
|
||||
{
|
||||
Assert.Equal(HttpStatusCode.OK, movePoseResponse.StatusCode);
|
||||
using var movePoseJson = await ReadJsonAsync(movePoseResponse);
|
||||
Assert.Equal("robot moved", movePoseJson.RootElement.GetProperty("status").GetString());
|
||||
}
|
||||
|
||||
using (var getJointPositionResponse = await client.GetAsync("/get_joint_position/"))
|
||||
{
|
||||
Assert.Equal(HttpStatusCode.OK, getJointPositionResponse.StatusCode);
|
||||
@@ -165,6 +173,32 @@ public sealed class LegacyHttpApiCompatibilityTests(FlyshotServerFactory factory
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 MovePose 请求必须显式提供六个有限直角坐标字段,避免缺字段被模型绑定静默补 0。
|
||||
/// </summary>
|
||||
[Theory]
|
||||
[InlineData("""{"x":100.0,"y":200.0,"z":300.0,"w":1.0,"p":2.0}""")]
|
||||
[InlineData("null")]
|
||||
[InlineData("""{"x":1e999,"y":200.0,"z":300.0,"w":1.0,"p":2.0,"r":3.0}""")]
|
||||
[InlineData("""{"x":1000.1,"y":200.0,"z":300.0,"w":1.0,"p":2.0,"r":3.0}""")]
|
||||
[InlineData("""{"x":100.0,"y":-1000.1,"z":300.0,"w":1.0,"p":2.0,"r":3.0}""")]
|
||||
[InlineData("""{"x":100.0,"y":200.0,"z":-0.1,"w":1.0,"p":2.0,"r":3.0}""")]
|
||||
[InlineData("""{"x":100.0,"y":200.0,"z":300.0,"w":-180.1,"p":2.0,"r":3.0}""")]
|
||||
[InlineData("""{"x":100.0,"y":200.0,"z":300.0,"w":1.0,"p":90.1,"r":3.0}""")]
|
||||
[InlineData("""{"x":100.0,"y":200.0,"z":300.0,"w":1.0,"p":2.0,"r":180.1}""")]
|
||||
public async Task MovePose_InvalidPayload_ReturnsLegacyBadRequest(string payload)
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
await InitializeRobotAsync(client);
|
||||
|
||||
using var content = new StringContent(payload, Encoding.UTF8, "application/json");
|
||||
using var response = await client.PostAsync("/move_pose/", content);
|
||||
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
using var json = await ReadJsonAsync(response);
|
||||
Assert.Equal("MovePose failed", json.RootElement.GetProperty("detail").GetString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证飞拍 HTTP 接口可以按旧 API 层的路径和字段完成上传、列出、执行与删除。
|
||||
/// </summary>
|
||||
|
||||
@@ -34,6 +34,39 @@ public sealed class StatusEndpointTests(FlyshotServerFactory factory) : IClassFi
|
||||
Assert.Contains("/api/status/snapshot", script, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 状态页应当提供直角坐标点动按钮,并复用现有 MovePose HTTP 接口。
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task GetStatusPageAssets_ExposeCartesianJogControls()
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
|
||||
using var htmlResponse = await client.GetAsync("/status.html");
|
||||
Assert.Equal(HttpStatusCode.OK, htmlResponse.StatusCode);
|
||||
|
||||
var html = await htmlResponse.Content.ReadAsStringAsync();
|
||||
Assert.Contains("直角坐标点动", html, StringComparison.Ordinal);
|
||||
Assert.Contains("id=\"linear-step\"", html, StringComparison.Ordinal);
|
||||
Assert.Contains("id=\"angular-step\"", html, StringComparison.Ordinal);
|
||||
|
||||
foreach (var axis in new[] { "x", "y", "z", "w", "p", "r" })
|
||||
{
|
||||
Assert.Contains($"data-axis=\"{axis}\"", html, StringComparison.Ordinal);
|
||||
Assert.Contains($"data-axis=\"{axis}\" data-direction=\"1\"", html, StringComparison.Ordinal);
|
||||
Assert.Contains($"data-axis=\"{axis}\" data-direction=\"-1\"", html, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
using var scriptResponse = await client.GetAsync("/assets/status.js");
|
||||
Assert.Equal(HttpStatusCode.OK, scriptResponse.StatusCode);
|
||||
|
||||
var script = await scriptResponse.Content.ReadAsStringAsync();
|
||||
Assert.Contains("/move_pose/", script, StringComparison.Ordinal);
|
||||
Assert.Contains("cartesianPose", script, StringComparison.Ordinal);
|
||||
Assert.Contains("pointerdown", script, StringComparison.Ordinal);
|
||||
Assert.Contains("pointerup", script, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证状态快照 API 会返回运行时连接、使能、速度和机器人元数据。
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user