From a82c9a2633c519d5d7d868d3ec89832f77849700 Mon Sep 17 00:00:00 2001
From: liusuyi <1951119284@qq.com>
Date: Mon, 17 Mar 2025 09:35:58 +0800
Subject: [PATCH] 增加飞行高度控制切面
---
/dev/null | 12 ---
ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java | 29 +++++-
ard-work/src/main/java/com/ard/tianyu/aspect/UavControlAspect.java | 44 +++++++++-
ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckTakeoffAltitude.java | 12 +++
ard-framework/src/main/java/com/ard/framework/web/exception/GlobalExceptionHandler.java | 6
ard-admin/src/main/resources/application.yml | 2
ard-common/src/main/java/com/ard/common/exception/ControlException.java | 12 +++
ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java | 8 +-
ard-work/src/main/java/com/ard/tianyu/util/CameraUtil.java | 75 ++++++++++++++++++
ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckControlRight.java | 2
10 files changed, 168 insertions(+), 34 deletions(-)
diff --git a/ard-admin/src/main/resources/application.yml b/ard-admin/src/main/resources/application.yml
index 334660b..3e15238 100644
--- a/ard-admin/src/main/resources/application.yml
+++ b/ard-admin/src/main/resources/application.yml
@@ -123,7 +123,7 @@
# 数据库索引
database: 0
# 密码
- password:
+ password: xzx12345
# 连接超时时间
timeout: 10s
lettuce:
diff --git a/ard-common/src/main/java/com/ard/common/exception/ControlException.java b/ard-common/src/main/java/com/ard/common/exception/ControlException.java
new file mode 100644
index 0000000..8a2bf34
--- /dev/null
+++ b/ard-common/src/main/java/com/ard/common/exception/ControlException.java
@@ -0,0 +1,12 @@
+package com.ard.common.exception;
+
+/**
+ * 无人机控制异常
+ *
+ * @author ruoyi
+ */
+public class ControlException extends RuntimeException {
+ public ControlException(String message) {
+ super(message);
+ }
+}
diff --git a/ard-common/src/main/java/com/ard/common/exception/NoPermissionException.java b/ard-common/src/main/java/com/ard/common/exception/NoPermissionException.java
deleted file mode 100644
index d08e499..0000000
--- a/ard-common/src/main/java/com/ard/common/exception/NoPermissionException.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.ard.common.exception;
-
-/**
- * 无人机权限异常
- *
- * @author ruoyi
- */
-public class NoPermissionException extends RuntimeException {
- public NoPermissionException(String message) {
- super(message);
- }
-}
diff --git a/ard-framework/src/main/java/com/ard/framework/web/exception/GlobalExceptionHandler.java b/ard-framework/src/main/java/com/ard/framework/web/exception/GlobalExceptionHandler.java
index 89f6592..eb3dab9 100644
--- a/ard-framework/src/main/java/com/ard/framework/web/exception/GlobalExceptionHandler.java
+++ b/ard-framework/src/main/java/com/ard/framework/web/exception/GlobalExceptionHandler.java
@@ -2,7 +2,7 @@
import javax.servlet.http.HttpServletRequest;
-import com.ard.common.exception.NoPermissionException;
+import com.ard.common.exception.ControlException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
@@ -148,8 +148,8 @@
/**
* 无人机无控制权异常
*/
- @ExceptionHandler(NoPermissionException.class)
- public AjaxResult handleNoPermissionException(NoPermissionException e)
+ @ExceptionHandler(ControlException.class)
+ public AjaxResult handleNoPermissionException(ControlException e)
{
return AjaxResult.error(e.getMessage());
}
diff --git a/ard-work/src/main/java/com/ard/tianyu/aspect/UavControlAspect.java b/ard-work/src/main/java/com/ard/tianyu/aspect/UavControlAspect.java
index ed9eae0..1d6f2f1 100644
--- a/ard-work/src/main/java/com/ard/tianyu/aspect/UavControlAspect.java
+++ b/ard-work/src/main/java/com/ard/tianyu/aspect/UavControlAspect.java
@@ -1,8 +1,11 @@
package com.ard.tianyu.aspect;
-import com.ard.common.exception.NoPermissionException;
+import com.ard.common.exception.ControlException;
import com.ard.common.utils.SecurityUtils;
-import com.ard.tianyu.aspect.annotation.RequireUavControl;
+import com.ard.tianyu.aspect.annotation.CheckTakeoffAltitude;
+import com.ard.tianyu.aspect.annotation.CheckControlRight;
+import com.ard.tianyu.domain.cache.UavTelemetryDataCache;
+import com.ard.tianyu.domain.dto.telemetry.TelemetryData;
import com.ard.tianyu.service.control.UavControlService;
import com.ard.tianyu.websocket.domain.UavControlType;
import org.aspectj.lang.JoinPoint;
@@ -15,6 +18,8 @@
/**
* AOP 切面:拦截 @RequireUavControl,检查用户是否拥有 UAV 控制权限
+ *
+ * 注意切面顺序:同类方法注解按字母ABCD顺序,不同类注解按order(1)顺序 越小优先级越高
*/
@Aspect
@Component
@@ -24,15 +29,15 @@
private UavControlService uavControlService;
/**
- * 拦截 @RequireUavControl 注解的方法
+ * 前置通知:控制权检测
*/
- @Before("@annotation(requireUavControl)")
- public void checkUavControl(JoinPoint joinPoint, RequireUavControl requireUavControl) {
+ @Before("@annotation(checkControlRight)")
+ public void checkUavControl(JoinPoint joinPoint, CheckControlRight checkControlRight) {
// 获取当前用户 ID
Long userId = SecurityUtils.getUserId();
// 获取控制类型
- UavControlType controlType = requireUavControl.value();
+ UavControlType controlType = checkControlRight.value();
// 获取方法参数
Object[] args = joinPoint.getArgs();
@@ -45,12 +50,37 @@
Long currentController = uavControlService.getCurrentController(boxSn,
controlType.name().toLowerCase());
if (currentController == null || !currentController.equals(userId)) {
- throw new NoPermissionException("无权执行该操作,需要 " + controlType + " 控制权限");
+ throw new ControlException("无权执行该操作,需要 " + controlType + " 控制权限");
}
}
}
}
+ /**
+ * 前置通知:高度检查
+ */
+ @Before("@annotation(checkTakeoffAltitude)")
+ public void takeoffAltitudeCheck(JoinPoint joinPoint, CheckTakeoffAltitude checkTakeoffAltitude) {
+ // 获取最小高度
+ double minAltitude = checkTakeoffAltitude.minAltitude();
+ // 获取方法参数
+ Object[] args = joinPoint.getArgs();
+
+ // 遍历参数,使用反射获取每个参数中的 boxSn
+ for (Object arg : args) {
+ String boxSn = getBoxSn(arg); // 调用之前实现的 getBoxSn 方法
+ if (boxSn != null) {
+ TelemetryData uavTelemetryData = UavTelemetryDataCache.getUavTelemetryData(boxSn);
+ if (uavTelemetryData == null) {
+ throw new ControlException("遥测数据异常,无法执行!");
+ }
+ // 检查高度
+ if (uavTelemetryData.getAltitude() < minAltitude) {
+ throw new ControlException("高度太低,无法执行!最低高度: " + minAltitude);
+ }
+ }
+ }
+ }
/**
* 通过反射获取对象中的 boxSn 字段
diff --git a/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/RequireUavControl.java b/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckControlRight.java
similarity index 92%
rename from ard-work/src/main/java/com/ard/tianyu/aspect/annotation/RequireUavControl.java
rename to ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckControlRight.java
index 7fb5b22..63303c0 100644
--- a/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/RequireUavControl.java
+++ b/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckControlRight.java
@@ -12,6 +12,6 @@
*/
@Target(ElementType.METHOD) // 作用于方法
@Retention(RetentionPolicy.RUNTIME) // 运行时生效
-public @interface RequireUavControl {
+public @interface CheckControlRight {
UavControlType value(); // 控制类型:"fly"、"payload"、"both"
}
diff --git a/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckTakeoffAltitude.java b/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckTakeoffAltitude.java
new file mode 100644
index 0000000..2d73381
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/tianyu/aspect/annotation/CheckTakeoffAltitude.java
@@ -0,0 +1,12 @@
+package com.ard.tianyu.aspect.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CheckTakeoffAltitude {
+ double minAltitude() default 20.0; // 默认最低起飞高度为10米
+}
\ No newline at end of file
diff --git a/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java b/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java
index a58c63b..850fb75 100644
--- a/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java
+++ b/ard-work/src/main/java/com/ard/tianyu/service/control/UavControlService.java
@@ -1,6 +1,6 @@
package com.ard.tianyu.service.control;
-import com.ard.common.exception.NoPermissionException;
+import com.ard.common.exception.ControlException;
import com.ard.common.utils.SecurityUtils;
import com.ard.tianyu.websocket.domain.UavControlType;
import com.ard.tianyu.websocket.handler.UavControlManager;
@@ -66,7 +66,7 @@
requestMap.put(boxSn, requester);
uavControlManager.sendControlRequest(controller, boxSn, controlType.getType(), requester);
} else {
- throw new NoPermissionException("当前已拥有控制权");
+ throw new ControlException("当前已拥有控制权");
}
return false;
}
@@ -94,7 +94,7 @@
Long requester = requestMap.get(boxSn);
if (requester == null || requester.equals(controller)) {
- throw new NoPermissionException("无控制请求");
+ throw new ControlException("无控制请求");
}
if (approve) {
@@ -128,7 +128,7 @@
ConcurrentHashMap<String, Long> controlMap = getControlMap(controlType);
if (!controller.equals(controlMap.get(boxSn))) {
- throw new NoPermissionException("没有该设备的" + controlType.getType().toUpperCase() + "控制权");
+ throw new ControlException("没有该设备的" + controlType.getType().toUpperCase() + "控制权");
}
controlMap.remove(boxSn);
diff --git a/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java b/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
index e3e3e54..359228f 100644
--- a/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
+++ b/ard-work/src/main/java/com/ard/tianyu/service/impl/TyServiceImpl.java
@@ -1,7 +1,8 @@
package com.ard.tianyu.service.impl;
import com.ard.common.utils.ByteUtils;
-import com.ard.tianyu.aspect.annotation.RequireUavControl;
+import com.ard.tianyu.aspect.annotation.CheckTakeoffAltitude;
+import com.ard.tianyu.aspect.annotation.CheckControlRight;
import com.ard.tianyu.config.TyConfiguration;
import com.ard.tianyu.domain.dto.camera.*;
import com.ard.tianyu.domain.dto.manual.*;
@@ -47,7 +48,6 @@
import com.ard.tianyu.netty.protobuf.TelemetryDataPB;
import com.ard.tianyu.service.ITyService;
import com.ard.tianyu.websocket.domain.UavControlType;
-import com.ard.tianyu.websocket.utils.WebSocketUtil;
import com.ard.vtdu.service.IMediaService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
@@ -197,7 +197,7 @@
/**
* 云台控制基于角度
*/
- @RequireUavControl(UavControlType.PAYLOAD)
+ @CheckControlRight(UavControlType.PAYLOAD)
@Override
public Boolean angleControl(AngleControlDTO angleControlDto) {
AngleControlCmd controlAngleCommand = new AngleControlCmd(angleControlDto);
@@ -208,7 +208,7 @@
/**
* 云台绝对值控制(基于角度)
*/
- @RequireUavControl(UavControlType.PAYLOAD)
+ @CheckControlRight(UavControlType.PAYLOAD)
@Override
public Boolean absAngleControl(AbsAngleControlDTO absAngleControlDto) {
AbsAngleControlCmd absAngleControlCommand = new AbsAngleControlCmd(absAngleControlDto);
@@ -219,7 +219,7 @@
/**
* 云台转动(基于速度)
*/
- @RequireUavControl(UavControlType.PAYLOAD)
+ @CheckControlRight(UavControlType.PAYLOAD)
@Override
public Boolean speedControl(SpeedControlDTO speedControlDto) {
SpeedControlCmd speedControlCommand = new SpeedControlCmd(speedControlDto);
@@ -267,6 +267,7 @@
/**
* 变倍
*/
+ @CheckControlRight(UavControlType.PAYLOAD)
@Override
public Boolean zoom(ZoomDTO zoomDTO) {
ZoomCmd zoomCommand = new ZoomCmd(zoomDTO);
@@ -277,6 +278,7 @@
/**
* 变倍到指定倍数
*/
+ @CheckControlRight(UavControlType.PAYLOAD)
@Override
public Boolean zoomToLevel(ZoomToLevelDTO zoomToLevelDTO) {
ZoomToLevelCmd zoomToLevelCommand = new ZoomToLevelCmd(zoomToLevelDTO);
@@ -327,7 +329,7 @@
/**
* 起飞
*/
- @RequireUavControl(UavControlType.FLY)
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean takeOff(TakeOffDTO takeOffDTO) {
TakeOffCmd takeOffCmd = new TakeOffCmd(takeOffDTO);
@@ -338,6 +340,7 @@
/**
* 返航
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean returnHome(ReturnHomeDTO returnHomeDTO) {
ReturnHomeCmd returnHomeCmd = new ReturnHomeCmd(returnHomeDTO);
@@ -348,6 +351,7 @@
/**
* 取消返航
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean returnHomeCancel(ReturnHomeCancelDTO returnHomeCancelDTO) {
ReturnHomeCancelCmd returnHomeCancelCmd = new ReturnHomeCancelCmd(returnHomeCancelDTO);
@@ -358,6 +362,7 @@
/**
* 降落
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean land(LandDTO landDTO) {
LandCmd landCmd = new LandCmd(landDTO);
@@ -368,6 +373,7 @@
/**
* 取消降落
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean landCancel(LandCancelDTO landCancelDTO) {
LandCancelCmd landCancelCmd = new LandCancelCmd(landCancelDTO);
@@ -378,6 +384,7 @@
/**
* 强制降落
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean landForced(LandForcedDTO landForcedDTO) {
LandForcedCmd landForcedCmd = new LandForcedCmd(landForcedDTO);
@@ -388,6 +395,8 @@
/**
* 方向控制
*/
+ @CheckControlRight(UavControlType.FLY)
+ @CheckTakeoffAltitude(minAltitude = 30.0)
@Override
public Boolean flyControl(FlyControlDTO flyControlDTO) {
FlyControlCmd flyControlCmd = new FlyControlCmd(flyControlDTO);
@@ -398,6 +407,8 @@
/**
* 指点飞行控制
*/
+ @CheckControlRight(UavControlType.FLY)
+ @CheckTakeoffAltitude(minAltitude = 30.0)
@Override
public Boolean flyPointControl(FlyPointControlDTO flyPointControlDTO) {
FlyPointControlCmd flyPointControlCmd = new FlyPointControlCmd(flyPointControlDTO);
@@ -408,6 +419,7 @@
/**
* 停止指点飞行控制
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean flyPointControlCancel(FlyPointControlCancelDTO flyPointControlCancelDTO) {
FlyPointControlCancelCmd flyPointControlCancelCmd = new FlyPointControlCancelCmd(flyPointControlCancelDTO);
@@ -418,6 +430,7 @@
/**
* 紧急制动
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public Boolean emeragencyBrake(EmeragencyBrakeDTO emeragencyBrakeDTO) {
EmergencyBrakeCmd emergencyBrakeCmd = new EmergencyBrakeCmd(emeragencyBrakeDTO);
@@ -559,6 +572,7 @@
/**
* 航线开始
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public void wayLineBegin(WayLineBeginDTO wayLineBeginDTO) {
WayLineBeginCmd wayLineBeginCmd = new WayLineBeginCmd(wayLineBeginDTO);
@@ -568,6 +582,7 @@
/**
* 航线暂停
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public void wayLinePause(WayLinePauseDTO wayLinePauseDTO) {
WayLinePauseCmd wayLinePauseCmd = new WayLinePauseCmd(wayLinePauseDTO);
@@ -577,6 +592,7 @@
/**
* 航线恢复
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public void wayLineResume(WayLineResumeDTO wayLineResumeDTO) {
WayLineResumeCmd wayLineResumeCmd = new WayLineResumeCmd(wayLineResumeDTO);
@@ -586,6 +602,7 @@
/**
* 航线结束
*/
+ @CheckControlRight(UavControlType.FLY)
@Override
public void wayLineEnd(WayLineEndDTO wayLineEndDTO) {
WayLineEndCmd wayLineEndCmd = new WayLineEndCmd(wayLineEndDTO);
diff --git a/ard-work/src/main/java/com/ard/tianyu/util/CameraUtil.java b/ard-work/src/main/java/com/ard/tianyu/util/CameraUtil.java
new file mode 100644
index 0000000..f30ce8e
--- /dev/null
+++ b/ard-work/src/main/java/com/ard/tianyu/util/CameraUtil.java
@@ -0,0 +1,75 @@
+package com.ard.tianyu.util;
+
+public class CameraUtil {
+
+ // 根据相机类型和变焦系数计算视场角度
+ public static Float getFieldAngleFromZoom(Integer source, Float zoomFactor) {
+ //处理视场角度
+ Float fieldAngle = 66.6F;
+ //空值的情况
+ if (source == null)
+ fieldAngle = 66.6F;
+ else if (source == 0) {
+ //广角
+ fieldAngle = (float) 82.9;
+ } else if (source == 2) {
+ //红外
+ fieldAngle = (float) 40.6;
+ } else {
+ //变焦相机
+ float zoom;
+ if (zoomFactor.isNaN())
+ zoom = 1;
+ else if (zoomFactor < 1)
+ zoom = 1;
+ else if (zoomFactor > 200)
+ zoom = 200;
+ else
+ zoom = zoomFactor;
+ fieldAngle = (float) (70.395 * Math.pow(zoom, -0.952));
+ if (fieldAngle < 4)
+ fieldAngle = 4F;
+ else if (fieldAngle > 66.6)
+ fieldAngle = 66.6F;
+ }
+ return fieldAngle;
+ }
+ // 根据相机类型和视场角度计算变焦系数
+ public static Float getZoomFromFieldAngle(Integer source, Float fieldAngle) {
+ //处理视场角度
+ Float zoomFactor = 1F;
+ //空值的情况
+ if (source == null)
+ zoomFactor = 1F;
+ else if (source == 0) {
+ //广角
+ zoomFactor = 1F;
+ } else if (source == 2) {
+ //红外
+ zoomFactor = 1F;
+ } else {
+ //变焦相机
+ float fieldAngleModify;
+ if (fieldAngle.isNaN())
+ fieldAngleModify = 66.6F;
+ else if (fieldAngle < 4)
+ fieldAngleModify = 4;
+ else if (fieldAngle > 66.6)
+ fieldAngleModify = 66.6F;
+ else
+ fieldAngleModify = fieldAngle;
+ zoomFactor = (float) (Math.pow((fieldAngleModify / 70.395), 1 / -0.952));
+ if (zoomFactor < 1)
+ zoomFactor = 1F;
+ else if (zoomFactor > 200)
+ zoomFactor = 200F;
+ }
+ return zoomFactor;
+ }
+
+
+ public static void main(String[] args) {
+ Float fieldAngleFromZoom = getFieldAngleFromZoom(1, 3F);
+ System.out.println(fieldAngleFromZoom);
+ }
+}
\ No newline at end of file
--
Gitblit v1.9.3