refactor(arm): 重构机械臂服务实现
- 将 HumanoidRobotService 重命名为 ArmService - 更新 EdgeTouchOperateService 中的服务依赖注入 - 修改 FlowiseActionService 中的机械臂服务引用 - 更新 GrpcServiceManager 中的客户端工厂注册 - 在 ActionEnum 中添加 ARM_MOVE_TO_POINT 动作类型 - 替换 EdgeMoveJVO 为 EdgeArmMoveJVO 模型类 - 更新触控操作中的机械臂移动方法调用参数
This commit is contained in:
parent
2d338d259b
commit
ac35fd229b
@ -0,0 +1,222 @@
|
|||||||
|
package com.cmvr.web.controller.api;
|
||||||
|
|
||||||
|
import cmvr.api.ArmCommand;
|
||||||
|
import cmvr.api.Common;
|
||||||
|
import com.cmvr.common.core.domain.AjaxResult;
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import com.cmvr.edge.client.model.arm.*;
|
||||||
|
import com.cmvr.edge.client.service.EdgeArmService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 边缘系统机械臂控制器
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Api(tags = "边缘--机械臂")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/arm")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EdgeArmController {
|
||||||
|
|
||||||
|
private final EdgeArmService edgeArmService;
|
||||||
|
|
||||||
|
@ApiOperation("关闭力矩")
|
||||||
|
@GetMapping("/torqueOff")
|
||||||
|
public AjaxResult torqueOff(EdgeCommonVO vo) {
|
||||||
|
Common.CommandHeader.Feedback result = edgeArmService.torqueOff(vo);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("开启力矩")
|
||||||
|
@GetMapping("/torqueOn")
|
||||||
|
public AjaxResult torqueOn(EdgeCommonVO vo) {
|
||||||
|
Common.CommandHeader.Feedback result = edgeArmService.torqueOn(vo);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("关节空间运动")
|
||||||
|
@PostMapping("/moveJ")
|
||||||
|
public AjaxResult moveJ(@RequestBody EdgeArmMoveJVO moveJVO) {
|
||||||
|
edgeArmService.moveJ(
|
||||||
|
moveJVO,
|
||||||
|
moveJVO.getTarget(),
|
||||||
|
moveJVO.getVelocity(),
|
||||||
|
moveJVO.getAcceleration(),
|
||||||
|
moveJVO.getBlendRadius(),
|
||||||
|
moveJVO.getJointVelocityLimits(),
|
||||||
|
moveJVO.getAsynchronous()
|
||||||
|
);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("笛卡尔空间直线运动")
|
||||||
|
@PostMapping("/moveL")
|
||||||
|
public AjaxResult moveL(@RequestBody EdgeArmMoveLVO moveLVO) {
|
||||||
|
edgeArmService.moveL(
|
||||||
|
moveLVO,
|
||||||
|
moveLVO.getX(),
|
||||||
|
moveLVO.getY(),
|
||||||
|
moveLVO.getZ(),
|
||||||
|
moveLVO.getRx(),
|
||||||
|
moveLVO.getRy(),
|
||||||
|
moveLVO.getRz(),
|
||||||
|
moveLVO.getFrame(),
|
||||||
|
moveLVO.getVelocity(),
|
||||||
|
moveLVO.getAcceleration(),
|
||||||
|
moveLVO.getBlendRadius()
|
||||||
|
);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("关节速度控制")
|
||||||
|
@PostMapping("/speedJ")
|
||||||
|
public AjaxResult speedJ(@RequestBody EdgeArmSpeedJVO speedJVO) {
|
||||||
|
edgeArmService.speedJ(
|
||||||
|
speedJVO,
|
||||||
|
speedJVO.getVelocities(),
|
||||||
|
speedJVO.getAcceleration(),
|
||||||
|
speedJVO.getDuration()
|
||||||
|
);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("笛卡尔速度控制")
|
||||||
|
@PostMapping("/speedL")
|
||||||
|
public AjaxResult speedL(@RequestBody EdgeArmSpeedLVO speedLVO) {
|
||||||
|
edgeArmService.speedL(
|
||||||
|
speedLVO,
|
||||||
|
speedLVO.getVx(),
|
||||||
|
speedLVO.getVy(),
|
||||||
|
speedLVO.getVz(),
|
||||||
|
speedLVO.getWx(),
|
||||||
|
speedLVO.getWy(),
|
||||||
|
speedLVO.getWz(),
|
||||||
|
speedLVO.getFrame(),
|
||||||
|
speedLVO.getAcceleration(),
|
||||||
|
speedLVO.getDuration()
|
||||||
|
);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("伺服关节控制")
|
||||||
|
@PostMapping("/servoJ")
|
||||||
|
public AjaxResult servoJ(@RequestBody EdgeArmServoJVO servoJVO) {
|
||||||
|
edgeArmService.servoJ(servoJVO, servoJVO.getTarget());
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("停止运动")
|
||||||
|
@GetMapping("/stopMotion")
|
||||||
|
public AjaxResult stopMotion(EdgeCommonVO vo) {
|
||||||
|
edgeArmService.stopMotion(vo);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取关节状态")
|
||||||
|
@GetMapping("/getJointState")
|
||||||
|
public AjaxResult getJointState(EdgeCommonVO vo) {
|
||||||
|
ArmCommand.JointResponse result = edgeArmService.getJointState(vo);
|
||||||
|
ArmCommand.JointState state = result.getState();
|
||||||
|
|
||||||
|
// 转换为VO
|
||||||
|
EdgeArmJointStateVO jointStateVO = new EdgeArmJointStateVO();
|
||||||
|
jointStateVO.setName(state.getNameList());
|
||||||
|
jointStateVO.setPosition(state.getPositionList());
|
||||||
|
jointStateVO.setVelocity(state.getVelocityList());
|
||||||
|
jointStateVO.setEffort(state.getEffortList());
|
||||||
|
jointStateVO.setTimestamp(state.getTimestamp());
|
||||||
|
|
||||||
|
return AjaxResult.ok(jointStateVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取末端位姿")
|
||||||
|
@GetMapping("/getPose")
|
||||||
|
public AjaxResult getPose(EdgeCommonVO vo, String baseLink, String eeLink) {
|
||||||
|
ArmCommand.GetPose.Response result = edgeArmService.getPose(vo, baseLink, eeLink);
|
||||||
|
ArmCommand.CartesianPose pose = result.getPose();
|
||||||
|
|
||||||
|
// 转换为VO
|
||||||
|
EdgeArmCartesianPoseVO poseVO = new EdgeArmCartesianPoseVO();
|
||||||
|
poseVO.setX(pose.getX());
|
||||||
|
poseVO.setY(pose.getY());
|
||||||
|
poseVO.setZ(pose.getZ());
|
||||||
|
poseVO.setRx(pose.getRx());
|
||||||
|
poseVO.setRy(pose.getRy());
|
||||||
|
poseVO.setRz(pose.getRz());
|
||||||
|
|
||||||
|
return AjaxResult.ok(poseVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("标定零点")
|
||||||
|
@GetMapping("/calibrateZeroQ")
|
||||||
|
public AjaxResult calibrateZeroQ(EdgeCommonVO vo, String jointName) {
|
||||||
|
edgeArmService.calibrateZeroQ(vo, jointName);
|
||||||
|
return AjaxResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取位姿矩阵")
|
||||||
|
@GetMapping("/getPoseMatrix")
|
||||||
|
public AjaxResult getPoseMatrix(EdgeCommonVO vo, String baseLink, String eeLink) {
|
||||||
|
ArmCommand.GetPoseMatrix.Response result = edgeArmService.getPoseMatrix(vo, baseLink, eeLink);
|
||||||
|
// 将TransformMatrix4x4转换为Map
|
||||||
|
ArmCommand.TransformMatrix4x4 matrix = result.getMatrix();
|
||||||
|
java.util.Map<String, Object> matrixMap = new java.util.HashMap<>();
|
||||||
|
matrixMap.put("m00", matrix.getM00());
|
||||||
|
matrixMap.put("m01", matrix.getM01());
|
||||||
|
matrixMap.put("m02", matrix.getM02());
|
||||||
|
matrixMap.put("m03", matrix.getM03());
|
||||||
|
matrixMap.put("m10", matrix.getM10());
|
||||||
|
matrixMap.put("m11", matrix.getM11());
|
||||||
|
matrixMap.put("m12", matrix.getM12());
|
||||||
|
matrixMap.put("m13", matrix.getM13());
|
||||||
|
matrixMap.put("m20", matrix.getM20());
|
||||||
|
matrixMap.put("m21", matrix.getM21());
|
||||||
|
matrixMap.put("m22", matrix.getM22());
|
||||||
|
matrixMap.put("m23", matrix.getM23());
|
||||||
|
matrixMap.put("m30", matrix.getM30());
|
||||||
|
matrixMap.put("m31", matrix.getM31());
|
||||||
|
matrixMap.put("m32", matrix.getM32());
|
||||||
|
matrixMap.put("m33", matrix.getM33());
|
||||||
|
return AjaxResult.ok(matrixMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("计算正向运动学")
|
||||||
|
@PostMapping("/computeForwardKinematics")
|
||||||
|
public AjaxResult computeForwardKinematics(@RequestBody EdgeArmForwardKinematicsVO fkVO) {
|
||||||
|
ArmCommand.ComputeForwardKinematics.Response result = edgeArmService.computeForwardKinematics(
|
||||||
|
fkVO,
|
||||||
|
fkVO.getJoints(),
|
||||||
|
fkVO.getBaseLink(),
|
||||||
|
fkVO.getEeLink()
|
||||||
|
);
|
||||||
|
// 将TransformMatrix4x4转换为Map
|
||||||
|
ArmCommand.TransformMatrix4x4 matrix = result.getMatrix();
|
||||||
|
java.util.Map<String, Object> matrixMap = new java.util.HashMap<>();
|
||||||
|
matrixMap.put("m00", matrix.getM00());
|
||||||
|
matrixMap.put("m01", matrix.getM01());
|
||||||
|
matrixMap.put("m02", matrix.getM02());
|
||||||
|
matrixMap.put("m03", matrix.getM03());
|
||||||
|
matrixMap.put("m10", matrix.getM10());
|
||||||
|
matrixMap.put("m11", matrix.getM11());
|
||||||
|
matrixMap.put("m12", matrix.getM12());
|
||||||
|
matrixMap.put("m13", matrix.getM13());
|
||||||
|
matrixMap.put("m20", matrix.getM20());
|
||||||
|
matrixMap.put("m21", matrix.getM21());
|
||||||
|
matrixMap.put("m22", matrix.getM22());
|
||||||
|
matrixMap.put("m23", matrix.getM23());
|
||||||
|
matrixMap.put("m30", matrix.getM30());
|
||||||
|
matrixMap.put("m31", matrix.getM31());
|
||||||
|
matrixMap.put("m32", matrix.getM32());
|
||||||
|
matrixMap.put("m33", matrix.getM33());
|
||||||
|
return AjaxResult.ok(matrixMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,55 +0,0 @@
|
|||||||
package com.cmvr.web.controller.api;
|
|
||||||
|
|
||||||
import com.cmvr.common.core.domain.AjaxResult;
|
|
||||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeMoveJVO;
|
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeSpeedJVO;
|
|
||||||
import com.cmvr.edge.client.service.EdgeHumanoidRobotService;
|
|
||||||
import io.swagger.annotations.Api;
|
|
||||||
import io.swagger.annotations.ApiOperation;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
@Api(tags = "边缘--机械臂")
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/api/humanoid")
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class EdgeHumanoidRobotController {
|
|
||||||
|
|
||||||
private final EdgeHumanoidRobotService edgeHumanoidRobotService;
|
|
||||||
|
|
||||||
@ApiOperation("moveJ")
|
|
||||||
@PostMapping("/moveJ")
|
|
||||||
public AjaxResult moveJ(@RequestBody EdgeMoveJVO moveJVO) {
|
|
||||||
return AjaxResult.ok(edgeHumanoidRobotService.moveJ(moveJVO));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("speedJ")
|
|
||||||
@PostMapping("/speedJ")
|
|
||||||
public AjaxResult speedJ(@RequestBody EdgeSpeedJVO speedJVO) {
|
|
||||||
return AjaxResult.ok(edgeHumanoidRobotService.speedJ(speedJVO));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("获取关节状态")
|
|
||||||
@GetMapping("/getJointState")
|
|
||||||
public AjaxResult status(EdgeCommonVO vo) {
|
|
||||||
return AjaxResult.ok(edgeHumanoidRobotService.getJointState(vo));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("使能开")
|
|
||||||
@GetMapping("/torqueOn")
|
|
||||||
public AjaxResult torqueOn(EdgeCommonVO vo) {
|
|
||||||
return AjaxResult.ok(edgeHumanoidRobotService.torqueOn(vo));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation("使能关")
|
|
||||||
@GetMapping("/torqueOff")
|
|
||||||
public AjaxResult torqueOff(EdgeCommonVO vo) {
|
|
||||||
return AjaxResult.ok(edgeHumanoidRobotService.torqueOff(vo));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -55,7 +55,7 @@ public class GrpcServiceManager {
|
|||||||
clientFactories.put(DexHandServiceGrpc.DexHandServiceBlockingStub.class, new GrpcClientFactory<>(DexHandServiceGrpc::newBlockingStub));
|
clientFactories.put(DexHandServiceGrpc.DexHandServiceBlockingStub.class, new GrpcClientFactory<>(DexHandServiceGrpc::newBlockingStub));
|
||||||
clientFactories.put(DexHandServiceGrpc.DexHandServiceStub.class, new GrpcClientFactory<>(DexHandServiceGrpc::newStub));
|
clientFactories.put(DexHandServiceGrpc.DexHandServiceStub.class, new GrpcClientFactory<>(DexHandServiceGrpc::newStub));
|
||||||
// 注册机械臂服务的stub
|
// 注册机械臂服务的stub
|
||||||
clientFactories.put(HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class, new GrpcClientFactory<>(HumanoidRobotServiceGrpc::newBlockingStub));
|
clientFactories.put(ArmServiceGrpc.ArmServiceBlockingStub.class, new GrpcClientFactory<>(ArmServiceGrpc::newBlockingStub));
|
||||||
clientFactories.put(HlcServiceGrpc.HlcServiceBlockingStub.class, new GrpcClientFactory<>(HlcServiceGrpc::newBlockingStub));
|
clientFactories.put(HlcServiceGrpc.HlcServiceBlockingStub.class, new GrpcClientFactory<>(HlcServiceGrpc::newBlockingStub));
|
||||||
// 注册agv服务的stub
|
// 注册agv服务的stub
|
||||||
clientFactories.put(AgvServiceGrpc.AgvServiceBlockingStub.class, new GrpcClientFactory<>(AgvServiceGrpc::newBlockingStub));
|
clientFactories.put(AgvServiceGrpc.AgvServiceBlockingStub.class, new GrpcClientFactory<>(AgvServiceGrpc::newBlockingStub));
|
||||||
|
|||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂笛卡尔位姿VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("机械臂笛卡尔位姿")
|
||||||
|
public class EdgeArmCartesianPoseVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("X轴坐标(单位:米)")
|
||||||
|
private double x;
|
||||||
|
|
||||||
|
@ApiModelProperty("Y轴坐标(单位:米)")
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
@ApiModelProperty("Z轴坐标(单位:米)")
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
@ApiModelProperty("RX旋转角度(单位:弧度)")
|
||||||
|
private double rx;
|
||||||
|
|
||||||
|
@ApiModelProperty("RY旋转角度(单位:弧度)")
|
||||||
|
private double ry;
|
||||||
|
|
||||||
|
@ApiModelProperty("RZ旋转角度(单位:弧度)")
|
||||||
|
private double rz;
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂正向运动学计算VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂正向运动学计算参数")
|
||||||
|
public class EdgeArmForwardKinematicsVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "关节位置数组(6个关节角度,单位:弧度)", required = true)
|
||||||
|
private double[] joints;
|
||||||
|
|
||||||
|
@ApiModelProperty("基座连杆名称")
|
||||||
|
private String baseLink;
|
||||||
|
|
||||||
|
@ApiModelProperty("末端执行器连杆名称")
|
||||||
|
private String eeLink;
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂关节状态VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("机械臂关节状态")
|
||||||
|
public class EdgeArmJointStateVO {
|
||||||
|
|
||||||
|
@ApiModelProperty("关节名称列表")
|
||||||
|
private List<String> name;
|
||||||
|
|
||||||
|
@ApiModelProperty("关节位置列表(单位:弧度)")
|
||||||
|
private List<Double> position;
|
||||||
|
|
||||||
|
@ApiModelProperty("关节速度列表(单位:rad/s)")
|
||||||
|
private List<Double> velocity;
|
||||||
|
|
||||||
|
@ApiModelProperty("关节力矩列表")
|
||||||
|
private List<Double> effort;
|
||||||
|
|
||||||
|
@ApiModelProperty("时间戳")
|
||||||
|
private double timestamp;
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂关节空间运动VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂关节空间运动参数")
|
||||||
|
public class EdgeArmMoveJVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "目标关节位置数组(6个关节角度,单位:弧度)", required = true)
|
||||||
|
private double[] target;
|
||||||
|
|
||||||
|
@ApiModelProperty("运动速度(单位:m/s)")
|
||||||
|
private Double velocity;
|
||||||
|
|
||||||
|
@ApiModelProperty("加速度(单位:m/s²)")
|
||||||
|
private Double acceleration;
|
||||||
|
|
||||||
|
@ApiModelProperty("融合半径(单位:m)")
|
||||||
|
private Double blendRadius;
|
||||||
|
|
||||||
|
@ApiModelProperty("关节速度限制数组")
|
||||||
|
private double[] jointVelocityLimits;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否异步执行")
|
||||||
|
private Boolean asynchronous;
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂笛卡尔空间直线运动VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂笛卡尔空间直线运动参数")
|
||||||
|
public class EdgeArmMoveLVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "X轴坐标(单位:米)", required = true)
|
||||||
|
private double x;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Y轴坐标(单位:米)", required = true)
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Z轴坐标(单位:米)", required = true)
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RX旋转角度(单位:弧度)", required = true)
|
||||||
|
private double rx;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RY旋转角度(单位:弧度)", required = true)
|
||||||
|
private double ry;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RZ旋转角度(单位:弧度)", required = true)
|
||||||
|
private double rz;
|
||||||
|
|
||||||
|
@ApiModelProperty("坐标系类型(BASE/TOOL/WORLD/USER)")
|
||||||
|
private String frame;
|
||||||
|
|
||||||
|
@ApiModelProperty("运动速度(单位:m/s)")
|
||||||
|
private Double velocity;
|
||||||
|
|
||||||
|
@ApiModelProperty("加速度(单位:m/s²)")
|
||||||
|
private Double acceleration;
|
||||||
|
|
||||||
|
@ApiModelProperty("融合半径(单位:m)")
|
||||||
|
private Double blendRadius;
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂末端运动到指定点VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂末端运动到指定点参数")
|
||||||
|
public class EdgeArmMoveToPointVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "X轴坐标(单位:米)", required = true)
|
||||||
|
private double x;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Y轴坐标(单位:米)", required = true)
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Z轴坐标(单位:米)", required = true)
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RX旋转角度(单位:弧度)", required = true)
|
||||||
|
private double rx;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RY旋转角度(单位:弧度)", required = true)
|
||||||
|
private double ry;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RZ旋转角度(单位:弧度)", required = true)
|
||||||
|
private double rz;
|
||||||
|
|
||||||
|
@ApiModelProperty("坐标系类型(BASE/TOOL/WORLD/USER)")
|
||||||
|
private String frame;
|
||||||
|
|
||||||
|
@ApiModelProperty("运动速度(单位:m/s)")
|
||||||
|
private Double velocity;
|
||||||
|
|
||||||
|
@ApiModelProperty("加速度(单位:m/s²)")
|
||||||
|
private Double acceleration;
|
||||||
|
|
||||||
|
@ApiModelProperty("融合半径(单位:m)")
|
||||||
|
private Double blendRadius;
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂伺服关节控制VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂伺服关节控制参数")
|
||||||
|
public class EdgeArmServoJVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "目标关节位置数组(6个关节角度,单位:弧度)", required = true)
|
||||||
|
private double[] target;
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂关节速度控制VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂关节速度控制参数")
|
||||||
|
public class EdgeArmSpeedJVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "关节速度数组(6个关节速度,单位:rad/s)", required = true)
|
||||||
|
private double[] velocities;
|
||||||
|
|
||||||
|
@ApiModelProperty("加速度(单位:rad/s²)")
|
||||||
|
private Double acceleration;
|
||||||
|
|
||||||
|
@ApiModelProperty("持续时间(单位:秒)")
|
||||||
|
private Double duration;
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package com.cmvr.edge.client.model.arm;
|
||||||
|
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂笛卡尔速度控制VO
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("机械臂笛卡尔速度控制参数")
|
||||||
|
public class EdgeArmSpeedLVO extends EdgeCommonVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "X轴速度(单位:m/s)", required = true)
|
||||||
|
private double vx;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Y轴速度(单位:m/s)", required = true)
|
||||||
|
private double vy;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "Z轴速度(单位:m/s)", required = true)
|
||||||
|
private double vz;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RX角速度(单位:rad/s)", required = true)
|
||||||
|
private double wx;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RY角速度(单位:rad/s)", required = true)
|
||||||
|
private double wy;
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "RZ角速度(单位:rad/s)", required = true)
|
||||||
|
private double wz;
|
||||||
|
|
||||||
|
@ApiModelProperty("坐标系类型(BASE/TOOL/WORLD/USER)")
|
||||||
|
private String frame;
|
||||||
|
|
||||||
|
@ApiModelProperty("加速度(单位:m/s²)")
|
||||||
|
private Double acceleration;
|
||||||
|
|
||||||
|
@ApiModelProperty("持续时间(单位:秒)")
|
||||||
|
private Double duration;
|
||||||
|
}
|
||||||
@ -1,22 +0,0 @@
|
|||||||
package com.cmvr.edge.client.model.humanoid;
|
|
||||||
|
|
||||||
import cmvr.api.HumanoidRobotCommand;
|
|
||||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class EdgeSpeedJVO extends EdgeCommonVO {
|
|
||||||
/** 关节角速度 (rad/s) */
|
|
||||||
private double vel;
|
|
||||||
|
|
||||||
/** 加速度 (rad/s^2) */
|
|
||||||
private double acc;
|
|
||||||
|
|
||||||
/** 关节名称 */
|
|
||||||
private String jointName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 角度
|
|
||||||
*/
|
|
||||||
private HumanoidRobotCommand.RobotJointIndexDirection dir;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
package com.cmvr.edge.client.service;
|
||||||
|
|
||||||
|
import cmvr.api.ArmCommand;
|
||||||
|
import cmvr.api.Common;
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 边缘系统机械臂服务
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
public interface EdgeArmService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭力矩(命令码:torqueOff)
|
||||||
|
* 关闭机械臂的力矩控制,使机械臂进入自由拖动模式
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
Common.CommandHeader.Feedback torqueOff(EdgeCommonVO edgeCommonVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开启力矩(命令码:torqueOn)
|
||||||
|
* 开启机械臂的力矩控制,使机械臂进入受控状态
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
Common.CommandHeader.Feedback torqueOn(EdgeCommonVO edgeCommonVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关节空间运动(命令码:moveJ)
|
||||||
|
* 控制机械臂通过关节空间插值运动到目标关节位置
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param target 目标关节位置数组(6个关节角度,单位:弧度)
|
||||||
|
* @param velocity 运动速度(单位:m/s,可选)
|
||||||
|
* @param acceleration 加速度(单位:m/s²,可选)
|
||||||
|
* @param blendRadius 融合半径(单位:m,可选)
|
||||||
|
* @param jointVelocityLimits 关节速度限制数组(可选)
|
||||||
|
* @param asynchronous 是否异步执行(可选)
|
||||||
|
* @return 运动结果
|
||||||
|
*/
|
||||||
|
ArmCommand.MoveJ.Response moveJ(EdgeCommonVO edgeCommonVO, double[] target, Double velocity,
|
||||||
|
Double acceleration, Double blendRadius,
|
||||||
|
double[] jointVelocityLimits, Boolean asynchronous);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 笛卡尔空间直线运动(命令码:moveL)
|
||||||
|
* 控制机械臂在笛卡尔空间中沿直线运动到目标位姿
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param x X轴坐标(单位:米)
|
||||||
|
* @param y Y轴坐标(单位:米)
|
||||||
|
* @param z Z轴坐标(单位:米)
|
||||||
|
* @param rx RX旋转角度(单位:弧度)
|
||||||
|
* @param ry RY旋转角度(单位:弧度)
|
||||||
|
* @param rz RZ旋转角度(单位:弧度)
|
||||||
|
* @param frame 坐标系类型(BASE/TOOL/WORLD/USER)
|
||||||
|
* @param velocity 运动速度(单位:m/s,可选)
|
||||||
|
* @param acceleration 加速度(单位:m/s²,可选)
|
||||||
|
* @param blendRadius 融合半径(单位:m,可选)
|
||||||
|
* @return 运动结果
|
||||||
|
*/
|
||||||
|
ArmCommand.MoveL.Response moveL(EdgeCommonVO edgeCommonVO, double x, double y, double z,
|
||||||
|
double rx, double ry, double rz, String frame,
|
||||||
|
Double velocity, Double acceleration, Double blendRadius);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关节速度控制(命令码:speedJ)
|
||||||
|
* 控制机械臂各关节以指定速度运动
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param velocities 关节速度数组(6个关节速度,单位:rad/s)
|
||||||
|
* @param acceleration 加速度(单位:rad/s²,可选)
|
||||||
|
* @param duration 持续时间(单位:秒,可选)
|
||||||
|
* @return 控制结果
|
||||||
|
*/
|
||||||
|
ArmCommand.SpeedJ.Response speedJ(EdgeCommonVO edgeCommonVO, double[] velocities,
|
||||||
|
Double acceleration, Double duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 笛卡尔速度控制(命令码:speedL)
|
||||||
|
* 控制机械臂末端以指定笛卡尔速度运动
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param vx X轴速度(单位:m/s)
|
||||||
|
* @param vy Y轴速度(单位:m/s)
|
||||||
|
* @param vz Z轴速度(单位:m/s)
|
||||||
|
* @param wx RX角速度(单位:rad/s)
|
||||||
|
* @param wy RY角速度(单位:rad/s)
|
||||||
|
* @param wz RZ角速度(单位:rad/s)
|
||||||
|
* @param frame 坐标系类型(BASE/TOOL/WORLD/USER)
|
||||||
|
* @param acceleration 加速度(单位:m/s²,可选)
|
||||||
|
* @param duration 持续时间(单位:秒,可选)
|
||||||
|
* @return 控制结果
|
||||||
|
*/
|
||||||
|
ArmCommand.SpeedL.Response speedL(EdgeCommonVO edgeCommonVO, double vx, double vy, double vz,
|
||||||
|
double wx, double wy, double wz, String frame,
|
||||||
|
Double acceleration, Double duration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 伺服关节控制(命令码:servoJ)
|
||||||
|
* 实时控制机械臂关节位置,用于高频控制场景
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param target 目标关节位置数组(6个关节角度,单位:弧度)
|
||||||
|
* @return 控制结果
|
||||||
|
*/
|
||||||
|
ArmCommand.ServoJ.Response servoJ(EdgeCommonVO edgeCommonVO, double[] target);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止运动(命令码:stopMotion)
|
||||||
|
* 立即停止机械臂当前正在执行的所有运动
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @return 停止结果
|
||||||
|
*/
|
||||||
|
Common.CommandHeader.Feedback stopMotion(EdgeCommonVO edgeCommonVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取关节状态(命令码:getJointState)
|
||||||
|
* 获取机械臂当前各关节的位置、速度和力矩信息
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @return 关节状态信息
|
||||||
|
*/
|
||||||
|
ArmCommand.JointResponse getJointState(EdgeCommonVO edgeCommonVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取末端位姿(命令码:getPose)
|
||||||
|
* 获取机械臂末端执行器相对于基座的笛卡尔位姿
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param baseLink 基座连杆名称(可选,默认为base)
|
||||||
|
* @param eeLink 末端执行器连杆名称(可选,默认为tool0)
|
||||||
|
* @return 末端位姿信息
|
||||||
|
*/
|
||||||
|
ArmCommand.GetPose.Response getPose(EdgeCommonVO edgeCommonVO, String baseLink, String eeLink);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标定零点(命令码:calibrateZeroQ)
|
||||||
|
* 对指定关节进行零点标定
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param jointName 关节名称(可选,为空则标定所有关节)
|
||||||
|
* @return 标定结果
|
||||||
|
*/
|
||||||
|
ArmCommand.CalibrateZeroQ.Response calibrateZeroQ(EdgeCommonVO edgeCommonVO, String jointName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取位姿矩阵(命令码:getPoseMatrix)
|
||||||
|
* 获取机械臂末端执行器相对于基座的4x4变换矩阵
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param baseLink 基座连杆名称(可选,默认为base)
|
||||||
|
* @param eeLink 末端执行器连杆名称(可选,默认为tool0)
|
||||||
|
* @return 位姿矩阵信息
|
||||||
|
*/
|
||||||
|
ArmCommand.GetPoseMatrix.Response getPoseMatrix(EdgeCommonVO edgeCommonVO, String baseLink, String eeLink);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算正向运动学(命令码:computeForwardKinematics)
|
||||||
|
* 根据给定的关节位置计算末端执行器的位姿矩阵
|
||||||
|
*
|
||||||
|
* @param edgeCommonVO 边缘通用参数
|
||||||
|
* @param joints 关节位置数组(6个关节角度,单位:弧度)
|
||||||
|
* @param baseLink 基座连杆名称(可选,默认为base)
|
||||||
|
* @param eeLink 末端执行器连杆名称(可选,默认为tool0)
|
||||||
|
* @return 正向运动学计算结果(4x4变换矩阵)
|
||||||
|
*/
|
||||||
|
ArmCommand.ComputeForwardKinematics.Response computeForwardKinematics(EdgeCommonVO edgeCommonVO,
|
||||||
|
double[] joints,
|
||||||
|
String baseLink,
|
||||||
|
String eeLink);
|
||||||
|
}
|
||||||
@ -1,35 +0,0 @@
|
|||||||
package com.cmvr.edge.client.service;
|
|
||||||
|
|
||||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeMoveJVO;
|
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeSpeedJVO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 边缘系统机械臂服务
|
|
||||||
*/
|
|
||||||
public interface EdgeHumanoidRobotService {
|
|
||||||
/**
|
|
||||||
* 移动机械臂
|
|
||||||
*/
|
|
||||||
public String moveJ(EdgeMoveJVO vo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取关节状态
|
|
||||||
*/
|
|
||||||
public String getJointState(EdgeCommonVO vo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 旋转关节
|
|
||||||
*/
|
|
||||||
public String speedJ(EdgeSpeedJVO vo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使能开
|
|
||||||
*/
|
|
||||||
public String torqueOn(EdgeCommonVO vo);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使能关
|
|
||||||
*/
|
|
||||||
public String torqueOff(EdgeCommonVO vo);
|
|
||||||
}
|
|
||||||
@ -0,0 +1,369 @@
|
|||||||
|
package com.cmvr.edge.client.service.impl;
|
||||||
|
|
||||||
|
import cmvr.api.ArmCommand;
|
||||||
|
import cmvr.api.ArmServiceGrpc;
|
||||||
|
import cmvr.api.Common;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.cmvr.common.exception.GlobalException;
|
||||||
|
import com.cmvr.edge.client.manage.GrpcServiceManager;
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import com.cmvr.edge.client.service.EdgeArmService;
|
||||||
|
import com.cmvr.edge.client.utils.EdgeCommonUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂服务实现类
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EdgeArmServiceImpl implements EdgeArmService {
|
||||||
|
|
||||||
|
private final GrpcServiceManager grpcServiceManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Common.CommandHeader.Feedback torqueOff(EdgeCommonVO edgeCommonVO) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||||
|
return executeGrpcCall(() -> stub.torqueOff(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Common.CommandHeader.Feedback torqueOn(EdgeCommonVO edgeCommonVO) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||||
|
return executeGrpcCall(() -> stub.torqueOn(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.MoveJ.Response moveJ(EdgeCommonVO edgeCommonVO, double[] target, Double velocity,
|
||||||
|
Double acceleration, Double blendRadius,
|
||||||
|
double[] jointVelocityLimits, Boolean asynchronous) {
|
||||||
|
if (target == null || target.length == 0) {
|
||||||
|
throw new GlobalException("目标关节位置不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
// 构建关节位置命令
|
||||||
|
ArmCommand.JointPositionCommand targetCommand = ArmCommand.JointPositionCommand.newBuilder()
|
||||||
|
.addAllPosition(Arrays.asList(
|
||||||
|
Arrays.stream(target).boxed().toArray(Double[]::new)
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 构建运动选项
|
||||||
|
ArmCommand.MotionOptions.Builder optionsBuilder = ArmCommand.MotionOptions.newBuilder();
|
||||||
|
if (velocity != null) {
|
||||||
|
optionsBuilder.setVelocity(velocity);
|
||||||
|
}
|
||||||
|
if (acceleration != null) {
|
||||||
|
optionsBuilder.setAcceleration(acceleration);
|
||||||
|
}
|
||||||
|
if (blendRadius != null) {
|
||||||
|
optionsBuilder.setBlendRadius(blendRadius);
|
||||||
|
}
|
||||||
|
if (jointVelocityLimits != null && jointVelocityLimits.length > 0) {
|
||||||
|
optionsBuilder.addAllJointVelocityLimits(Arrays.asList(
|
||||||
|
Arrays.stream(jointVelocityLimits).boxed().toArray(Double[]::new)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if (asynchronous != null) {
|
||||||
|
optionsBuilder.setAsynchronous(asynchronous);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArmCommand.MoveJ.Request request = ArmCommand.MoveJ.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.setTarget(targetCommand)
|
||||||
|
.setOptions(optionsBuilder.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.moveJ(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.MoveL.Response moveL(EdgeCommonVO edgeCommonVO, double x, double y, double z,
|
||||||
|
double rx, double ry, double rz, String frame,
|
||||||
|
Double velocity, Double acceleration, Double blendRadius) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
// 构建笛卡尔位姿
|
||||||
|
ArmCommand.CartesianPose targetPose = ArmCommand.CartesianPose.newBuilder()
|
||||||
|
.setX(x)
|
||||||
|
.setY(y)
|
||||||
|
.setZ(z)
|
||||||
|
.setRx(rx)
|
||||||
|
.setRy(ry)
|
||||||
|
.setRz(rz)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 构建运动选项
|
||||||
|
ArmCommand.MotionOptions.Builder optionsBuilder = ArmCommand.MotionOptions.newBuilder();
|
||||||
|
if (velocity != null) {
|
||||||
|
optionsBuilder.setVelocity(velocity);
|
||||||
|
}
|
||||||
|
if (acceleration != null) {
|
||||||
|
optionsBuilder.setAcceleration(acceleration);
|
||||||
|
}
|
||||||
|
if (blendRadius != null) {
|
||||||
|
optionsBuilder.setBlendRadius(blendRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确定坐标系类型
|
||||||
|
ArmCommand.ArmFrameType frameType = parseFrameType(frame);
|
||||||
|
|
||||||
|
ArmCommand.MoveL.Request request = ArmCommand.MoveL.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.setTarget(targetPose)
|
||||||
|
.setOptions(optionsBuilder.build())
|
||||||
|
.setFrame(frameType)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.moveL(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.SpeedJ.Response speedJ(EdgeCommonVO edgeCommonVO, double[] velocities,
|
||||||
|
Double acceleration, Double duration) {
|
||||||
|
if (velocities == null || velocities.length == 0) {
|
||||||
|
throw new GlobalException("关节速度数组不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
// 构建关节速度命令
|
||||||
|
ArmCommand.JointVelocityCommand velocityCommand = ArmCommand.JointVelocityCommand.newBuilder()
|
||||||
|
.addAllVelocity(Arrays.asList(
|
||||||
|
Arrays.stream(velocities).boxed().toArray(Double[]::new)
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ArmCommand.SpeedJ.Request.Builder requestBuilder = ArmCommand.SpeedJ.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.setVelocity(velocityCommand);
|
||||||
|
|
||||||
|
if (acceleration != null) {
|
||||||
|
requestBuilder.setAcceleration(acceleration);
|
||||||
|
}
|
||||||
|
if (duration != null) {
|
||||||
|
requestBuilder.setDuration(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.speedJ(requestBuilder.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.SpeedL.Response speedL(EdgeCommonVO edgeCommonVO, double vx, double vy, double vz,
|
||||||
|
double wx, double wy, double wz, String frame,
|
||||||
|
Double acceleration, Double duration) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
// 构建笛卡尔速度
|
||||||
|
ArmCommand.CartesianVelocity velocity = ArmCommand.CartesianVelocity.newBuilder()
|
||||||
|
.setVx(vx)
|
||||||
|
.setVy(vy)
|
||||||
|
.setVz(vz)
|
||||||
|
.setWx(wx)
|
||||||
|
.setWy(wy)
|
||||||
|
.setWz(wz)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ArmCommand.SpeedL.Request.Builder requestBuilder = ArmCommand.SpeedL.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.setVelocity(velocity);
|
||||||
|
|
||||||
|
if (acceleration != null) {
|
||||||
|
requestBuilder.setAcceleration(acceleration);
|
||||||
|
}
|
||||||
|
if (duration != null) {
|
||||||
|
requestBuilder.setDuration(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确定坐标系类型
|
||||||
|
ArmCommand.ArmFrameType frameType = parseFrameType(frame);
|
||||||
|
requestBuilder.setFrame(frameType);
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.speedL(requestBuilder.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.ServoJ.Response servoJ(EdgeCommonVO edgeCommonVO, double[] target) {
|
||||||
|
if (target == null || target.length == 0) {
|
||||||
|
throw new GlobalException("目标关节位置不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
// 构建关节位置命令
|
||||||
|
ArmCommand.JointPositionCommand targetCommand = ArmCommand.JointPositionCommand.newBuilder()
|
||||||
|
.addAllPosition(Arrays.asList(
|
||||||
|
Arrays.stream(target).boxed().toArray(Double[]::new)
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ArmCommand.ServoJ.Request request = ArmCommand.ServoJ.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.setTarget(targetCommand)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.servoJ(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Common.CommandHeader.Feedback stopMotion(EdgeCommonVO edgeCommonVO) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
Common.CommandHeader.Request request = EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId());
|
||||||
|
return executeGrpcCall(() -> stub.stopMotion(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.JointResponse getJointState(EdgeCommonVO edgeCommonVO) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
ArmCommand.JointRequest request = ArmCommand.JointRequest.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.build();
|
||||||
|
return executeGrpcCall(() -> stub.getJointState(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.GetPose.Response getPose(EdgeCommonVO edgeCommonVO, String baseLink, String eeLink) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
ArmCommand.GetPose.Request.Builder requestBuilder = ArmCommand.GetPose.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()));
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(baseLink)) {
|
||||||
|
requestBuilder.setBaseLink(baseLink);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(eeLink)) {
|
||||||
|
requestBuilder.setEeLink(eeLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.getPose(requestBuilder.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.CalibrateZeroQ.Response calibrateZeroQ(EdgeCommonVO edgeCommonVO, String jointName) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
ArmCommand.CalibrateZeroQ.Request.Builder requestBuilder = ArmCommand.CalibrateZeroQ.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()));
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(jointName)) {
|
||||||
|
requestBuilder.setJointName(jointName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.calibrateZeroQ(requestBuilder.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.GetPoseMatrix.Response getPoseMatrix(EdgeCommonVO edgeCommonVO, String baseLink, String eeLink) {
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
ArmCommand.GetPoseMatrix.Request.Builder requestBuilder = ArmCommand.GetPoseMatrix.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()));
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(baseLink)) {
|
||||||
|
requestBuilder.setBaseLink(baseLink);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(eeLink)) {
|
||||||
|
requestBuilder.setEeLink(eeLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.getPoseMatrix(requestBuilder.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArmCommand.ComputeForwardKinematics.Response computeForwardKinematics(EdgeCommonVO edgeCommonVO,
|
||||||
|
double[] joints,
|
||||||
|
String baseLink,
|
||||||
|
String eeLink) {
|
||||||
|
if (joints == null || joints.length == 0) {
|
||||||
|
throw new GlobalException("关节位置数组不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArmServiceGrpc.ArmServiceBlockingStub stub = grpcServiceManager.getGrpcClient(
|
||||||
|
edgeCommonVO.getTerminalId(), ArmServiceGrpc.ArmServiceBlockingStub.class);
|
||||||
|
|
||||||
|
// 构建关节位置命令
|
||||||
|
ArmCommand.JointPositionCommand jointsCommand = ArmCommand.JointPositionCommand.newBuilder()
|
||||||
|
.addAllPosition(Arrays.asList(
|
||||||
|
Arrays.stream(joints).boxed().toArray(Double[]::new)
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ArmCommand.ComputeForwardKinematics.Request.Builder requestBuilder = ArmCommand.ComputeForwardKinematics.Request.newBuilder()
|
||||||
|
.setHeader(EdgeCommonUtil.buildRequest(edgeCommonVO.getDeviceId()))
|
||||||
|
.setJoints(jointsCommand);
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(baseLink)) {
|
||||||
|
requestBuilder.setBaseLink(baseLink);
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(eeLink)) {
|
||||||
|
requestBuilder.setEeLink(eeLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeGrpcCall(() -> stub.computeForwardKinematics(requestBuilder.build()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析坐标系类型
|
||||||
|
*
|
||||||
|
* @param frame 坐标系字符串
|
||||||
|
* @return 坐标系枚举
|
||||||
|
*/
|
||||||
|
private ArmCommand.ArmFrameType parseFrameType(String frame) {
|
||||||
|
if (StrUtil.isBlank(frame)) {
|
||||||
|
return ArmCommand.ArmFrameType.ARM_FRAME_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (frame.toUpperCase()) {
|
||||||
|
case "BASE":
|
||||||
|
return ArmCommand.ArmFrameType.ARM_FRAME_BASE;
|
||||||
|
case "TOOL":
|
||||||
|
return ArmCommand.ArmFrameType.ARM_FRAME_TOOL;
|
||||||
|
case "WORLD":
|
||||||
|
return ArmCommand.ArmFrameType.ARM_FRAME_WORLD;
|
||||||
|
case "USER":
|
||||||
|
return ArmCommand.ArmFrameType.ARM_FRAME_USER;
|
||||||
|
default:
|
||||||
|
log.warn("未知的坐标系类型: {}, 使用默认值 BASE", frame);
|
||||||
|
return ArmCommand.ArmFrameType.ARM_FRAME_BASE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行gRPC调用并处理异常
|
||||||
|
*
|
||||||
|
* @param call gRPC调用
|
||||||
|
* @param <T> 返回类型
|
||||||
|
* @return 调用结果
|
||||||
|
*/
|
||||||
|
private <T> T executeGrpcCall(java.util.function.Supplier<T> call) {
|
||||||
|
try {
|
||||||
|
return call.get();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("机械臂 gRPC调用失败", e);
|
||||||
|
throw new GlobalException("机械臂通信失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,102 +0,0 @@
|
|||||||
package com.cmvr.edge.client.service.impl;
|
|
||||||
|
|
||||||
import cmvr.api.Common;
|
|
||||||
import cmvr.api.HumanoidRobotCommand;
|
|
||||||
import cmvr.api.HumanoidRobotServiceGrpc;
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
|
||||||
import com.cmvr.edge.client.manage.GrpcServiceManager;
|
|
||||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeMoveJVO;
|
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeSpeedJVO;
|
|
||||||
import com.cmvr.edge.client.service.EdgeHumanoidRobotService;
|
|
||||||
import com.cmvr.edge.client.utils.EdgeCommonUtil;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class EdgeHumanoidRobotServiceImpl implements EdgeHumanoidRobotService {
|
|
||||||
|
|
||||||
private final GrpcServiceManager grpcServiceManager;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String moveJ(EdgeMoveJVO vo) {
|
|
||||||
HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub stub =
|
|
||||||
grpcServiceManager.getGrpcClient(vo.getTerminalId(),
|
|
||||||
HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class);
|
|
||||||
|
|
||||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(vo.getDeviceId());
|
|
||||||
|
|
||||||
HumanoidRobotCommand.MoveJ.Request.Builder builder = HumanoidRobotCommand.MoveJ.Request.newBuilder()
|
|
||||||
.setHeader(header)
|
|
||||||
.setVel(vo.getVel())
|
|
||||||
.setAcc(vo.getAcc());
|
|
||||||
|
|
||||||
if (vo.getCmds() != null) {
|
|
||||||
for (EdgeMoveJVO.JointCmd j : vo.getCmds()) {
|
|
||||||
builder.addCmds(HumanoidRobotCommand.JointCmd.newBuilder()
|
|
||||||
.setJointName(j.getJointName())
|
|
||||||
.setRad(j.getRad())
|
|
||||||
.setVel(j.getVel())
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// log.info("movej start time={}", System.currentTimeMillis());
|
|
||||||
|
|
||||||
HumanoidRobotCommand.MoveJ.Response response = stub.moveJ(builder.build());
|
|
||||||
// log.info("movej success time={}", System.currentTimeMillis());
|
|
||||||
return JSON.toJSONString(response.getHeader());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getJointState(EdgeCommonVO vo) {
|
|
||||||
HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub stub =
|
|
||||||
grpcServiceManager.getGrpcClient(vo.getTerminalId(), HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class);
|
|
||||||
|
|
||||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(vo.getDeviceId());
|
|
||||||
HumanoidRobotCommand.JointRequest build = HumanoidRobotCommand.JointRequest.newBuilder()
|
|
||||||
.setHeader(header)
|
|
||||||
.build();
|
|
||||||
HumanoidRobotCommand.JointResponse response = stub.getJointState(build);
|
|
||||||
return JSON.toJSONString(response.getStateList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String speedJ(EdgeSpeedJVO vo) {
|
|
||||||
HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub stub =
|
|
||||||
grpcServiceManager.getGrpcClient(vo.getTerminalId(), HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class);
|
|
||||||
|
|
||||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(vo.getDeviceId());
|
|
||||||
HumanoidRobotCommand.SpeedJ.Request request = HumanoidRobotCommand.SpeedJ.Request.newBuilder()
|
|
||||||
.setHeader(header)
|
|
||||||
.setAcc(vo.getAcc())
|
|
||||||
.setVel(vo.getVel())
|
|
||||||
.setDir(vo.getDir())
|
|
||||||
.build();
|
|
||||||
HumanoidRobotCommand.SpeedJ.Response response = stub.speedJ(request);
|
|
||||||
return JSON.toJSONString(response.getHeader());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String torqueOn(EdgeCommonVO vo) {
|
|
||||||
HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub stub =
|
|
||||||
grpcServiceManager.getGrpcClient(vo.getTerminalId(), HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class);
|
|
||||||
|
|
||||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(vo.getDeviceId());
|
|
||||||
Common.CommandHeader.Feedback response = stub.torqueOn(header);
|
|
||||||
return JSON.toJSONString(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String torqueOff(EdgeCommonVO vo) {
|
|
||||||
HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub stub =
|
|
||||||
grpcServiceManager.getGrpcClient(vo.getTerminalId(), HumanoidRobotServiceGrpc.HumanoidRobotServiceBlockingStub.class);
|
|
||||||
|
|
||||||
Common.CommandHeader.Request header = EdgeCommonUtil.buildRequest(vo.getDeviceId());
|
|
||||||
Common.CommandHeader.Feedback response = stub.torqueOff(header);
|
|
||||||
return JSON.toJSONString(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,66 @@
|
|||||||
|
// Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
|
// source: cmvr/api/arm_service.proto
|
||||||
|
|
||||||
|
package cmvr.api;
|
||||||
|
|
||||||
|
public final class ArmServiceOuterClass {
|
||||||
|
private ArmServiceOuterClass() {}
|
||||||
|
public static void registerAllExtensions(
|
||||||
|
com.google.protobuf.ExtensionRegistryLite registry) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerAllExtensions(
|
||||||
|
com.google.protobuf.ExtensionRegistry registry) {
|
||||||
|
registerAllExtensions(
|
||||||
|
(com.google.protobuf.ExtensionRegistryLite) registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
getDescriptor() {
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
private static com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
descriptor;
|
||||||
|
static {
|
||||||
|
java.lang.String[] descriptorData = {
|
||||||
|
"\n\032cmvr/api/arm_service.proto\022\010cmvr.api\032\025" +
|
||||||
|
"cmvr/api/common.proto\032\032cmvr/api/arm_comm" +
|
||||||
|
"and.proto2\325\007\n\nArmService\022N\n\ttorqueOff\022\037." +
|
||||||
|
"cmvr.api.CommandHeader.Request\032 .cmvr.ap" +
|
||||||
|
"i.CommandHeader.Feedback\022M\n\010torqueOn\022\037.c" +
|
||||||
|
"mvr.api.CommandHeader.Request\032 .cmvr.api" +
|
||||||
|
".CommandHeader.Feedback\022:\n\005moveJ\022\027.cmvr." +
|
||||||
|
"api.MoveJ.Request\032\030.cmvr.api.MoveJ.Respo" +
|
||||||
|
"nse\022:\n\005moveL\022\027.cmvr.api.MoveL.Request\032\030." +
|
||||||
|
"cmvr.api.MoveL.Response\022=\n\006speedJ\022\030.cmvr" +
|
||||||
|
".api.SpeedJ.Request\032\031.cmvr.api.SpeedJ.Re" +
|
||||||
|
"sponse\022=\n\006speedL\022\030.cmvr.api.SpeedL.Reque" +
|
||||||
|
"st\032\031.cmvr.api.SpeedL.Response\022=\n\006servoJ\022" +
|
||||||
|
"\030.cmvr.api.ServoJ.Request\032\031.cmvr.api.Ser" +
|
||||||
|
"voJ.Response\022O\n\nstopMotion\022\037.cmvr.api.Co" +
|
||||||
|
"mmandHeader.Request\032 .cmvr.api.CommandHe" +
|
||||||
|
"ader.Feedback\022@\n\rgetJointState\022\026.cmvr.ap" +
|
||||||
|
"i.JointRequest\032\027.cmvr.api.JointResponse\022" +
|
||||||
|
"@\n\007getPose\022\031.cmvr.api.GetPose.Request\032\032." +
|
||||||
|
"cmvr.api.GetPose.Response\022U\n\016calibrateZe" +
|
||||||
|
"roQ\022 .cmvr.api.CalibrateZeroQ.Request\032!." +
|
||||||
|
"cmvr.api.CalibrateZeroQ.Response\022R\n\rgetP" +
|
||||||
|
"oseMatrix\022\037.cmvr.api.GetPoseMatrix.Reque" +
|
||||||
|
"st\032 .cmvr.api.GetPoseMatrix.Response\022s\n\030" +
|
||||||
|
"computeForwardKinematics\022*.cmvr.api.Comp" +
|
||||||
|
"uteForwardKinematics.Request\032+.cmvr.api." +
|
||||||
|
"ComputeForwardKinematics.Responseb\006proto" +
|
||||||
|
"3"
|
||||||
|
};
|
||||||
|
descriptor = com.google.protobuf.Descriptors.FileDescriptor
|
||||||
|
.internalBuildGeneratedFileFrom(descriptorData,
|
||||||
|
new com.google.protobuf.Descriptors.FileDescriptor[] {
|
||||||
|
cmvr.api.Common.getDescriptor(),
|
||||||
|
cmvr.api.ArmCommand.getDescriptor(),
|
||||||
|
});
|
||||||
|
cmvr.api.Common.getDescriptor();
|
||||||
|
cmvr.api.ArmCommand.getDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @@protoc_insertion_point(outer_class_scope)
|
||||||
|
}
|
||||||
@ -57,6 +57,8 @@ public enum ActionEnum {
|
|||||||
|
|
||||||
// ---------------机械臂---------------
|
// ---------------机械臂---------------
|
||||||
TOUCH("EDGE", "TOUCH", "触控"),
|
TOUCH("EDGE", "TOUCH", "触控"),
|
||||||
|
// 末端运动
|
||||||
|
ARM_MOVE_TO_POINT("EDGE", "ARM_MOVE_TO_POINT", "运动到指定点"),
|
||||||
|
|
||||||
// --------------- 头部 ---------------
|
// --------------- 头部 ---------------
|
||||||
BIO_HEAD_SPEAK_START("EDGE", "BIO_HEAD_SPEAK_START", "开始说话"),
|
BIO_HEAD_SPEAK_START("EDGE", "BIO_HEAD_SPEAK_START", "开始说话"),
|
||||||
|
|||||||
@ -0,0 +1,104 @@
|
|||||||
|
package com.cmvr.test.flow.runtime.operator.edge;
|
||||||
|
|
||||||
|
import cmvr.api.ArmCommand;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.cmvr.common.exception.GlobalException;
|
||||||
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import com.cmvr.edge.client.service.EdgeArmService;
|
||||||
|
import com.cmvr.test.enums.ActionEnum;
|
||||||
|
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
|
||||||
|
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 机械臂边缘操作服务
|
||||||
|
* 处理机械臂相关的设备行为,如末端运动到指定位置
|
||||||
|
*
|
||||||
|
* @author cmvr-iot
|
||||||
|
* @since 2026-07-01
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class EdgeArmOperateService implements EdgeOperateService {
|
||||||
|
|
||||||
|
private final EdgeArmService edgeArmService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supports(ActionEnum action) {
|
||||||
|
return action.name().startsWith("ARM_");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TaskNodeExecuteResult execute(TaskNodeExecuteMessage message) {
|
||||||
|
ActionEnum action = message.getAction();
|
||||||
|
JSONObject inputParams = message.getInputParams();
|
||||||
|
String terminalId = message.getTerminalId();
|
||||||
|
|
||||||
|
// 从输入参数中获取设备ID
|
||||||
|
String deviceId = inputParams.getString("deviceId");
|
||||||
|
|
||||||
|
if (deviceId == null || deviceId.isEmpty()) {
|
||||||
|
throw new GlobalException("设备ID(deviceId)不能为空");
|
||||||
|
}
|
||||||
|
// 构建边缘端通用参数
|
||||||
|
EdgeCommonVO edgeCommonVO = new EdgeCommonVO();
|
||||||
|
edgeCommonVO.setTerminalId(terminalId);
|
||||||
|
edgeCommonVO.setDeviceId(deviceId);
|
||||||
|
|
||||||
|
// 先调用开启力矩
|
||||||
|
edgeArmService.torqueOn(edgeCommonVO);
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case ARM_MOVE_TO_POINT: {
|
||||||
|
log.info("执行机械臂末端运动到指定点操作,设备ID: {}", deviceId);
|
||||||
|
|
||||||
|
// 从输入参数中获取坐标信息
|
||||||
|
Double x = inputParams.getDouble("x");
|
||||||
|
Double y = inputParams.getDouble("y");
|
||||||
|
Double z = inputParams.getDouble("z");
|
||||||
|
Double rx = inputParams.getDouble("rx");
|
||||||
|
Double ry = inputParams.getDouble("ry");
|
||||||
|
Double rz = inputParams.getDouble("rz");
|
||||||
|
String frame = inputParams.getString("frame");
|
||||||
|
Double velocity = inputParams.getDouble("velocity");
|
||||||
|
Double acceleration = inputParams.getDouble("acceleration");
|
||||||
|
Double blendRadius = inputParams.getDouble("blendRadius");
|
||||||
|
|
||||||
|
// 参数验证
|
||||||
|
if (x == null || y == null || z == null) {
|
||||||
|
throw new GlobalException("X、Y、Z坐标不能为空");
|
||||||
|
}
|
||||||
|
if (rx == null || ry == null || rz == null) {
|
||||||
|
throw new GlobalException("RX、RY、RZ旋转角度不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接调用边缘端机械臂服务执行笛卡尔空间直线运动
|
||||||
|
ArmCommand.MoveL.Response result = edgeArmService.moveL(
|
||||||
|
edgeCommonVO,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
z,
|
||||||
|
rx,
|
||||||
|
ry,
|
||||||
|
rz,
|
||||||
|
frame,
|
||||||
|
velocity,
|
||||||
|
acceleration,
|
||||||
|
blendRadius
|
||||||
|
);
|
||||||
|
|
||||||
|
log.info("机械臂末端运动任务下发成功");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new GlobalException("不支持的机械臂操作类型: " + action);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TaskNodeExecuteResult.success();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,8 +3,8 @@ package com.cmvr.test.flow.runtime.operator.edge;
|
|||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.cmvr.common.exception.GlobalException;
|
import com.cmvr.common.exception.GlobalException;
|
||||||
import com.cmvr.edge.client.model.humanoid.EdgeMoveJVO;
|
import com.cmvr.edge.client.model.arm.EdgeArmMoveJVO;
|
||||||
import com.cmvr.edge.client.service.EdgeHumanoidRobotService;
|
import com.cmvr.edge.client.service.EdgeArmService;
|
||||||
import com.cmvr.test.enums.ActionEnum;
|
import com.cmvr.test.enums.ActionEnum;
|
||||||
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
|
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteMessage;
|
||||||
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
|
import com.cmvr.test.flow.runtime.message.TaskNodeExecuteResult;
|
||||||
@ -18,7 +18,7 @@ import org.springframework.stereotype.Service;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class EdgeTouchOperateService implements EdgeOperateService {
|
public class EdgeTouchOperateService implements EdgeOperateService {
|
||||||
|
|
||||||
private final EdgeHumanoidRobotService edgeHumanoidRobotService;
|
private final EdgeArmService edgeArmService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(ActionEnum action) {
|
public boolean supports(ActionEnum action) {
|
||||||
@ -35,11 +35,19 @@ public class EdgeTouchOperateService implements EdgeOperateService {
|
|||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case TOUCH: {
|
case TOUCH: {
|
||||||
EdgeMoveJVO edgeMoveJVO = JSON.parseObject(touchParams, EdgeMoveJVO.class);
|
EdgeArmMoveJVO edgeArmMoveJVO = JSON.parseObject(touchParams, EdgeArmMoveJVO.class);
|
||||||
edgeMoveJVO.setTerminalId(terminalId);
|
edgeArmMoveJVO.setTerminalId(terminalId);
|
||||||
edgeMoveJVO.setDeviceId(deviceId);
|
edgeArmMoveJVO.setDeviceId(deviceId);
|
||||||
|
|
||||||
edgeHumanoidRobotService.moveJ(edgeMoveJVO);
|
edgeArmService.moveJ(
|
||||||
|
edgeArmMoveJVO,
|
||||||
|
edgeArmMoveJVO.getTarget(),
|
||||||
|
edgeArmMoveJVO.getVelocity(),
|
||||||
|
edgeArmMoveJVO.getAcceleration(),
|
||||||
|
edgeArmMoveJVO.getBlendRadius(),
|
||||||
|
edgeArmMoveJVO.getJointVelocityLimits(),
|
||||||
|
edgeArmMoveJVO.getAsynchronous()
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,8 +9,8 @@ import com.cmvr.common.exception.GlobalException;
|
|||||||
import com.cmvr.common.utils.http.CallAPIUtil;
|
import com.cmvr.common.utils.http.CallAPIUtil;
|
||||||
import com.cmvr.common.utils.uuid.IdUtils;
|
import com.cmvr.common.utils.uuid.IdUtils;
|
||||||
import com.cmvr.edge.client.model.EdgeCommonVO;
|
import com.cmvr.edge.client.model.EdgeCommonVO;
|
||||||
|
import com.cmvr.edge.client.service.EdgeArmService;
|
||||||
import com.cmvr.edge.client.service.EdgeBioHeadService;
|
import com.cmvr.edge.client.service.EdgeBioHeadService;
|
||||||
import com.cmvr.edge.client.service.EdgeHumanoidRobotService;
|
|
||||||
import com.cmvr.test.enums.FlowiseActionEnum;
|
import com.cmvr.test.enums.FlowiseActionEnum;
|
||||||
import com.cmvr.test.flow.context.TaskContext;
|
import com.cmvr.test.flow.context.TaskContext;
|
||||||
import com.cmvr.test.flow.context.TaskContextManager;
|
import com.cmvr.test.flow.context.TaskContextManager;
|
||||||
@ -36,7 +36,7 @@ import java.util.Map;
|
|||||||
public class FlowiseActionService {
|
public class FlowiseActionService {
|
||||||
|
|
||||||
private final EdgeBioHeadService edgeBioHeadService;
|
private final EdgeBioHeadService edgeBioHeadService;
|
||||||
private final EdgeHumanoidRobotService edgeHumanoidRobotService;
|
private final EdgeArmService edgeArmService;
|
||||||
private final TaskContextManager taskContextManager;
|
private final TaskContextManager taskContextManager;
|
||||||
private final FlowControlService flowControlService;
|
private final FlowControlService flowControlService;
|
||||||
private final FlowTaskRuntimeService flowTaskRuntimeService;
|
private final FlowTaskRuntimeService flowTaskRuntimeService;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user