* 新增 DebugConsoleController,提供 /debug 纯内嵌调试页 - 零外部依赖,基于 Swagger JSON 自动生成各端点表单 - 与 Swagger:Enabled 同步开关,避免生产环境误暴露 * 启用 <GenerateDocumentationFile>,将 XML 注释注入 OpenAPI - 调试页与 Swagger UI 共用同一份端点标题和说明 * 为 Health/Status/LegacyHttpApi 控制器添加 Tags 分组 * 补充 VS Code launch.json 与 tasks.json,支持现场调试 * 新增 DebugConsoleEndpointTests 覆盖调试页基础响应 * 同步更新 README 进度与待办清单
952 lines
29 KiB
C#
952 lines
29 KiB
C#
using System.Text.Json;
|
|
using Flyshot.ControllerClientCompat;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace Flyshot.Server.Host.Controllers;
|
|
|
|
/// <summary>
|
|
/// 提供对 `flyshot-uaes-interface` 既有 FastAPI HTTP 路由层的一比一 MVC 兼容控制器。
|
|
/// </summary>
|
|
[ApiController]
|
|
[Tags("ControllerClient 兼容")]
|
|
public sealed class LegacyHttpApiController : ControllerBase
|
|
{
|
|
private readonly IControllerClientCompatService _compatService;
|
|
|
|
/// <summary>
|
|
/// 初始化旧 HTTP 兼容控制器。
|
|
/// </summary>
|
|
/// <param name="compatService">ControllerClient 兼容服务。</param>
|
|
public LegacyHttpApiController(IControllerClientCompatService compatService)
|
|
{
|
|
_compatService = compatService ?? throw new ArgumentNullException(nameof(compatService));
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧根路径探活接口。
|
|
/// </summary>
|
|
/// <returns>旧 HTTP 服务约定的 Hello World 响应。</returns>
|
|
[HttpGet("/")]
|
|
public IActionResult Root()
|
|
{
|
|
return Ok(new { message = "Hello World" });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/connect_server/` 路由;在 replacement 宿主中仅记录调用方期望连接的地址。
|
|
/// </summary>
|
|
/// <param name="server_ip">旧客户端传入的服务端 IP。</param>
|
|
/// <param name="port">旧客户端传入的服务端端口。</param>
|
|
/// <returns>与旧 FastAPI 层一致的状态响应。</returns>
|
|
[HttpPost("/connect_server/")]
|
|
public IActionResult ConnectServer([FromQuery] string server_ip, [FromQuery] int port)
|
|
{
|
|
try
|
|
{
|
|
_compatService.ConnectServer(server_ip, port);
|
|
return Ok(new { status = "connected" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("Connect Server failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `GetServerVersion` 版本查询语义。
|
|
/// </summary>
|
|
/// <returns>服务端版本号。</returns>
|
|
[HttpGet("/get_server_version/")]
|
|
public IActionResult GetServerVersion()
|
|
{
|
|
return Ok(new { server_version = _compatService.GetServerVersion() });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `GetClientVersion` 版本查询语义。
|
|
/// </summary>
|
|
/// <returns>客户端版本号。</returns>
|
|
[HttpGet("/get_client_version/")]
|
|
public IActionResult GetClientVersion()
|
|
{
|
|
return Ok(new { client_version = _compatService.GetClientVersion() });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/setup_robot/` 路由。
|
|
/// </summary>
|
|
/// <param name="robot_name">旧 HTTP 层使用的机器人名称。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/setup_robot/")]
|
|
public IActionResult SetupRobot([FromQuery] string robot_name)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetUpRobot(robot_name);
|
|
return Ok(new { status = "robot setup" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SetUpRobot failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `SetUpRobotFromEnv(env_file)` 参数形状。
|
|
/// </summary>
|
|
/// <param name="env_file">环境文件路径。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/setup_robot_from_env/")]
|
|
public IActionResult SetupRobotFromEnv([FromQuery] string env_file)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetUpRobotFromEnv(env_file);
|
|
return Ok(new { status = "robot setup" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SetUpRobotFromEnv failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `SetShowTCP(is_show, axis_length, axis_size)` 参数形状。
|
|
/// </summary>
|
|
/// <param name="is_show">是否显示 TCP。</param>
|
|
/// <param name="axis_length">坐标轴长度。</param>
|
|
/// <param name="axis_size">坐标轴线宽。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/set_show_tcp/")]
|
|
public IActionResult SetShowTcp(
|
|
[FromQuery] bool is_show = true,
|
|
[FromQuery] double axis_length = 0.1,
|
|
[FromQuery] int axis_size = 2)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetShowTcp(is_show, axis_length, axis_size);
|
|
return Ok(new { status = "show TCP set" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SetShowTCP failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/is_setup/` 路由。
|
|
/// </summary>
|
|
/// <returns>当前机器人是否完成初始化。</returns>
|
|
[HttpGet("/is_setup/")]
|
|
public IActionResult IsSetup()
|
|
{
|
|
return Ok(new { is_setup = _compatService.IsSetUp });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `EnableRobot(buffer_size=2)` 参数形状。
|
|
/// </summary>
|
|
/// <param name="buffer_size">控制器执行缓冲区大小。</param>
|
|
/// <returns>旧 FastAPI 层风格的布尔状态响应。</returns>
|
|
[HttpGet("/enable_robot/")]
|
|
public IActionResult EnableRobot([FromQuery] int buffer_size = 2)
|
|
{
|
|
try
|
|
{
|
|
_compatService.EnableRobot(buffer_size);
|
|
return Ok(new { enable_robot = true });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("EnableRobot failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/disable_robot/` 路由。
|
|
/// </summary>
|
|
/// <returns>旧 FastAPI 层风格的布尔状态响应。</returns>
|
|
[HttpGet("/disable_robot/")]
|
|
public IActionResult DisableRobot()
|
|
{
|
|
try
|
|
{
|
|
_compatService.DisableRobot();
|
|
return Ok(new { disable_robot = true });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("DisableRobot failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提供与旧客户端 <c>StopMove</c> 语义对应的 HTTP 端点。
|
|
/// </summary>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpGet("/stop_move/")]
|
|
public IActionResult StopMove()
|
|
{
|
|
try
|
|
{
|
|
_compatService.StopMove();
|
|
return Ok(new { status = "move stopped" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("StopMove failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/set_active_controller/` 路由。
|
|
/// </summary>
|
|
/// <param name="sim">是否切到仿真控制器。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/set_active_controller/")]
|
|
public IActionResult SetActiveController([FromQuery] bool sim)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetActiveController(sim);
|
|
return Ok(new { status = "active controller set" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SetActiveController failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/connect_robot/` 路由。
|
|
/// </summary>
|
|
/// <param name="ip">控制器 IP。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/connect_robot/")]
|
|
public IActionResult ConnectRobot([FromQuery] string ip)
|
|
{
|
|
try
|
|
{
|
|
_compatService.Connect(ip);
|
|
return Ok(new { status = "robot connected" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("Connect failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 提供与旧客户端 <c>Disconnect</c> 语义对应的 HTTP 端点。
|
|
/// </summary>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/disconnect_robot/")]
|
|
public IActionResult DisconnectRobot()
|
|
{
|
|
try
|
|
{
|
|
_compatService.Disconnect();
|
|
return Ok(new { status = "robot disconnected" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("Disconnect failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/robot_info/` 路由。
|
|
/// </summary>
|
|
/// <returns>旧 HTTP 层聚合的机器人元信息。</returns>
|
|
[HttpGet("/robot_info/")]
|
|
public IActionResult GetRobotInfo()
|
|
{
|
|
try
|
|
{
|
|
return Ok(new
|
|
{
|
|
name = _compatService.GetRobotName(),
|
|
server_version = _compatService.ServerVersion,
|
|
dof = _compatService.GetDegreesOfFreedom(),
|
|
speed_ratio = _compatService.GetSpeedRatio()
|
|
});
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("GetRobotInfo failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/set_tcp/` 路由。
|
|
/// </summary>
|
|
/// <param name="tcp_data">三维 TCP 请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/set_tcp/")]
|
|
public IActionResult SetTcp([FromBody] LegacyTcpRequest tcp_data)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetTcp(tcp_data.x, tcp_data.y, tcp_data.z);
|
|
return Ok(new { status = "TCP set" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SetTCP failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/get_tcp/` 路由。
|
|
/// </summary>
|
|
/// <returns>当前 TCP 三维坐标。</returns>
|
|
[HttpGet("/get_tcp/")]
|
|
public IActionResult GetTcp()
|
|
{
|
|
try
|
|
{
|
|
return Ok(new { tcp = _compatService.GetTcp() });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("GetTCP failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/set_io/` 路由。
|
|
/// </summary>
|
|
/// <param name="port">IO 端口号。</param>
|
|
/// <param name="value">IO 值。</param>
|
|
/// <param name="io_type">IO 类型字符串。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/set_io/")]
|
|
public IActionResult SetIo([FromQuery] int port, [FromQuery] bool value, [FromQuery] string io_type)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetIo(port, value, io_type);
|
|
return Ok(new { status = "IO set" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SetDigitalOutput failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/get_io/` 路由。
|
|
/// </summary>
|
|
/// <param name="port">IO 端口号。</param>
|
|
/// <param name="io_type">IO 类型字符串。</param>
|
|
/// <returns>当前 IO 值。</returns>
|
|
[HttpGet("/get_io/")]
|
|
public IActionResult GetIo([FromQuery] int port, [FromQuery] string io_type)
|
|
{
|
|
try
|
|
{
|
|
return Ok(new { value = _compatService.GetIo(port, io_type) });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("GetDigitalOutput failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/get_joint_position/` 路由。
|
|
/// </summary>
|
|
/// <returns>旧 HTTP 层定义的关节位置 JSON 外形。</returns>
|
|
[HttpGet("/get_joint_position/")]
|
|
public IActionResult GetJointPosition()
|
|
{
|
|
try
|
|
{
|
|
return Ok(new { success = true, points = _compatService.GetJointPositions() });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("GetJointPosition failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/move_joint/` 路由。
|
|
/// </summary>
|
|
/// <param name="joint_data">关节位置请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/move_joint/")]
|
|
public IActionResult MoveJoint([FromBody] LegacyJointPositionRequest joint_data)
|
|
{
|
|
try
|
|
{
|
|
_compatService.MoveJoint(joint_data.joints);
|
|
return Ok(new { status = "robot moved" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("MoveJoint failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `GetNearestIK(pose, seed, ik)` 参数形状。
|
|
/// </summary>
|
|
/// <param name="request">IK 请求体。</param>
|
|
/// <returns>IK 结果。</returns>
|
|
[HttpPost("/get_nearest_ik/")]
|
|
public IActionResult GetNearestIk([FromBody] LegacyNearestIkRequest request)
|
|
{
|
|
try
|
|
{
|
|
return Ok(new { success = true, ik = _compatService.GetNearestIk(request.pose, request.seed) });
|
|
}
|
|
catch (NotSupportedException exception)
|
|
{
|
|
return StatusCode(StatusCodes.Status501NotImplemented, new { detail = exception.Message });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("GetNearestIK failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/list_flyShotTraj/` 路由。
|
|
/// </summary>
|
|
/// <returns>已上传飞拍轨迹名称列表。</returns>
|
|
[HttpGet("/list_flyShotTraj/")]
|
|
public IActionResult ListFlyshotTrajectories()
|
|
{
|
|
var names = _compatService.ListTrajectoryNames();
|
|
if (names.Count == 0)
|
|
{
|
|
return LegacyBadRequest("ListFlyShotTraj failed");
|
|
}
|
|
|
|
return Ok(new { flyshot_trajs = names });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/execute_trajectory/` 路由,并接受两种历史请求体形状。
|
|
/// </summary>
|
|
/// <param name="waypoints">轨迹请求体。</param>
|
|
/// <param name="method">查询字符串中的 method 覆盖值(兼容历史调用方式)。</param>
|
|
/// <param name="save_traj">查询字符串中的 save_traj 覆盖值(兼容历史调用方式)。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/execute_trajectory/")]
|
|
public IActionResult ExecuteTrajectory(
|
|
[FromBody] JsonElement waypoints,
|
|
[FromQuery] string? method = null,
|
|
[FromQuery] bool? save_traj = null)
|
|
{
|
|
try
|
|
{
|
|
var request = ParseExecuteTrajectoryRequest(waypoints, method, save_traj);
|
|
_compatService.ExecuteTrajectory(
|
|
request.Waypoints,
|
|
new TrajectoryExecutionOptions(request.Method, request.SaveTrajectory));
|
|
return Ok(new { status = "trajectory executed" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("ExecuteTrajectory failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/upload_flyshot/` 路由。
|
|
/// </summary>
|
|
/// <param name="trajectory_data">飞拍上传请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/upload_flyshot/")]
|
|
public IActionResult UploadFlyshot([FromBody] LegacyFlightTrajectoryRequest trajectory_data)
|
|
{
|
|
if (trajectory_data.shot_flags.Count != trajectory_data.waypoints.Count)
|
|
{
|
|
return LegacyValidationError("shot_flags长度必须与路点数量相同");
|
|
}
|
|
|
|
if (trajectory_data.offset_values.Count != trajectory_data.waypoints.Count)
|
|
{
|
|
return LegacyValidationError("offset_values长度必须与路点数量相同");
|
|
}
|
|
|
|
if (trajectory_data.addrs.Count != trajectory_data.waypoints.Count)
|
|
{
|
|
return LegacyValidationError("addrs长度必须与路点数量相同");
|
|
}
|
|
|
|
try
|
|
{
|
|
var trajectory = new ControllerClientCompatUploadedTrajectory(
|
|
name: trajectory_data.name,
|
|
waypoints: trajectory_data.waypoints,
|
|
shotFlags: trajectory_data.shot_flags,
|
|
offsetValues: trajectory_data.offset_values.Select(static value => (int)value),
|
|
addressGroups: trajectory_data.addrs);
|
|
|
|
_compatService.UploadTrajectory(trajectory);
|
|
return Ok(new { status = "FlyShot uploaded" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("UploadFlyShotTraj failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/execute_flyshot/` 路由。
|
|
/// </summary>
|
|
/// <param name="data">包含轨迹名称和执行参数的请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/execute_flyshot/")]
|
|
public IActionResult ExecuteFlyshot([FromBody] LegacyExecuteFlyshotRequest data)
|
|
{
|
|
try
|
|
{
|
|
_compatService.ExecuteTrajectoryByName(
|
|
data.name,
|
|
new FlyshotExecutionOptions(
|
|
moveToStart: data.move_to_start,
|
|
method: data.method,
|
|
saveTrajectory: data.save_traj,
|
|
useCache: data.use_cache));
|
|
return Ok(new { status = "FlyShot executed", success = true });
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
return StatusCode(StatusCodes.Status500InternalServerError, new { detail = exception.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `SaveTrajInfo(name, method)` 参数形状。
|
|
/// </summary>
|
|
/// <param name="request">轨迹保存请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/save_traj_info/")]
|
|
public IActionResult SaveTrajectoryInfo([FromBody] LegacyTrajectoryInfoRequest request)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SaveTrajectoryInfo(request.name, request.method);
|
|
return Ok(new { status = "trajectory info saved", success = true });
|
|
}
|
|
catch (NotSupportedException exception)
|
|
{
|
|
return StatusCode(StatusCodes.Status501NotImplemented, new { detail = exception.Message });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("SaveTrajInfo failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `IsFlyShotTrajValid(time, name, method, save_traj)` 参数形状。
|
|
/// </summary>
|
|
/// <param name="request">轨迹有效性检查请求体。</param>
|
|
/// <returns>有效性和轨迹时长。</returns>
|
|
[HttpPost("/is_flyShotTrajValid/")]
|
|
public IActionResult IsFlyshotTrajectoryValid([FromBody] LegacyFlyshotValidationRequest request)
|
|
{
|
|
try
|
|
{
|
|
var isValid = _compatService.IsFlyshotTrajectoryValid(
|
|
out var duration,
|
|
request.name,
|
|
request.method,
|
|
request.save_traj);
|
|
|
|
return Ok(new { success = isValid, valid = isValid, time = duration.TotalSeconds });
|
|
}
|
|
catch (NotSupportedException exception)
|
|
{
|
|
return StatusCode(StatusCodes.Status501NotImplemented, new { detail = exception.Message });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("IsFlyShotTrajValid failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/set_speedRatio/` 路由。
|
|
/// </summary>
|
|
/// <param name="data">速度倍率请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/set_speedRatio/")]
|
|
public IActionResult SetSpeedRatio([FromBody] LegacySpeedRatioRequest data)
|
|
{
|
|
try
|
|
{
|
|
_compatService.SetSpeedRatio(data.speed);
|
|
return Ok(new { message = "set_speedRatio executed", returnCode = 0 });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("set_speedRatio failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/delete_flyshot/` 路由。
|
|
/// </summary>
|
|
/// <param name="request">包含轨迹名称的请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的状态响应。</returns>
|
|
[HttpPost("/delete_flyshot/")]
|
|
public IActionResult DeleteFlyshot([FromBody] LegacyNameRequest request)
|
|
{
|
|
try
|
|
{
|
|
_compatService.DeleteTrajectory(request.name);
|
|
return Ok(new { status = "FlyShot deleted" });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("DeleteFlyShotTraj failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/init_mpc_robt` 路由,保留历史拼写。
|
|
/// </summary>
|
|
/// <param name="data">初始化请求体。</param>
|
|
/// <returns>旧 FastAPI 层风格的初始化结果。</returns>
|
|
[HttpPost("/init_mpc_robt")]
|
|
public IActionResult InitMpcRobot([FromBody] LegacyInitMpcRobotRequest data)
|
|
{
|
|
try
|
|
{
|
|
_compatService.ConnectServer(data.server_ip, data.port);
|
|
_compatService.SetUpRobot(data.robot_name);
|
|
if (!_compatService.IsSetUp)
|
|
{
|
|
return LegacyBadRequest("Robot not setup");
|
|
}
|
|
|
|
_compatService.SetActiveController(data.sim);
|
|
_compatService.Connect(data.robot_ip);
|
|
_compatService.EnableRobot(2);
|
|
return Ok(new { message = "init_Success", returnCode = 0 });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("Connect Server failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 兼容旧 `/get_pose` 路由。
|
|
/// </summary>
|
|
/// <returns>当前末端位姿数组。</returns>
|
|
[HttpGet("/get_pose")]
|
|
public IActionResult GetPose()
|
|
{
|
|
try
|
|
{
|
|
return Ok(new { pose = _compatService.GetPose() });
|
|
}
|
|
catch
|
|
{
|
|
return LegacyBadRequest("GetPose failed");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 解析旧 `/execute_trajectory/` 的完整参数形状。
|
|
/// </summary>
|
|
/// <param name="payload">原始 JSON 请求体。</param>
|
|
/// <param name="queryMethod">查询字符串中的 method 覆盖值。</param>
|
|
/// <param name="querySaveTrajectory">查询字符串中的 save_traj 覆盖值。</param>
|
|
/// <returns>统一后的路点和执行参数。</returns>
|
|
private static (
|
|
IReadOnlyList<IReadOnlyList<double>> Waypoints,
|
|
string Method,
|
|
bool SaveTrajectory) ParseExecuteTrajectoryRequest(
|
|
JsonElement payload,
|
|
string? queryMethod,
|
|
bool? querySaveTrajectory)
|
|
{
|
|
string method = queryMethod ?? "icsp";
|
|
bool saveTrajectory = querySaveTrajectory ?? false;
|
|
|
|
if (payload.ValueKind == JsonValueKind.Object)
|
|
{
|
|
if (payload.TryGetProperty("method", out var methodElement) && methodElement.ValueKind == JsonValueKind.String)
|
|
{
|
|
method = methodElement.GetString() ?? method;
|
|
}
|
|
|
|
if (payload.TryGetProperty("save_traj", out var saveTrajectoryElement))
|
|
{
|
|
saveTrajectory = saveTrajectoryElement.GetBoolean();
|
|
}
|
|
|
|
if (!payload.TryGetProperty("waypoints", out var waypointElement))
|
|
{
|
|
throw new InvalidOperationException("ExecuteTrajectory request body must include waypoints.");
|
|
}
|
|
|
|
return (ParseLegacyTrajectoryWaypoints(waypointElement), method, saveTrajectory);
|
|
}
|
|
|
|
return (ParseLegacyTrajectoryWaypoints(payload), method, saveTrajectory);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 解析旧 `/execute_trajectory/` 可能出现的两种历史请求体形状。
|
|
/// </summary>
|
|
/// <param name="waypoints">原始 JSON 请求体。</param>
|
|
/// <returns>统一后的关节路点集合。</returns>
|
|
private static IReadOnlyList<IReadOnlyList<double>> ParseLegacyTrajectoryWaypoints(JsonElement waypoints)
|
|
{
|
|
if (waypoints.ValueKind != JsonValueKind.Array)
|
|
{
|
|
throw new InvalidOperationException("ExecuteTrajectory request body must be an array.");
|
|
}
|
|
|
|
var parsedWaypoints = new List<IReadOnlyList<double>>();
|
|
foreach (var waypointElement in waypoints.EnumerateArray())
|
|
{
|
|
if (waypointElement.ValueKind == JsonValueKind.Array)
|
|
{
|
|
parsedWaypoints.Add(waypointElement.EnumerateArray().Select(static value => value.GetDouble()).ToArray());
|
|
continue;
|
|
}
|
|
|
|
if (waypointElement.ValueKind == JsonValueKind.Object && waypointElement.TryGetProperty("joints", out var jointElement))
|
|
{
|
|
parsedWaypoints.Add(jointElement.EnumerateArray().Select(static value => value.GetDouble()).ToArray());
|
|
continue;
|
|
}
|
|
|
|
throw new InvalidOperationException("Unsupported waypoint payload shape.");
|
|
}
|
|
|
|
return parsedWaypoints;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 构造与旧 FastAPI `HTTPException(status_code=400, detail=...)` 等价的响应。
|
|
/// </summary>
|
|
/// <param name="detail">错误详情文本。</param>
|
|
/// <returns>400 JSON 响应。</returns>
|
|
private BadRequestObjectResult LegacyBadRequest(string detail)
|
|
{
|
|
return BadRequest(new { detail });
|
|
}
|
|
|
|
/// <summary>
|
|
/// 构造与旧 FastAPI `422` 输入校验失败等价的响应。
|
|
/// </summary>
|
|
/// <param name="detail">错误详情文本。</param>
|
|
/// <returns>422 JSON 响应。</returns>
|
|
private ObjectResult LegacyValidationError(string detail)
|
|
{
|
|
return StatusCode(StatusCodes.Status422UnprocessableEntity, new { detail });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/set_tcp/` 路由使用的三维 TCP 请求体。
|
|
/// </summary>
|
|
public sealed class LegacyTcpRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置 TCP X。
|
|
/// </summary>
|
|
public double x { get; init; }
|
|
|
|
/// <summary>
|
|
/// 获取或设置 TCP Y。
|
|
/// </summary>
|
|
public double y { get; init; }
|
|
|
|
/// <summary>
|
|
/// 获取或设置 TCP Z。
|
|
/// </summary>
|
|
public double z { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/move_joint/` 路由使用的关节请求体。
|
|
/// </summary>
|
|
public sealed class LegacyJointPositionRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置目标关节数组。
|
|
/// </summary>
|
|
public List<double> joints { get; init; } = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/upload_flyshot/` 路由使用的飞拍上传请求体。
|
|
/// </summary>
|
|
public sealed class LegacyFlightTrajectoryRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置地址组集合。
|
|
/// </summary>
|
|
public List<List<int>> addrs { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// 获取或设置飞拍轨迹名称。
|
|
/// </summary>
|
|
public string name { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置偏移周期集合。
|
|
/// </summary>
|
|
public List<double> offset_values { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// 获取或设置拍照标志集合。
|
|
/// </summary>
|
|
public List<bool> shot_flags { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// 获取或设置关节路点集合。
|
|
/// </summary>
|
|
public List<List<double>> waypoints { get; init; } = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/execute_flyshot/` 与 `/delete_flyshot/` 路由使用的名称请求体。
|
|
/// </summary>
|
|
public sealed class LegacyNameRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置轨迹名称。
|
|
/// </summary>
|
|
public string name { get; init; } = string.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/execute_flyshot/` 路由使用的完整执行请求体。
|
|
/// </summary>
|
|
public sealed class LegacyExecuteFlyshotRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置轨迹名称。
|
|
/// </summary>
|
|
public string name { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置是否先移动到轨迹起点。
|
|
/// </summary>
|
|
public bool move_to_start { get; init; } = true;
|
|
|
|
/// <summary>
|
|
/// 获取或设置轨迹生成方法。
|
|
/// </summary>
|
|
public string method { get; init; } = "icsp";
|
|
|
|
/// <summary>
|
|
/// 获取或设置是否保存轨迹信息。
|
|
/// </summary>
|
|
public bool save_traj { get; init; } = true;
|
|
|
|
/// <summary>
|
|
/// 获取或设置是否复用轨迹缓存。
|
|
/// </summary>
|
|
public bool use_cache { get; init; } = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `SaveTrajInfo` 参数形状。
|
|
/// </summary>
|
|
public sealed class LegacyTrajectoryInfoRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置轨迹名称。
|
|
/// </summary>
|
|
public string name { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置轨迹生成方法。
|
|
/// </summary>
|
|
public string method { get; init; } = "icsp";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `IsFlyShotTrajValid` 参数形状。
|
|
/// </summary>
|
|
public sealed class LegacyFlyshotValidationRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置轨迹名称。
|
|
/// </summary>
|
|
public string name { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置轨迹生成方法。
|
|
/// </summary>
|
|
public string method { get; init; } = "icsp";
|
|
|
|
/// <summary>
|
|
/// 获取或设置是否保存轨迹信息。
|
|
/// </summary>
|
|
public bool save_traj { get; init; } = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `GetNearestIK` 参数形状。
|
|
/// </summary>
|
|
public sealed class LegacyNearestIkRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置目标位姿 `[x,y,z,qx,qy,qz,qw]`。
|
|
/// </summary>
|
|
public List<double> pose { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// 获取或设置 IK seed 关节数组。
|
|
/// </summary>
|
|
public List<double> seed { get; init; } = [];
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/set_speedRatio/` 路由使用的速度倍率请求体。
|
|
/// </summary>
|
|
public sealed class LegacySpeedRatioRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置目标速度倍率。
|
|
/// </summary>
|
|
public double speed { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 表示旧 `/init_mpc_robt` 路由使用的初始化请求体。
|
|
/// </summary>
|
|
public sealed class LegacyInitMpcRobotRequest
|
|
{
|
|
/// <summary>
|
|
/// 获取或设置目标服务端 IP。
|
|
/// </summary>
|
|
public string server_ip { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置目标服务端端口。
|
|
/// </summary>
|
|
public int port { get; init; }
|
|
|
|
/// <summary>
|
|
/// 获取或设置机器人名称。
|
|
/// </summary>
|
|
public string robot_name { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置机器人控制器 IP。
|
|
/// </summary>
|
|
public string robot_ip { get; init; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// 获取或设置是否使用仿真控制器;默认 false 连接真机。
|
|
/// </summary>
|
|
public bool sim { get; init; }
|
|
}
|