防止apc线程池爆了

This commit is contained in:
cxf 2026-06-18 15:04:36 +08:00
parent e3c49008ef
commit d6a6c505a1
16 changed files with 374 additions and 124 deletions

View File

@ -28,7 +28,6 @@ import dji.sdk.keyvalue.key.KeyTools
import dji.sdk.keyvalue.value.common.ComponentIndexType import dji.sdk.keyvalue.value.common.ComponentIndexType
import dji.v5.manager.KeyManager import dji.v5.manager.KeyManager
import dji.v5.utils.common.StringUtils import dji.v5.utils.common.StringUtils
import org.opencv.android.OpenCVLoader
open class ConnectionActivity : BaseActivity() { open class ConnectionActivity : BaseActivity() {
@ -338,6 +337,15 @@ open class ConnectionActivity : BaseActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
LogUtil.log(TAG,"进入首页连接") LogUtil.log(TAG,"进入首页连接")
// ===== AMS配置参数写入OSD和日志 =====
val closeObstacle = if (PreferenceUtils.getInstance().getCloseObsEnable()) 1 else 0
val interruptAction = PreferenceUtils.getInstance().getMissionInterruptAction()
val landType = PreferenceUtils.getInstance().getLandType()
val cameraLoc = PreferenceUtils.getInstance().getCameraLocationType()
LogUtil.log(TAG, String.format("AMS配置: 关闭避障=%d 中断动作=%d 降落方式=%d 相机位置=%d",
closeObstacle, interruptAction, landType, cameraLoc));
} }
override fun useEventBus(): Boolean { override fun useEventBus(): Boolean {

View File

@ -889,7 +889,7 @@ open class MainActivity : BaseActivity() {
2 -> StreamManager.getInstance().startLiveWithCustom() 2 -> StreamManager.getInstance().startLiveWithCustom()
else -> StreamManager.getInstance().startLiveWithCustom() else -> StreamManager.getInstance().startLiveWithCustom()
} }
SimplePortScanner.getInstance().startScan() // SimplePortScanner.getInstance().startScan()
}, 5000) }, 5000)
LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType) LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType)
@ -944,7 +944,7 @@ open class MainActivity : BaseActivity() {
2 -> StreamManager.getInstance().startLiveWithCustom() 2 -> StreamManager.getInstance().startLiveWithCustom()
else -> StreamManager.getInstance().startLiveWithCustom() else -> StreamManager.getInstance().startLiveWithCustom()
} }
SimplePortScanner.getInstance().startScan() // SimplePortScanner.getInstance().startScan()
}, 5000) }, 5000)
LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType) LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType)
@ -1002,7 +1002,7 @@ open class MainActivity : BaseActivity() {
2 -> StreamManager.getInstance().startLiveWithCustom() 2 -> StreamManager.getInstance().startLiveWithCustom()
else -> StreamManager.getInstance().startLiveWithCustom() else -> StreamManager.getInstance().startLiveWithCustom()
} }
SimplePortScanner.getInstance().startScan() // SimplePortScanner.getInstance().startScan()
}, 5000) }, 5000)
LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType) LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType)

View File

@ -43,54 +43,12 @@ public abstract class BaseManager {
public String TAG = getClass().getSimpleName(); public String TAG = getClass().getSimpleName();
/**
* 推送psdkmovement
* @param
*/
public void sendpsdkinfo2Server(){
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MessageReply messageReply = new MessageReply();
MessageReply.Data data=new MessageReply.Data();
data.setResult(0);
messageReply.setData(data);
MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(messageReply).getBytes("UTF-8"));
mqttMessage.setQos(0);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.UP_UAV_SERVICES_REPLY, mqttMessage);
} else {
LogUtil.log(TAG, "回复失败mqtt 未连接");
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.log(TAG, "回复异常:" + e.toString());
}
}
/**
* 推送psdkreply
* @param
*/
public void sendpsdkreply2server(){
}
/** /**
* 响应reply * 响应reply
* @param entity * @param entity
*/ */
public void sendMsg2Server(MessageDown entity) { public void sendMsg2Server(MessageDown entity) {
LogUtil.log(TAG, "sendMsg2Server 入口, method=" + entity.getMethod() + ", tid=" + entity.getTid());
// 直接在主线程发送Paho 内部有独立发送线程不会阻塞主线程
mainHandler.post(() -> {
try { try {
LogUtil.log(TAG, "sendMsg2Server 执行, connected=" + MqttManager.getInstance().mqttAndroidClient.isConnected() + ", tid=" + entity.getTid());
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) { if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MessageReply messageReply = new MessageReply(); MessageReply messageReply = new MessageReply();
messageReply.setBid(entity.getBid()); messageReply.setBid(entity.getBid());
@ -112,9 +70,8 @@ public abstract class BaseManager {
e.printStackTrace(); e.printStackTrace();
LogUtil.log(TAG, "回复异常:" + e.toString() + ", tid=" + entity.getTid()); LogUtil.log(TAG, "回复异常:" + e.toString() + ", tid=" + entity.getTid());
} }
});
} }
final Handler mainHandler = new Handler(Looper.getMainLooper());
/** /**
* 响应replay+event * 响应replay+event

View File

@ -1082,6 +1082,12 @@ public class MqttCallBack extends BaseManager implements MqttCallbackExtended {
LogUtil.log(TAG, "未检测到图传5 秒后再次确认..."); LogUtil.log(TAG, "未检测到图传5 秒后再次确认...");
handler.postDelayed(() -> { handler.postDelayed(() -> {
// 返航/降落状态下视频流停止是正常现象不应重启App导致MQTT断连
int goHomeState = Movement.getInstance().getGoHomeState();
if (goHomeState == 1 || goHomeState == 2) {
LogUtil.log(TAG, "返航/降落中(goHomeState=" + goHomeState + ")跳过VTX检测不重启");
return;
}
if (!Movement.getInstance().isVtx()) { if (!Movement.getInstance().isVtx()) {
// 图传仍未恢复 执行重启逻辑 // 图传仍未恢复 执行重启逻辑
int times = PreferenceUtils.getInstance().getRestartAMSTimes(); int times = PreferenceUtils.getInstance().getRestartAMSTimes();

View File

@ -118,6 +118,11 @@ public class Osd {
private int wind_speed; private int wind_speed;
private boolean ocu_sync_lte; private boolean ocu_sync_lte;
private int ocu_sync_lte_time; private int ocu_sync_lte_time;
// ===== AMS配置参数 =====
private int close_obstacle_enable; // 关闭全向避障 0=开启避障 1=关闭避障
private int mission_interrupt_action; // 航线意外终止动作 1=悬停 2=继续 3=拉高返航
private int land_type; // 精准降落方式 1=RTK 2=视觉
private int camera_location_type; // 主相机位置 1= 2= 3= 4=融右 5=融中
public double getRtk_takeoff_altitude() { public double getRtk_takeoff_altitude() {
@ -168,6 +173,19 @@ public class Osd {
this.ocu_sync_lte_time = ocu_sync_lte_time; this.ocu_sync_lte_time = ocu_sync_lte_time;
} }
// ===== AMS配置参数 getters/setters =====
public int getClose_obstacle_enable() { return close_obstacle_enable; }
public void setClose_obstacle_enable(int close_obstacle_enable) { this.close_obstacle_enable = close_obstacle_enable; }
public int getMission_interrupt_action() { return mission_interrupt_action; }
public void setMission_interrupt_action(int mission_interrupt_action) { this.mission_interrupt_action = mission_interrupt_action; }
public int getLand_type() { return land_type; }
public void setLand_type(int land_type) { this.land_type = land_type; }
public int getCamera_location_type() { return camera_location_type; }
public void setCamera_location_type(int camera_location_type) { this.camera_location_type = camera_location_type; }
public int getActivation_time() { public int getActivation_time() {
return activation_time; return activation_time;
} }

View File

@ -1541,6 +1541,7 @@ public class FlightManager extends BaseManager {
KeyManager.getInstance().performAction(createKey(FlightControllerKey.KeyStartGoHome), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() { KeyManager.getInstance().performAction(createKey(FlightControllerKey.KeyStartGoHome), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override @Override
public void onSuccess(EmptyMsg emptyMsg) { public void onSuccess(EmptyMsg emptyMsg) {
LogUtil.log(TAG,"返航执行成功");
sendMsg2Server(message); sendMsg2Server(message);
} }

View File

@ -56,16 +56,33 @@ public class LTEManager extends BaseManager {
} }
}); });
KeyManager.getInstance().listen(KeyTools.createKey(AirLinkKey.KeyWlmLinkQualityLevel), this, new CommonCallbacks.KeyListener<WlmLinkQualityLevelInfo>() { // KeyManager.getInstance().listen(KeyTools.createKey(AirLinkKey.KeyWlmLinkQualityLevel), this, new CommonCallbacks.KeyListener<WlmLinkQualityLevelInfo>() {
// @Override
// public void onValueChange(@Nullable WlmLinkQualityLevelInfo wlmLinkQualityLevelInfo, @Nullable WlmLinkQualityLevelInfo t1) {
// if (t1 != null) {
// Movement.getInstance().setQuality_4g(t1.getLteLinkQualityLevel() + "");
// Movement.getInstance().setGnd_quality_4g(t1.getLteLinkQualityLevel() + "");
// Movement.getInstance().setUav_quality_4g(t1.getLteLinkQualityLevel() + "");
// }
// }
// });
dji.v5.manager.aircraft.lte.LTEManager.getInstance().addLTELinkInfoListener(new LTELinkInfoListener() {
@Override @Override
public void onValueChange(@Nullable WlmLinkQualityLevelInfo wlmLinkQualityLevelInfo, @Nullable WlmLinkQualityLevelInfo t1) { public void onLTELinkInfoUpdate(LTELinkInfo t1) {
if (t1 != null) { if (t1 != null) {
Movement.getInstance().setQuality_4g(t1.getLteLinkQualityLevel() + ""); LogUtil.log(TAG, "信号质量" + t1.getLinkQualityLevel());
Movement.getInstance().setGnd_quality_4g(t1.getLteLinkQualityLevel() + ""); if(t1.getLinkQualityLevel()!=null){
Movement.getInstance().setUav_quality_4g(t1.getLteLinkQualityLevel() + ""); Movement.getInstance().setQuality_4g(t1.getLinkQualityLevel().getLteGndSingalBar().value()+ "");
Movement.getInstance().setGnd_quality_4g(t1.getLinkQualityLevel().getOcuSyncSignalQualityLevel().value()+ "");
Movement.getInstance().setUav_quality_4g(t1.getLinkQualityLevel().getLteUavSingalBar().value()+ "");
}
} }
} }
}); });
KeyManager.getInstance().listen(KeyTools.createKey(AirLinkKey.KeyDownLinkQualityRaw), this, new CommonCallbacks.KeyListener<Integer>() { KeyManager.getInstance().listen(KeyTools.createKey(AirLinkKey.KeyDownLinkQualityRaw), this, new CommonCallbacks.KeyListener<Integer>() {
@Override @Override
public void onValueChange(@Nullable Integer integer, @Nullable Integer value) { public void onValueChange(@Nullable Integer integer, @Nullable Integer value) {

View File

@ -116,8 +116,8 @@ public class MediaManager extends BaseManager {
isPlaybackEnabling = true; isPlaybackEnabling = true;
// 停止端口扫描和 RTSP 刷新关闭 RTSP 推流确保媒体上传稳定 // 停止端口扫描和 RTSP 刷新关闭 RTSP 推流确保媒体上传稳定
StreamManager.getInstance().stopStreamRefreshTimer(); // StreamManager.getInstance().stopStreamRefreshTimer();
com.aros.apron.tools.SimplePortScanner.getInstance().stopScan(); //com.aros.apron.tools.SimplePortScanner.getInstance().stopScan();
StreamManager.getInstance().stopstream(); StreamManager.getInstance().stopstream();
// 仅首次调用时清理状态重试时保留计数器 // 仅首次调用时清理状态重试时保留计数器
@ -675,7 +675,7 @@ public class MediaManager extends BaseManager {
//退出媒体模式 //退出媒体模式
public void disablePlayback() { public void disablePlayback() {
// 任务结束停止视频流刷新定时器 // 任务结束停止视频流刷新定时器
StreamManager.getInstance().stopStreamRefreshTimer(); // StreamManager.getInstance().stopStreamRefreshTimer();
MediaDataCenter.getInstance().getMediaManager().disable(new CommonCallbacks.CompletionCallback() { MediaDataCenter.getInstance().getMediaManager().disable(new CommonCallbacks.CompletionCallback() {
@Override @Override
public void onSuccess() { public void onSuccess() {

View File

@ -236,7 +236,7 @@ public class MissionV3Manager extends BaseManager {
//航线飞行 //航线飞行
if (Movement.getInstance().getFlightmode() == 1) { if (Movement.getInstance().getFlightmode() == 1) {
Movement.getInstance().setMode_code(5);
} else if (Movement.getInstance().getFlightmode() == 2) { } else if (Movement.getInstance().getFlightmode() == 2) {
//指令飞行 //指令飞行
Movement.getInstance().setMode_code(17); Movement.getInstance().setMode_code(17);
@ -255,6 +255,13 @@ public class MissionV3Manager extends BaseManager {
// Movement.getInstance().setTask_status("in_progress"); // Movement.getInstance().setTask_status("in_progress");
// } // }
//航线飞行
if (Movement.getInstance().getFlightmode() == 1) {
Movement.getInstance().setMode_code(5);
} else if (Movement.getInstance().getFlightmode() == 2) {
}
Movement.getInstance().setVirtualStickQuitMission(false); Movement.getInstance().setVirtualStickQuitMission(false);
@ -617,17 +624,20 @@ public class MissionV3Manager extends BaseManager {
//4.返航或降落状态无法执行航线 //4.返航或降落状态无法执行航线
if (Movement.getInstance().getGoHomeState() == 1 || Movement.getInstance().getGoHomeState() == 2) { if (Movement.getInstance().getGoHomeState() == 1 || Movement.getInstance().getGoHomeState() == 2) {
sendFailMsg2Server(message, "返航中,无法执行航线任务"); sendFailMsg2Server(message, "返航中,无法执行航线任务");
LogUtil.log(TAG,"返航中,无法执行航线任务");
return false; return false;
} }
//5.检查航线备降点参数 //5.检查航线备降点参数
if (message.getData().getAlternate_land_point() == null) { if (message.getData().getAlternate_land_point() == null) {
sendEvent2Server("备降点参数异常", 2); sendEvent2Server("备降点参数异常", 2);
LogUtil.log(TAG,"备降点参数异常");
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
return false; return false;
} }
//6.检查航线参数 //6.检查航线参数
if (message.getData().getFile() == null) { if (message.getData().getFile() == null) {
sendEvent2Server("航线参数异常", 2); sendEvent2Server("航线参数异常", 2);
LogUtil.log(TAG,"航线参数异常");
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
return false; return false;
} }
@ -636,6 +646,7 @@ public class MissionV3Manager extends BaseManager {
KeyBatteryPowerPercent, 0)); KeyBatteryPowerPercent, 0));
if (value != null && value < Integer.parseInt(PreferenceUtils.getInstance().getMinumumBattery())) { if (value != null && value < Integer.parseInt(PreferenceUtils.getInstance().getMinumumBattery())) {
sendEvent2Server("任务执行失败,电量过低", 2); sendEvent2Server("任务执行失败,电量过低", 2);
LogUtil.log(TAG,"任务执行失败,电量过低");
TaskFailManager.getInstance().sendTaskFailMsg2Server(ErrorCode.DEVICE_BATTERY_LEVEL_TOO_LOW); TaskFailManager.getInstance().sendTaskFailMsg2Server(ErrorCode.DEVICE_BATTERY_LEVEL_TOO_LOW);
return false; return false;
} }
@ -643,6 +654,7 @@ public class MissionV3Manager extends BaseManager {
KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode)); KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode));
if (remoteControllerFlightMode != null && remoteControllerFlightMode != RemoteControllerFlightMode.P) { if (remoteControllerFlightMode != null && remoteControllerFlightMode != RemoteControllerFlightMode.P) {
sendEvent2Server("任务执行失败,请将遥控器切换为P/N挡", 2); sendEvent2Server("任务执行失败,请将遥控器切换为P/N挡", 2);
LogUtil.log(TAG,"任务执行失败,请将遥控器切换为P/N挡");
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
return false; return false;

View File

@ -16,6 +16,7 @@ import com.aros.apron.entity.Movement;
import com.aros.apron.entity.Osd; import com.aros.apron.entity.Osd;
import com.aros.apron.tools.LogUtil; import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager; import com.aros.apron.tools.MqttManager;
import com.aros.apron.tools.PreferenceUtils;
import com.aros.apron.tools.TakeoffProgressScheduler; import com.aros.apron.tools.TakeoffProgressScheduler;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -284,6 +285,17 @@ public class OSDManager extends BaseManager {
data.setOcu_sync_lte(Movement.getInstance().isOcuSyncLte()); data.setOcu_sync_lte(Movement.getInstance().isOcuSyncLte());
data.setOcu_sync_lte_time(Movement.getInstance().getOcuSyncLteTime()); data.setOcu_sync_lte_time(Movement.getInstance().getOcuSyncLteTime());
// ===== AMS配置参数写入OSD和日志 =====
int closeObstacle = PreferenceUtils.getInstance().getCloseObsEnable() ? 1 : 0;
data.setClose_obstacle_enable(closeObstacle);
int interruptAction = PreferenceUtils.getInstance().getMissionInterruptAction();
data.setMission_interrupt_action(interruptAction);
int landType = PreferenceUtils.getInstance().getLandType();
data.setLand_type(landType);
int cameraLoc = PreferenceUtils.getInstance().getCameraLocationType();
data.setCamera_location_type(cameraLoc);
Osd.Data.MaintainStatus maintainStatus = new Osd.Data.MaintainStatus(); Osd.Data.MaintainStatus maintainStatus = new Osd.Data.MaintainStatus();
Osd.Data.MaintainStatus.MaintainStatusArray maintainItem = new Osd.Data.MaintainStatus.MaintainStatusArray(); Osd.Data.MaintainStatus.MaintainStatusArray maintainItem = new Osd.Data.MaintainStatus.MaintainStatusArray();
// state: 保养状态, enum_int, 0:无保养, 1:有保养 // state: 保养状态, enum_int, 0:无保养, 1:有保养

View File

@ -247,7 +247,7 @@ public class RtspStreamManager {
mainHandler.post(() -> { mainHandler.post(() -> {
LogUtil.log(TAG, "强制启动RTSP推流成功"); LogUtil.log(TAG, "强制启动RTSP推流成功");
isStreaming.set(true); isStreaming.set(true);
startPortScanner(); //startPortScanner();
}); });
} }
@ -303,7 +303,7 @@ public class RtspStreamManager {
mainHandler.post(() -> { mainHandler.post(() -> {
LogUtil.log(TAG, "RTSP推流启动成功" + (isRestart ? "(重启)" : "")); LogUtil.log(TAG, "RTSP推流启动成功" + (isRestart ? "(重启)" : ""));
isStreaming.set(true); isStreaming.set(true);
startPortScanner(); //startPortScanner();
}); });
} }
@ -343,7 +343,7 @@ public class RtspStreamManager {
mainHandler.post(() -> { mainHandler.post(() -> {
LogUtil.log(TAG, "推流停止成功"); LogUtil.log(TAG, "推流停止成功");
isStreaming.set(false); isStreaming.set(false);
SimplePortScanner.getInstance().stopScan(); // SimplePortScanner.getInstance().stopScan();
}); });
} }

View File

@ -112,8 +112,8 @@ public class StreamManager extends BaseManager {
// ========== 新增重置推流状态用于端口关闭后重启 ========== // ========== 新增重置推流状态用于端口关闭后重启 ==========
public void resetStreamState() { public void resetStreamState() {
stopStreamRefreshTimer(); //stopStreamRefreshTimer();
SimplePortScanner.getInstance().stopScan(); // 同时停止端口扫描 // SimplePortScanner.getInstance().stopScan(); // 同时停止端口扫描
mainHandler.removeCallbacksAndMessages(null); // 清理所有待执行的回调 mainHandler.removeCallbacksAndMessages(null); // 清理所有待执行的回调
startLiveFailTimes = 0; startLiveFailTimes = 0;
isLiveStreamAlreadyStart = false; isLiveStreamAlreadyStart = false;
@ -277,6 +277,7 @@ public class StreamManager extends BaseManager {
public void switchptspfpv(ComponentIndexType ComponentIndex, MessageDown message) { public void switchptspfpv(ComponentIndexType ComponentIndex, MessageDown message) {
if(isliveindex==2){ if(isliveindex==2){
sendMsg2Server(message);
return; return;
} }
isliveindex = 2; isliveindex = 2;
@ -302,6 +303,7 @@ public class StreamManager extends BaseManager {
public void switchptspport(ComponentIndexType ComponentIndex, MessageDown message) { public void switchptspport(ComponentIndexType ComponentIndex, MessageDown message) {
if(isliveindex==1){ if(isliveindex==1){
sendMsg2Server(message);
return; return;
} }
isliveindex = 1; isliveindex = 1;
@ -470,9 +472,9 @@ public class StreamManager extends BaseManager {
isStartingRTSP = false; // 重置并发标志 isStartingRTSP = false; // 重置并发标志
LogUtil.log(TAG, "========== RTSP 推流启动成功 =========="); LogUtil.log(TAG, "========== RTSP 推流启动成功 ==========");
// 启动5秒定时刷新视频流防止起飞卡死 // 启动5秒定时刷新视频流防止起飞卡死
startStreamRefreshTimer(); // startStreamRefreshTimer();
// 开始端口扫描 // 开始端口扫描
SimplePortScanner.getInstance().startScan(); // SimplePortScanner.getInstance().startScan();
}); });
} }

View File

@ -129,11 +129,13 @@ public class TakeOffToPointManager extends BaseManager {
if (Movement.getInstance().getGoHomeState() == 1 if (Movement.getInstance().getGoHomeState() == 1
|| Movement.getInstance().getGoHomeState() == 2) { || Movement.getInstance().getGoHomeState() == 2) {
sendFailMsg2Server(message, "返航中,无法执行航线任务"); sendFailMsg2Server(message, "返航中,无法执行航线任务");
LogUtil.log(TAG,"返航中,无法执行航线任务");
return false; return false;
} }
//5.检查航线备降点参数 //5.检查航线备降点参数
if (message.getData().getAlternate_land_point() == null) { if (message.getData().getAlternate_land_point() == null) {
sendEvent2Server("备降点参数异常", 2); sendEvent2Server("备降点参数异常", 2);
LogUtil.log(TAG,"备降点参数异常");
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
return false; return false;
} }
@ -148,6 +150,7 @@ public class TakeOffToPointManager extends BaseManager {
KeyBatteryPowerPercent, 0)); KeyBatteryPowerPercent, 0));
if (value != null && value < Integer.parseInt(PreferenceUtils.getInstance().getMinumumBattery())) { if (value != null && value < Integer.parseInt(PreferenceUtils.getInstance().getMinumumBattery())) {
sendEvent2Server("任务执行失败,电量过低", 2); sendEvent2Server("任务执行失败,电量过低", 2);
LogUtil.log(TAG,"任务执行失败,电量过低");
TaskFailManager.getInstance().sendTaskFailMsg2Server(ErrorCode.DEVICE_BATTERY_LEVEL_TOO_LOW); TaskFailManager.getInstance().sendTaskFailMsg2Server(ErrorCode.DEVICE_BATTERY_LEVEL_TOO_LOW);
return false; return false;
} }
@ -155,6 +158,7 @@ public class TakeOffToPointManager extends BaseManager {
KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode)); KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode));
if (remoteControllerFlightMode != null && remoteControllerFlightMode != RemoteControllerFlightMode.P) { if (remoteControllerFlightMode != null && remoteControllerFlightMode != RemoteControllerFlightMode.P) {
sendEvent2Server("任务执行失败,请将遥控器切换为P/N挡", 2); sendEvent2Server("任务执行失败,请将遥控器切换为P/N挡", 2);
LogUtil.log(TAG,"任务执行失败,请将遥控器切换为P/N挡");
TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1);
return false; return false;
} }
@ -277,7 +281,6 @@ public class TakeOffToPointManager extends BaseManager {
} }
return false; return false;
} }
/** /**
* 6.上传指点航线 * 6.上传指点航线
* *

View File

@ -244,63 +244,67 @@ public class AprilTagPort {
return; return;
} }
// 高度纯AprilTag // 高度来源
// 备用超声波兜底需要时取消注释 // 备用超声波兜底需要时取消注释
// double ultraM = ultrasonicHeight / 10.0; // double ultraM = ultrasonicHeight / 10.0;
// double altM = (ultrasonicHeight > 0 && ultrasonicHeight <= 50) // double altM = (ultrasonicHeight > 0 && ultrasonicHeight <= 50)
// ? ultraM : smoothZ; // ? ultraM : smoothZ;
double altM = smoothZ; double altM = smoothZ; // 单位AprilTag位姿Z分量相机离地高度
// 统一 PID2m以上边转边降2m以下只平移 // 偏差绝对值
double absX = Math.abs(smoothX); double absX = Math.abs(smoothX); // 降落点左右偏差
double absY = Math.abs(smoothY); double absY = Math.abs(smoothY); // 降落点前后偏差
double absYaw = Math.abs(smoothYaw); double absYaw = Math.abs(smoothYaw); // 偏航角偏差
boolean aboveTwo = altM > 2.0; // 阶段判断
boolean yawAligned = absYaw <= 5.0; boolean aboveTwo = altM > 2.0; // 2米以上
boolean yawAligned = absYaw <= 5.0; // 5度以内算对准
// X/Y 水平 PID动态缩放 // X/Y 水平 PID动态缩放类似 errPx/scaleFactor
double scaleXY = Math.max(altM * 0.6, 0.3); double scaleXY = Math.max(altM * 0.6, 0.3); // 缩放因子最小0.3
double normX = smoothX / scaleXY; double normX = smoothX / scaleXY; // 归一化输入无单位
double normY = smoothY / scaleXY; double normY = smoothY / scaleXY; // 归一化输入无单位
double speedLimit = MAX_HORIZ_SPEED; // 水平速度上限越低越慢防过冲
if (altM < 1.0) speedLimit = 0.2; double speedLimit = MAX_HORIZ_SPEED; // >3m: 1.2 m/s
else if (altM < 2.0) speedLimit = 0.5; if (altM < 1.0) speedLimit = 0.2; // <1m: 0.2 m/s
else if (altM < 3.0) speedLimit = 0.8; else if (altM < 2.0) speedLimit = 0.5; // 1~2m: 0.5 m/s
float maxV = (float) speedLimit; else if (altM < 3.0) speedLimit = 0.8; // 2~3m: 0.8 m/s
float maxV = (float) speedLimit; // m/s
pidX.setInputFilterAll((float) normX); pidX.setInputFilterAll((float) normX);
pidY.setInputFilterAll((float) normY); pidY.setInputFilterAll((float) normY);
float vx = clamp(pidX.get_pid(), maxV); float vx = clamp(pidX.get_pid(), maxV); // m/s前后
float vy = clamp(pidY.get_pid(), maxV); float vy = clamp(pidY.get_pid(), maxV); // m/s左右
if (absX < 0.02) vx = 0f; if (absX < 0.02) vx = 0f; // <2cm死区
if (absY < 0.02) vy = 0f; if (absY < 0.02) vy = 0f; // <2cm死区
// Yaw2m以上边转边降确保到2m时已转好2m以下不转 // Yaw旋转2m以上边转边降2m以下不转
float yawRate = 0f; float yawRate = 0f; // °/s
if (aboveTwo && !yawAligned) { if (aboveTwo && !yawAligned) {
boolean nearTwo = altM <= 3.0; // 2-3m紧急修正区 boolean nearTwo = altM <= 3.0; // 2~3m紧急修正区
if (nearTwo) { if (nearTwo) {
// 接近2m全力转确保到2m时对准 // 全力转确保到2m时对准
yawRate = (absYaw > 10.0) ? 40.0f : 8.0f; yawRate = (absYaw > 10.0) ? 40.0f : 8.0f;
} else { } else {
// 3m以上从容修正 // 3m以上从容修正
if (absYaw > 60.0) yawRate = 35.0f; if (absYaw > 60.0) yawRate = 35.0f; // >60°偏差
else if (absYaw > 30.0) yawRate = 25.0f; else if (absYaw > 30.0) yawRate = 25.0f; // 30~60°
else if (absYaw > 15.0) yawRate = 15.0f; else if (absYaw > 15.0) yawRate = 15.0f; // 15~30°
else if (absYaw > 8.0) yawRate = 8.0f; else if (absYaw > 8.0) yawRate = 8.0f; // 8~15°
else yawRate = 5.0f; else yawRate = 5.0f; // 5~8°
} }
yawRate = (smoothYaw > 0) ? -yawRate : yawRate; yawRate = (smoothYaw > 0) ? -yawRate : yawRate; // 反向修正
} }
// 垂直速度一路降到底 // 垂直速度一路降到底
float baseDescent = mapHeightToDescent((float) altM); float baseDescent = mapHeightToDescent((float) altM); // m/s基础下降率
// 对齐系数偏差大降慢对准全速[0.15, 1.0]
float alignFactor = 1.0f - clamp01( float alignFactor = 1.0f - clamp01(
(float) Math.max(absX / 0.3, absY / 0.3)); (float) Math.max(absX / 0.3, absY / 0.3));
alignFactor = Math.max(0.15f, alignFactor); // absX=0.3m0.0, absX=0m1.0, absX>=0.255m0.15
float vz = baseDescent * alignFactor; alignFactor = Math.max(0.15f, alignFactor); // 最低15%
float vz = baseDescent * alignFactor; // m/s最终下降速度=下降
LogUtil.log(TAG, String.format( LogUtil.log(TAG, String.format(
"【统一PID】vx=%.3f vy=%.3f yaw=%.1f vz=%.2f | err=(%.3f,%.3f,%.1f°) alt=%.2fm tag=%d", "【统一PID】vx=%.3f vy=%.3f yaw=%.1f vz=%.2f | err=(%.3f,%.3f,%.1f°) alt=%.2fm tag=%d",

View File

@ -0,0 +1,211 @@
//package com.aros.apron.tools;
//
//import org.dom4j.Document;
//import org.dom4j.Element;
//import org.dom4j.io.SAXReader;
//
//import java.io.ByteArrayInputStream;
//import java.io.ByteArrayOutputStream;
//import java.io.InputStream;
//import java.nio.file.Files;
//import java.nio.file.Path;
//import java.nio.file.Paths;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.zip.ZipEntry;
//import java.util.zip.ZipInputStream;
//
///**
// * KMZ航点解析经纬度悬停时间
// *
// * <p>单文件自包含解压 kmz -> 读取 wpmz/template.kml -> 解析航点</p>
// *
// * @author 938693313@qq.com
// * @since 1.0.0 2026-06-09
// */
//public class KmzParseController {
//
// /** kmz 内航线模板文件路径 */
// private static final String TEMPLATE_KML = "wpmz/template.kml";
//
// @PostMapping("waypoint")
// @Operation(summary = "解析KMZ航点经纬度、悬停时间")
// public Result<List<Waypoint>> parseWaypoint(
// @Parameter(name = "file", description = "kmz文件") @RequestParam("file") MultipartFile file) {
// if (file == null || file.isEmpty()) {
// throw new RenException("kmz文件不能为空");
// }
//
// try (InputStream in = file.getInputStream()) {
// byte[] templateKml = readTemplateKml(in);
// if (templateKml == null) {
// throw new RenException("kmz文件中未找到 " + TEMPLATE_KML);
// }
// return new Result<List<Waypoint>>().ok(parse(templateKml));
// } catch (RenException e) {
// throw e;
// } catch (Exception e) {
// throw new RenException("kmz文件解析失败" + e.getMessage());
// }
// }
//
// @GetMapping("waypointByPath")
// @Operation(summary = "解析本地路径的KMZ航点经纬度、悬停时间")
// public Result<List<Waypoint>> parseWaypointByPath(
// @Parameter(name = "path", description = "kmz文件本地绝对路径") @RequestParam("path") String path) {
// if (StringUtils.isBlank(path)) {
// throw new RenException("kmz文件路径不能为空");
// }
// Path filePath = Paths.get(path.trim());
// if (!Files.exists(filePath) || Files.isDirectory(filePath)) {
// throw new RenException("kmz文件不存在" + path);
// }
//
// try (InputStream in = Files.newInputStream(filePath)) {
// byte[] templateKml = readTemplateKml(in);
// if (templateKml == null) {
// throw new RenException("kmz文件中未找到 " + TEMPLATE_KML);
// }
// return new Result<List<Waypoint>>().ok(parse(templateKml));
// } catch (RenException e) {
// throw e;
// } catch (Exception e) {
// throw new RenException("kmz文件解析失败" + e.getMessage());
// }
// }
//
// /**
// * kmzzip流中读取 wpmz/template.kml 的字节内容
// */
// private byte[] readTemplateKml(InputStream in) throws Exception {
// try (ZipInputStream zis = new ZipInputStream(in)) {
// ZipEntry entry;
// while ((entry = zis.getNextEntry()) != null) {
// if (TEMPLATE_KML.equals(entry.getName())) {
// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// byte[] buffer = new byte[8192];
// int len;
// while ((len = zis.read(buffer)) > 0) {
// bos.write(buffer, 0, len);
// }
// return bos.toByteArray();
// }
// zis.closeEntry();
// }
// }
// return null;
// }
//
// /**
// * 解析 template.kml提取每个航点的经纬度与悬停时间
// * 同一航点下存在多个 hover 动作时悬停时间累加
// */
// private List<Waypoint> parse(byte[] kml) throws Exception {
// List<Waypoint> result = new ArrayList<>();
//
// SAXReader reader = new SAXReader();
// Document document = reader.read(new ByteArrayInputStream(kml));
// Element root = document.getRootElement();
//
// Element doc = root.element("Document");
// if (doc == null) {
// throw new RenException("kml文件有误无法解析");
// }
// Element folder = doc.element("Folder");
// if (folder == null) {
// throw new RenException("模板信息不存在,无法解析");
// }
//
// List<Element> placemarks = folder.elements("Placemark");
// if (placemarks == null || placemarks.isEmpty()) {
// throw new RenException("航点信息不存在,无法解析");
// }
//
// for (Element placemark : placemarks) {
// Waypoint waypoint = new Waypoint();
//
// // 航点序号
// String index = placemark.elementText("index");
// waypoint.setIndex(StringUtils.isBlank(index) ? null : Integer.valueOf(index));
//
// // 经纬度coordinates 格式为 "经度,纬度"
// Element point = placemark.element("Point");
// if (point != null) {
// String coordinates = point.elementText("coordinates");
// if (StringUtils.isNotBlank(coordinates)) {
// String[] split = coordinates.replaceAll("\\s+", "").split(",");
// if (split.length >= 2) {
// waypoint.setLongitude(Double.valueOf(split[0]));
// waypoint.setLatitude(Double.valueOf(split[1]));
// }
// }
// }
//
// // 悬停时间累加该航点所有 actionGroup hover 动作的 hoverTime
// int hoverTime = 0;
// List<Element> actionGroups = placemark.elements("actionGroup");
// for (Element actionGroup : actionGroups) {
// List<Element> actions = actionGroup.elements("action");
// for (Element action : actions) {
// if (!"hover".equals(action.elementText("actionActuatorFunc"))) {
// continue;
// }
// Element funcParam = action.element("actionActuatorFuncParam");
// if (funcParam == null) {
// continue;
// }
// String hover = funcParam.elementText("hoverTime");
// if (StringUtils.isNotBlank(hover)) {
// hoverTime += (int) Math.round(Double.parseDouble(hover));
// }
// }
// }
// waypoint.setHoverTime(hoverTime);
//
// result.add(waypoint);
// }
// return result;
// }
//
// /**
// * 航点解析结果
// */
// public static class Waypoint {
// /** 航点序号 */
// private Integer index;
// /** 经度 */
// private Double longitude;
// /** 纬度 */
// private Double latitude;
// /** 悬停时间同一航点多个hover动作累加 */
// private Integer hoverTime;
//
// public Integer getIndex() {
// return index;
// }
//
// public void setIndex(Integer index) {
// this.index = index;
// }
//
// public Double getLongitude() {
// return longitude;
// }
//
// public void setLongitude(Double longitude) {
// this.longitude = longitude;
// }
//
// public Double getLatitude() {
// return latitude;
// }
//
// public void setLatitude(Double latitude) {
// this.latitude = latitude;
// }
//
// public void setHoverTime(Integer hoverTime) {
// this.hoverTime = hoverTime;
// }
// }
//}

View File

@ -42,12 +42,11 @@ public class MqttManager {
public void needConnect() { public void needConnect() {
initMqttClientParams(); initMqttClientParams();
} }
private void initMqttClientParams() { private void initMqttClientParams() {
mqttAndroidClient = new MqttAndroidClient(ApronApp.Companion.getApplication(), AMSConfig.getInstance().getMqttServerUri(), generateRandomString(10)); mqttAndroidClient = new MqttAndroidClient(ApronApp.Companion.getApplication(), AMSConfig.getInstance().getMqttServerUri(), generateRandomString(10));
mMqttConnectOptions = new MqttConnectOptions(); mMqttConnectOptions = new MqttConnectOptions();
mMqttConnectOptions.setAutomaticReconnect(true); //ltz add mMqttConnectOptions.setAutomaticReconnect(true);
mMqttConnectOptions.setMaxInflight(1000);// 增加最大并发未确认消息数量 mMqttConnectOptions.setMaxInflight(1000);// 避免消息积压导致连接拥塞
mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存 mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存
mMqttConnectOptions.setConnectionTimeout(30); //设置超时时间单位 ltz denote mMqttConnectOptions.setConnectionTimeout(30); //设置超时时间单位 ltz denote
mMqttConnectOptions.setKeepAliveInterval(20); //设置心跳包发送间隔单位 ltz denote mMqttConnectOptions.setKeepAliveInterval(20); //设置心跳包发送间隔单位 ltz denote