diff --git a/app/build.gradle b/app/build.gradle index f16d44e6..737c6ea1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -126,6 +126,13 @@ android { pickFirst 'lib/x86_64/libc++_shared.so' pickFirst 'lib/armeabi-v7a/libc++_shared.so' pickFirst 'lib/arm64-v8a/libc++_shared.so' + + pickFirst 'lib/arm64-v8a/libxcrash.so' + pickFirst 'lib/arm64-v8a/libxcrash_dumper.so' + pickFirst 'lib/arm64-v8a/libsqlcipher.so' + pickFirst 'lib/armeabi-v7a/libsqlcipher.so' + pickFirst 'lib/x86/libsqlcipher.so' + pickFirst 'lib/x86_64/libsqlcipher.so' } packagingOptions { @@ -193,9 +200,9 @@ dependencies { implementation 'com.commonsware.cwac:saferoom.x:1.3.0' - implementation 'com.dji:dji-sdk-v5-aircraft:5.16.0' - compileOnly 'com.dji:dji-sdk-v5-aircraft-provided:5.16.0' - implementation 'com.dji:dji-sdk-v5-networkImp:5.16.0' + implementation 'com.dji:dji-sdk-v5-aircraft:5.18.0' + compileOnly 'com.dji:dji-sdk-v5-aircraft-provided:5.18.0' + implementation 'com.dji:dji-sdk-v5-networkImp:5.18.0' // implementation 'com.shd:dji-uxsdk:5.9.1' diff --git a/app/src/main/java/com/aros/apron/activity/MainActivity.kt b/app/src/main/java/com/aros/apron/activity/MainActivity.kt index 20cef3f3..fd0f8358 100644 --- a/app/src/main/java/com/aros/apron/activity/MainActivity.kt +++ b/app/src/main/java/com/aros/apron/activity/MainActivity.kt @@ -33,6 +33,7 @@ import com.aros.apron.manager.FlightTaskProgressManager import com.aros.apron.manager.GimbalManager import com.aros.apron.manager.LEDsSettingsManager import com.aros.apron.manager.LTEManager +import com.aros.apron.manager.MLTEManager import com.aros.apron.manager.MediaManager import com.aros.apron.manager.MissionV3Manager import com.aros.apron.manager.NavigationSatelliteSystemManager @@ -803,6 +804,17 @@ open class MainActivity : BaseActivity() { GimbalManager.getInstance().setmode() PayloadWidgetManager.getInstance().initPayloadInfo() + if (PreferenceUtils.getInstance().lteEnable){ + // LogUtil.log("qwq","lteEnable"+PreferenceUtils.getInstance().lteEnable) + MLTEManager.getInstance().initLTEManager() + Handler().postDelayed(Runnable { MLTEManager.getInstance().setLTEEnhancedTransmissionType()},3000) + + } + + + + LogUtil.log("qwq","lteEnable"+PreferenceUtils.getInstance().lteEnable) + LogUtil.log(TAG, "自定义推流方式:" + PreferenceUtils.getInstance().customStreamType) Handler(Looper.getMainLooper()).postDelayed({ @@ -833,6 +845,16 @@ open class MainActivity : BaseActivity() { LEDsSettingsManager.getInstance().initLEDsInfo() RTKManager.getInstance().initRTKInfo() LTEManager.getInstance().initLTEInfo() + + + // LogUtil.log("qwq","lteEnable"+PreferenceUtils.getInstance().lteEnable) + if (PreferenceUtils.getInstance().lteEnable){ + // LogUtil.log("qwq","lteEnable"+PreferenceUtils.getInstance().lteEnable) + MLTEManager.getInstance().initLTEManager() + Handler().postDelayed(Runnable { MLTEManager.getInstance().setLTEEnhancedTransmissionType()},3000) + + } + WirelessLinkManager.getInstance().initWirelessLink() CameraManager.getInstance().initCameraInfo() NavigationSatelliteSystemManager.getInstance().initNavigationSatelliteSystem() @@ -885,11 +907,23 @@ open class MainActivity : BaseActivity() { initCameraStream() startVtxHeartbeat() + SpeakerManager.getInstance().addMegaphoneInfoListener() GeoidManager.getInstance().init(this) GimbalManager.getInstance().setmode() PayloadWidgetManager.getInstance().initPayloadInfo() + + // LogUtil.log("qwq","lteEnable"+PreferenceUtils.getInstance().lteEnable) + + if (PreferenceUtils.getInstance().lteEnable){ + // LogUtil.log("qwq","lteEnable"+PreferenceUtils.getInstance().lteEnable) + MLTEManager.getInstance().initLTEManager() + Handler().postDelayed(Runnable { MLTEManager.getInstance().setLTEEnhancedTransmissionType()},3000) + + } + + LogUtil.log(TAG, "自定义推流方式:" + PreferenceUtils.getInstance().customStreamType) Handler(Looper.getMainLooper()).postDelayed({ @@ -1167,7 +1201,7 @@ open class MainActivity : BaseActivity() { }, 6000) } else if (PreferenceUtils.getInstance().cameraLocationType == 4 || PreferenceUtils.getInstance().cameraLocationType == 5) { Handler().postDelayed(Runnable { - if (!Aprongim.getInstance().isTriggerSuccess) { + if (!Aprondown.getInstance().isTriggerSuccess) { LogUtil.log(TAG, "图传异常:飞往备降点") //测试图传丢失 AlternateLandingManager.getInstance().startTaskProcess(null) diff --git a/app/src/main/java/com/aros/apron/callback/MqttCallBack.java b/app/src/main/java/com/aros/apron/callback/MqttCallBack.java index ecd9436a..1d202050 100644 --- a/app/src/main/java/com/aros/apron/callback/MqttCallBack.java +++ b/app/src/main/java/com/aros/apron/callback/MqttCallBack.java @@ -21,6 +21,7 @@ import com.aros.apron.manager.CameraManager; import com.aros.apron.manager.FlightManager; import com.aros.apron.manager.FlyToPointManager; import com.aros.apron.manager.GimbalManager; +import com.aros.apron.manager.MLTEManager; import com.aros.apron.manager.MissionV3Manager; import com.aros.apron.manager.OSDManager; import com.aros.apron.manager.PayloadlightManager; @@ -191,7 +192,6 @@ public class MqttCallBack extends BaseManager implements MqttCallbackExtended { MissionV3Manager.getInstance().taskExecute(message); Synchronizedstatus.setIsruning(true); - Synchronizedstatus.setFlighttaskExecuteStatus(true); }else{ @@ -318,7 +318,7 @@ public class MqttCallBack extends BaseManager implements MqttCallbackExtended { StickManager.getInstance().disableVirtualStick(message); break; case Constant.DRONE_CONTROL: - LogUtil.log(TAG, "收到:DRC-飞行控制" + jsonString); + LogUtil.log(TAG, " " + jsonString); if (!Movement.getInstance().isAlternate() && !ApronArucoDetectPort.getInstance().isStartAruco() && !ApronArucoDetect.getInstance().isStartAruco() && !Aprongim.getInstance().isStartAruco() && !Aprondown.getInstance().isStartAruco()) { resetVirtualStickHeartbeat(); StickManager.getInstance().sendVirtualStickAdvancedParam(message); @@ -630,6 +630,55 @@ public class MqttCallBack extends BaseManager implements MqttCallbackExtended { } break; + case Constant.LTE_GET_VERIFICATION_CODE: + LogUtil.log(TAG, "收到:LTE认证-获取验证码 " + jsonString); + if (message.getData() != null) { + String phoneAreaCode = message.getData().getPhone_area_code(); + String phoneNumber = message.getData().getPhone_number(); + if (phoneNumber != null && !phoneNumber.isEmpty()) { + if (phoneAreaCode == null || phoneAreaCode.isEmpty()) { + phoneAreaCode = "86"; + } + MLTEManager.getInstance().requestLTEVerificationCode(phoneAreaCode, phoneNumber); + } else { + LogUtil.log(TAG, "LTE认证手机号为空"); + sendEvent2Server("LTE认证手机号为空",1); + sendFailMsg2Server(message, "LTE认证手机号为空"); + } + } + break; + + case Constant.LTE_START_AUTHENTICATION: + LogUtil.log(TAG, "收到:LTE认证-提交验证码 " + jsonString); + String verificationCode = message.getData() != null ? message.getData().getVerification_code() : null; + if (verificationCode != null && !verificationCode.isEmpty()) { + MLTEManager.getInstance().startLTEAuthentication(verificationCode, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + LogUtil.log(TAG, "LTE认证成功"); + sendEvent2Server("LTE认证成功",1); + sendMsg2Server(message); + } + + @Override + public void onFailure(@NonNull IDJIError idjiError) { + LogUtil.log(TAG, "LTE认证失败: " + new Gson().toJson(idjiError)); + sendEvent2Server("LTE认证失败",2); + sendFailMsg2Server(message, "LTE认证失败: " + idjiError); + } + }); + } else { + LogUtil.log(TAG, "LTE验证码为空"); + sendFailMsg2Server(message, "LTE验证码为空"); + } + break; + + case Constant.HANGXIANTEST: + MLTEManager.getInstance().test(); + break; + + + // //获取控制权 // case 60007: // LogUtil.log(TAG, "收到:获取控制权" + jsonString); @@ -1027,7 +1076,8 @@ public class MqttCallBack extends BaseManager implements MqttCallbackExtended { if (times < 5) { PreferenceUtils.getInstance().setRestartAMSTimes(times + 1); LogUtil.log(TAG, "图传仍未恢复,重启 AMS 第 " + (times + 1) + " 次"); - RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext()); + new Handler(Looper.getMainLooper()).postDelayed(() -> + RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext()), 1000); } } else { // 图传恢复 → 执行后续逻辑 diff --git a/app/src/main/java/com/aros/apron/constant/Constant.java b/app/src/main/java/com/aros/apron/constant/Constant.java index 205f3eb6..15c13ef7 100644 --- a/app/src/main/java/com/aros/apron/constant/Constant.java +++ b/app/src/main/java/com/aros/apron/constant/Constant.java @@ -352,6 +352,20 @@ public class Constant { */ public static final String APP_UPDATE="app_update"; + /** + * LTE认证-获取验证码 + */ + public static final String LTE_GET_VERIFICATION_CODE="lte_get_verification_code"; + + /** + * LTE认证-提交验证码 + */ + public static final String LTE_START_AUTHENTICATION="lte_start_authentication"; + + /** + * 航线测试 + */ + public static final String HANGXIANTEST="hangxiantest"; } diff --git a/app/src/main/java/com/aros/apron/entity/MessageDown.java b/app/src/main/java/com/aros/apron/entity/MessageDown.java index 38488b2d..1d5af8e5 100644 --- a/app/src/main/java/com/aros/apron/entity/MessageDown.java +++ b/app/src/main/java/com/aros/apron/entity/MessageDown.java @@ -122,6 +122,11 @@ public class MessageDown { private int language; private Tts tts; + //LTE认证 + private String phone_area_code; + private String phone_number; + private String verification_code; + //探照灯 private int group; // brightness: 亮度 1-100 (int) @@ -147,6 +152,30 @@ public class MessageDown { this.group = group; } + public String getPhone_area_code() { + return phone_area_code; + } + + public void setPhone_area_code(String phone_area_code) { + this.phone_area_code = phone_area_code; + } + + public String getPhone_number() { + return phone_number; + } + + public void setPhone_number(String phone_number) { + this.phone_number = phone_number; + } + + public String getVerification_code() { + return verification_code; + } + + public void setVerification_code(String verification_code) { + this.verification_code = verification_code; + } + public int getBrightness() { return brightness; } diff --git a/app/src/main/java/com/aros/apron/entity/Movement.java b/app/src/main/java/com/aros/apron/entity/Movement.java index 045d76e6..6b436e7e 100644 --- a/app/src/main/java/com/aros/apron/entity/Movement.java +++ b/app/src/main/java/com/aros/apron/entity/Movement.java @@ -77,6 +77,8 @@ public class Movement { private String minTemperaturePointX;//最小温度的位置 private String minTemperaturePointY; private String LTELinkType;//图传类型 1cusync 图传 3LTE 增强图传 + private String ltePhoneAreaCode = "";//LTE认证手机号区号 + private String ltePhoneNumber = "";//LTE认证手机号 private int goHomeHeight;//返航高度 private int failsafeAction;//失控动作 private int heightLimit;//限高 @@ -2170,6 +2172,22 @@ public class Movement { this.LTELinkType = LTELinkType; } + public String getLtePhoneAreaCode() { + return ltePhoneAreaCode; + } + + public void setLtePhoneAreaCode(String ltePhoneAreaCode) { + this.ltePhoneAreaCode = ltePhoneAreaCode; + } + + public String getLtePhoneNumber() { + return ltePhoneNumber; + } + + public void setLtePhoneNumber(String ltePhoneNumber) { + this.ltePhoneNumber = ltePhoneNumber; + } + public int getIsVirtualStickAdvancedModeEnabled() { return isVirtualStickAdvancedModeEnabled; } diff --git a/app/src/main/java/com/aros/apron/manager/FlightManager.java b/app/src/main/java/com/aros/apron/manager/FlightManager.java index 22cb4396..33d2fe2a 100644 --- a/app/src/main/java/com/aros/apron/manager/FlightManager.java +++ b/app/src/main/java/com/aros/apron/manager/FlightManager.java @@ -386,6 +386,7 @@ public class FlightManager extends BaseManager { if (newValue != null) { Movement.getInstance().setGps_number(newValue); Movement.getInstance().setRtk_number(newValue); + // LogUtil.log(TAG,"number"+newValue); pushFlightAttitude(); } } diff --git a/app/src/main/java/com/aros/apron/manager/LTEManager.java b/app/src/main/java/com/aros/apron/manager/LTEManager.java index a0a4d01a..ebeeb0b0 100644 --- a/app/src/main/java/com/aros/apron/manager/LTEManager.java +++ b/app/src/main/java/com/aros/apron/manager/LTEManager.java @@ -19,6 +19,7 @@ import dji.sdk.keyvalue.value.airlink.WlmLinkFrequenceBand; import dji.sdk.keyvalue.value.airlink.WlmLinkQualityLevelInfo; import dji.sdk.keyvalue.value.airlink.WlmLinkStatus; import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; import dji.v5.manager.KeyManager; import dji.v5.manager.aircraft.lte.LTEDongleInfoListener; import dji.v5.manager.aircraft.lte.LTELinkInfo; @@ -140,4 +141,61 @@ public class LTEManager extends BaseManager { LogUtil.log(TAG, "初始化LTE失败"); } } + +// /** +// * 启动LTE认证,认证通过后可调用setLTEEnhancedTransmissionType开启LTE增强图传 +// * 调用前需先通过getLTEAuthenticationVerificationCode获取验证码 +// * +// * @param phoneNumber LTE认证手机号码 +// * @param verificationCode LTE认证验证码 +// * @param callback 执行结果回调 +// */ +// public void startLTEAuthentication(String phoneNumber, String verificationCode, CommonCallbacks.CompletionCallback callback) { +// LogUtil.log(TAG, "startLTEAuthentication phone:" + phoneNumber); +// dji.v5.manager.interfaces.ILTEManager.getInstance().startLTEAuthentication( +// "86", +// phoneNumber, +// verificationCode, +// new CommonCallbacks.CompletionCallback() { +// @Override +// public void onResult(Object o, IDJIError iDJIError) { +// if (iDJIError == null) { +// LogUtil.log(TAG, "LTE认证成功"); +// } else { +// LogUtil.log(TAG, "LTE认证失败: " + iDJIError.getDescription()); +// } +// if (callback != null) { +// callback.onResult(o, iDJIError); +// } +// } +// } +// ); +// } +// +// /** +// * 获取LTE认证验证码 +// * +// * @param phoneNumber LTE认证手机号码 +// * @param callback 执行结果回调 +// */ +// public void getLTEAuthenticationVerificationCode(String phoneNumber, CommonCallbacks.CompletionCallback callback) { +// LogUtil.log(TAG, "getLTEAuthenticationVerificationCode phone:" + phoneNumber); +// dji.v5.manager.interfaces.ILTEManager.getInstance().getLTEAuthenticationVerificationCode( +// "86", +// phoneNumber, +// new CommonCallbacks.CompletionCallback() { +// @Override +// public void onResult(Object o, IDJIError iDJIError) { +// if (iDJIError == null) { +// LogUtil.log(TAG, "获取验证码成功"); +// } else { +// LogUtil.log(TAG, "获取验证码失败: " + iDJIError.getDescription()); +// } +// if (callback != null) { +// callback.onResult(o, iDJIError); +// } +// } +// } +// ); +// } } \ No newline at end of file diff --git a/app/src/main/java/com/aros/apron/manager/MLTEManager.java b/app/src/main/java/com/aros/apron/manager/MLTEManager.java new file mode 100644 index 00000000..0b8b390e --- /dev/null +++ b/app/src/main/java/com/aros/apron/manager/MLTEManager.java @@ -0,0 +1,182 @@ +package com.aros.apron.manager; + +import android.os.Handler; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.aros.apron.base.BaseManager; +import com.aros.apron.entity.Movement; +import com.aros.apron.tools.LogUtil; +import com.google.gson.Gson; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.manager.aircraft.lte.LTEAuthenticationInfo; +import dji.v5.manager.aircraft.lte.LTEAuthenticationInfoListener; +import dji.v5.manager.aircraft.lte.LTELinkInfo; +import dji.v5.manager.aircraft.lte.LTELinkInfoListener; +import dji.v5.manager.aircraft.lte.LTELinkType; +import dji.v5.manager.aircraft.lte.LTEManager; + + +public class MLTEManager extends BaseManager { + + + private MLTEManager() { + } + + private static class LTEHolder { + private static final MLTEManager INSTANCE = new MLTEManager(); + } + + public static MLTEManager getInstance() { + return LTEHolder.INSTANCE; + } + + public void initLTEManager() { + Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey. + KeyConnection)); + if (isConnect != null && isConnect) { + + LTEManager.getInstance().addLTELinkInfoListener(new LTELinkInfoListener() { + @Override + public void onLTELinkInfoUpdate(LTELinkInfo info) { + if (info != null && info.getLTELinkType() != null) { + Movement.getInstance().setLTELinkType(info.getLTELinkType().name()); + LogUtil.log(TAG, "当前图传类型:" + info.getLTELinkType().name()); + } + } + }); + +// LTEManager.getInstance().addLTEDongleInfoListener(new LTEDongleInfoListener() { +// @Override +// public void onLTEAircraftDongleInfoUpdate(@NonNull List aircraftDongleInfos) { +// if (!aircraftDongleInfos.isEmpty()) { +// LogUtil.log(TAG, "aircraft DongleInfo:" + new Gson().toJson(aircraftDongleInfos.get(0))); +// } +// +// } +// +// @Override +// public void onLTERemoteControllerDongleInfoUpdate(@NonNull List remoteControllerDongleInfos) { +// LogUtil.log(TAG, "remote DongleInfo:" + new Gson().toJson(remoteControllerDongleInfos.get(0))); +// +// } +// }); + + + // 监听认证信息(认证状态、剩余有效时间) + LTEManager.getInstance().addLTEAuthenticationInfoListener(new LTEAuthenticationInfoListener() { + @Override + public void onLTEAuthenticationInfoUpdate(LTEAuthenticationInfo info) { + if (info != null) { + LogUtil.log(TAG, "LTE认证信息 - 是否可用: " + info.isLTEAuthenticationAvailable() + + ", 是否认证: " + info.isLTEAuthenticated() + + ", 认证手机号: " + info.getLTEAuthenticatedPhoneNumber() + + ", 剩余有效时间: " + info.getLTEAuthenticatedRemainingTime() + "秒" + + ", 最后认证时间: " + info.getLTELastAuthenticatedTime()); + + sendEvent2Server("LTE认证信息 - 是否可用: " + info.isLTEAuthenticationAvailable() + + ", 是否认证: " + info.isLTEAuthenticated() + + ", 认证手机号: " + info.getLTEAuthenticatedPhoneNumber() + + ", 剩余有效时间: " + info.getLTEAuthenticatedRemainingTime() + "秒" + + ", 最后认证时间: " + info.getLTELastAuthenticatedTime(), 1); + + if (!info.isLTEAuthenticationAvailable() || !info.isLTEAuthenticated()) { + sendEvent2Server("⚠ LTE认证已过期或未认证,需要重新认证", 1); + } else if (info.getLTEAuthenticatedRemainingTime() > 0 && info.getLTEAuthenticatedRemainingTime() < 3 * 24 * 3600) { + sendEvent2Server("⚠ LTE认证剩余时间不足3天,请尽快重新认证", 1); + } + + + } + } + }); + + } + } + + private int setLTEEnhancedTransmissionTypeTimes; + private boolean isLTEEnhancedTransmissionLte; + + public void setLTEEnhancedTransmissionType() { + Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey. + KeyConnection)); + if (isConnect != null && isConnect) { + LTEManager.getInstance().setLTEEnhancedTransmissionType(LTELinkType.OCU_SYNC_LTE, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + isLTEEnhancedTransmissionLte = true; + LogUtil.log(TAG, "设置增强图传成功"); + } + + @Override + public void onFailure(@NonNull IDJIError idjiError) { + LogUtil.log(TAG, "设置增强图传第" + setLTEEnhancedTransmissionTypeTimes + "次开启失败:" + new Gson().toJson(idjiError)); + if (!isLTEEnhancedTransmissionLte) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (setLTEEnhancedTransmissionTypeTimes < 20) { + setLTEEnhancedTransmissionTypeTimes++; + setLTEEnhancedTransmissionType(); + } + } + }, 3000); + } + } + }); + } + + } + + + /** + * 请求LTE验证码,同时保存手机号和区号到Movement + */ + public void requestLTEVerificationCode(String phoneAreaCode, String phoneNumber) { + Movement.getInstance().setLtePhoneAreaCode(phoneAreaCode); + Movement.getInstance().setLtePhoneNumber(phoneNumber); + LTEManager.getInstance().getLTEAuthenticationVerificationCode(phoneAreaCode, phoneNumber, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + LogUtil.log(TAG, "LTE验证码发送成功,手机号: " + phoneNumber); + sendEvent2Server("LTE验证码发送成功,手机号: " + phoneNumber,1); + } + + @Override + public void onFailure(@NonNull IDJIError idjiError) { + LogUtil.log(TAG, "LTE验证码发送失败: " + new Gson().toJson(idjiError)); + sendEvent2Server("LTE验证码发送失败: " + new Gson().toJson(idjiError) + phoneNumber,2); + } + }); + } + + /** + * 提交LTE验证码进行认证 + */ + public void startLTEAuthentication(String verificationCode, CommonCallbacks.CompletionCallback callback) { + String phoneAreaCode = Movement.getInstance().getLtePhoneAreaCode(); + String phoneNumber = Movement.getInstance().getLtePhoneNumber(); + LTEManager.getInstance().startLTEAuthentication(phoneAreaCode, phoneNumber, verificationCode, callback); + } + + public void test() { + LTEManager.getInstance().getLTEAuthenticationVerificationCode("86", "18505198302", new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + LogUtil.log(TAG, "发送成功"); + } + + @Override + public void onFailure(@NonNull IDJIError idjiError) { + + } + }); + } + +} diff --git a/app/src/main/java/com/aros/apron/manager/MissionV3Manager.java b/app/src/main/java/com/aros/apron/manager/MissionV3Manager.java index 1cb6d8e8..7459775d 100644 --- a/app/src/main/java/com/aros/apron/manager/MissionV3Manager.java +++ b/app/src/main/java/com/aros/apron/manager/MissionV3Manager.java @@ -402,7 +402,11 @@ public class MissionV3Manager extends BaseManager { @Override public void onWaylineExecutingInfoUpdate(WaylineExecutingInfo excutingWaylineInfo) { if (excutingWaylineInfo != null) { + LogUtil.log(TAG,"航点"+excutingWaylineInfo.getCurrentWaypointIndex()); + + //状态等执行完发送再更新(测试暂停时不改变index为0) + if (excutingWaylineInfo.getCurrentWaypointIndex() != 0) { Movement.getInstance().setCurrentWaypointIndex(excutingWaylineInfo.getCurrentWaypointIndex()); Movement.getInstance().setTask_current_waypoint_index(excutingWaylineInfo.getCurrentWaypointIndex()); @@ -484,11 +488,15 @@ public class MissionV3Manager extends BaseManager { //3.检查飞机状态(不满足条件直接taskFail入库) boolean statusOk = verifyAircraftStatus(message); + //downLoadKMZFile(message); + if (statusOk) { sendEvent2Server("条件满足进入自建和下发航线", 1); verifyGpsAndMissionState(message); } + // verifyGpsAndMissionState(message); + } @@ -567,8 +575,8 @@ public class MissionV3Manager extends BaseManager { boolean isMissionStateValid = (missionStateCode == 2 || missionStateCode == 0 || missionStateCode == 7); boolean isPlaneMessageValid = !TextUtils.isEmpty(planeMessage) && !planeMessage.equals("无法起飞"); - boolean isGpsQualityValid = (quality == 4 || quality == 5 || quality == 10); - boolean GPSSatelliteCountValid = GPSSatelliteCount > 14; + boolean isGpsQualityValid = (quality == 4 || quality == 5 || quality == 10 ||quality == 3); + boolean GPSSatelliteCountValid = GPSSatelliteCount > 12; LogUtil.log(TAG, "isMissionStateValid" + isMissionStateValid + "isPlaneMessageValid" + isPlaneMessageValid + "isGpsQualityValid" + isGpsQualityValid); // if (isMissionStateValid && isPlaneMessageValid && isGpsQualityValid) { @@ -622,6 +630,7 @@ public class MissionV3Manager extends BaseManager { @Override public void onFailure(Call call, IOException e) { sendEvent2Server("任务下载失败:" + e.toString(), 2); + // LogUtil.log(TAG, "任务下载失败"); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); } @@ -646,6 +655,7 @@ public class MissionV3Manager extends BaseManager { } fos.flush(); sendEvent2Server("航线下载成功 ", 1); + //LogUtil.log(TAG, "航线下载成功"); mainHandler.post(new Runnable() { @Override public void run() { @@ -654,6 +664,7 @@ public class MissionV3Manager extends BaseManager { }); } catch (Exception e) { sendEvent2Server("任务下载失败,网络异常:" + e.toString(), 2); + //LogUtil.log(TAG, "任务下载失败,网络异常"); TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); } } @@ -883,7 +894,6 @@ public class MissionV3Manager extends BaseManager { if( PreferenceUtils.getInstance().getMissionType()==0){ Movement.getInstance().setTask_status("paused"); - sendFlightTaskProgress2Server(); } @@ -1022,7 +1032,11 @@ public class MissionV3Manager extends BaseManager { if (times < 5) { PreferenceUtils.getInstance().setRestartAMSTimes(times + 1); LogUtil.log(TAG, "图传仍未恢复,重启 AMS 第 " + (times + 1) + " 次"); - RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext()); + mainHandler.postDelayed(() -> + RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext()), 1000); + }else{ + sendEvent2Server("达到重启最大次数还没有获得图传", 2); + TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); } } else { diff --git a/app/src/main/java/com/aros/apron/manager/PayloadWidgetManager.java b/app/src/main/java/com/aros/apron/manager/PayloadWidgetManager.java index 9497dd0e..04fe4a5f 100644 --- a/app/src/main/java/com/aros/apron/manager/PayloadWidgetManager.java +++ b/app/src/main/java/com/aros/apron/manager/PayloadWidgetManager.java @@ -78,90 +78,78 @@ public class PayloadWidgetManager extends BaseManager { if (payloadManager != null) { IPayloadManager iPayloadManager = payloadManager.get(PayloadIndexType.PORT_2); if (iPayloadManager != null) { - PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).pullWidgetInfoFromPayload(new CommonCallbacks.CompletionCallback() { + //基础信息 + PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).addPayloadBasicInfoListener(new PayloadBasicInfoListener() { @Override - public void onSuccess() { - //基础信息 - PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).addPayloadBasicInfoListener(new PayloadBasicInfoListener() { - @Override - public void onPayloadBasicInfoUpdate(PayloadBasicInfo info) { - //LogUtil.log(TAG, "左侧负载基础信息:" + info.toString()); - // XcFileLog.getInstace().w(TAG, "左侧负载基础信息:" + info.toString()); - //cachedBasicInfo = info; - //startPsdkWidgetReport(); - } - }); - - PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).addPayloadDataListener(new PayloadDataListener() { - @Override - public void onDataFromPayloadUpdate(byte[] data) { - String cleanData = new String(data, java.nio.charset.StandardCharsets.UTF_8) - .replaceAll("[^\\x20-\\x7E\\u4e00-\\u9fa5]", ""); - // LogUtil.log(TAG, "左侧负载数据信息:" + cleanData); - // XcFileLog.getInstace().w(TAG, "左侧负载数据信息:" + cleanData); - - - if (cleanData.contains("jwD")) { - payloadBuffer.setLength(0); - payloadBuffer.append(cleanData); - // LogUtil.log(TAG, "负载数据开始,清空缓存"); - } - - - if (cleanData.contains("}")) { - if (payloadBuffer.length() > 0) { - payloadBuffer.append(cleanData); - String fullJson = payloadBuffer.toString(); - payloadBuffer.setLength(0); // 清空,准备下次 - // LogUtil.log(TAG, "负载完整数据: " + fullJson); - sendFloatingWindowText(fullJson); - } else { - //LogUtil.log(TAG, "负载数据: 缓存为空,忽略孤立}"); - } - } - - - } - }); - - //可以把负载设备控件打印 - PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).addPayloadWidgetInfoListener(new PayloadWidgetInfoListener() { - @Override - public void onPayloadWidgetInfoUpdate(PayloadWidgetInfo info) { - //LogUtil.log(TAG, "左侧负载控件信息:" + info.toString()); - //XcFileLog.getInstace().w(TAG, "左侧负载控件信息:" + info.toString()); - //cachedWidgetInfo = info; - //如果负载为空 - detectSpeaker(info, 2); - - if (info.getConfigInterfaceWidgetList() == null || info.getMainInterfaceWidgetList() == null) { - PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).pullWidgetInfoFromPayload(new CommonCallbacks.CompletionCallback() { - @Override - public void onSuccess() { - LogUtil.log(TAG, "负载重复拉取成功"); - - } - - @Override - public void onFailure(@NonNull IDJIError idjiError) { - LogUtil.log(TAG, "负载重复拉取失败"); - } - }); - } - } - }); + public void onPayloadBasicInfoUpdate(PayloadBasicInfo info) { + //LogUtil.log(TAG, "左侧负载基础信息:" + info.toString()); + // XcFileLog.getInstace().w(TAG, "左侧负载基础信息:" + info.toString()); + //cachedBasicInfo = info; + //startPsdkWidgetReport(); } - + }); + PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).addPayloadDataListener(new PayloadDataListener() { @Override - public void onFailure(@NonNull IDJIError idjiError) { - LogUtil.log(TAG, "负载第一次拉取失败"); + public void onDataFromPayloadUpdate(byte[] data) { + String cleanData = new String(data, java.nio.charset.StandardCharsets.UTF_8) + .replaceAll("[^\\x20-\\x7E\\u4e00-\\u9fa5]", ""); + // LogUtil.log(TAG, "左侧负载数据信息:" + cleanData); + // XcFileLog.getInstace().w(TAG, "左侧负载数据信息:" + cleanData); + + + if (cleanData.contains("jwD")) { + payloadBuffer.setLength(0); + payloadBuffer.append(cleanData); + // LogUtil.log(TAG, "负载数据开始,清空缓存"); + } + + + if (cleanData.contains("}")) { + if (payloadBuffer.length() > 0) { + payloadBuffer.append(cleanData); + String fullJson = payloadBuffer.toString(); + payloadBuffer.setLength(0); // 清空,准备下次 + // LogUtil.log(TAG, "负载完整数据: " + fullJson); + sendFloatingWindowText(fullJson); + } else { + //LogUtil.log(TAG, "负载数据: 缓存为空,忽略孤立}"); + } + } + + + } + }); + //可以把负载设备控件打印 + PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).addPayloadWidgetInfoListener(new PayloadWidgetInfoListener() { + @Override + public void onPayloadWidgetInfoUpdate(PayloadWidgetInfo info) { + //LogUtil.log(TAG, "左侧负载控件信息:" + info.toString()); + //XcFileLog.getInstace().w(TAG, "左侧负载控件信息:" + info.toString()); + //cachedWidgetInfo = info; + //如果负载为空 + + detectSpeaker(info, 2); + + if (info.getConfigInterfaceWidgetList() == null || info.getMainInterfaceWidgetList() == null) { + PayloadCenter.getInstance().getPayloadManager().get(PayloadIndexType.PORT_2).pullWidgetInfoFromPayload(new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + LogUtil.log(TAG, "负载重复拉取成功"); + + } + + @Override + public void onFailure(@NonNull IDJIError idjiError) { + LogUtil.log(TAG, "负载重复拉取失败"); + } + }); + } } }); } else { LogUtil.log(TAG, "监听LEFT_OR_MAIN PSDK数据失败:设备未连接"); } - IPayloadManager iPayloadManager3 = payloadManager.get(PayloadIndexType.PORT_3); if (iPayloadManager3 != null) { //基础信息 @@ -200,9 +188,6 @@ public class PayloadWidgetManager extends BaseManager { } else { LogUtil.log(TAG, "监听right_OR_MAIN PSDK数据失败:设备未连接"); } - - - } else { LogUtil.log(TAG, "监听psdk数据失败:未检测到设备"); } diff --git a/app/src/main/java/com/aros/apron/manager/RTKManager.java b/app/src/main/java/com/aros/apron/manager/RTKManager.java index 089f74b9..6d9fd0dc 100644 --- a/app/src/main/java/com/aros/apron/manager/RTKManager.java +++ b/app/src/main/java/com/aros/apron/manager/RTKManager.java @@ -120,10 +120,10 @@ public class RTKManager extends BaseManager { //开启自定义网络RTK服务 private void startNetworkRTKService() { if (PreferenceUtils.getInstance().getRtkType()==1) { - if (Movement.getInstance().getIs_fixed()==2) { - LogUtil.log(TAG, "RTK服务已开启"); - return; - } +// if (Movement.getInstance().getIs_fixed()==2) { +// LogUtil.log(TAG, "RTK服务已开启"); +// return; +// } RTKCustomNetworkSetting rtkCustomNetworkSetting = new RTKCustomNetworkSetting(); rtkCustomNetworkSetting.setServerAddress(PreferenceUtils.getInstance().getNTRIP()); rtkCustomNetworkSetting.setPort(Integer.valueOf(PreferenceUtils.getInstance().getNTRPort())); diff --git a/app/src/main/java/com/aros/apron/manager/SpeakerManager.java b/app/src/main/java/com/aros/apron/manager/SpeakerManager.java index 6532746a..1d4aba8d 100644 --- a/app/src/main/java/com/aros/apron/manager/SpeakerManager.java +++ b/app/src/main/java/com/aros/apron/manager/SpeakerManager.java @@ -229,10 +229,10 @@ public class SpeakerManager extends BaseManager { public void onUpdateMegaphoneInfo(MegaphoneInfo megaphoneInfo) { if (megaphoneInfo == null) return; //工作模式 音量 状态 播放模式 - Movement.getInstance().setPlay_mode(String.valueOf(megaphoneInfo.getPlayMode().value)); + Movement.getInstance().setPlay_mode(String.valueOf(megaphoneInfo.getPlayMode().ordinal())); Movement.getInstance().setPlay_volume(String.valueOf(megaphoneInfo.getVolume())); - Movement.getInstance().setWork_mode(String.valueOf(megaphoneInfo.getWorkMode().co_a)); - Movement.getInstance().setSystem_state(String.valueOf(megaphoneInfo.getStatus().co_a)); + Movement.getInstance().setWork_mode(String.valueOf(megaphoneInfo.getWorkMode().ordinal())); + Movement.getInstance().setSystem_state(String.valueOf(megaphoneInfo.getStatus().ordinal())); MegaphoneStatus status = megaphoneInfo.getStatus(); if (status == MegaphoneStatus.PLAYING) { @@ -362,7 +362,7 @@ public class SpeakerManager extends BaseManager { @Override public void onSuccess() { LogUtil.log(TAG, "喊话器内容上传成功"); - Synchronizedstatus.setSpeakrunning(false); + //Synchronizedstatus.setSpeakrunning(false); } @Override @@ -581,46 +581,52 @@ public class SpeakerManager extends BaseManager { MegaphoneManager.getInstance().startPushingFileToMegaphone(fileInfo, new CommonCallbacks.CompletionCallbackWithProgress() { + private boolean hasTriggeredPlay = false; @Override public void onProgressUpdate(Integer integer) { Movement.getInstance().setTTS_status("in_progress"); Movement.getInstance().setSpeakerpercent(integer); + Movement.getInstance().setStep_key("upload"); LogUtil.log(TAG, "喊话器内容上传进度:" + integer + "%"); + + if (integer >= 99 && !hasTriggeredPlay) { + hasTriggeredPlay = true; + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + LogUtil.log(TAG, "开始播放音频"); + MegaphoneManager.getInstance().startPlay(new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + sendMsg2Server(message); + Movement.getInstance().setTTS_status("success"); + Movement.getInstance().setStep_key("play"); + + SpeakerProgressReporter.getInstance().sendNowTTSProgress(psdkindex); + sendEvent2Server("喊话器播放TTS音频成功", 1); + LogUtil.log(TAG,"喊话器播放TTS音频成功"); + Synchronizedstatus.setSpeakTTSrunning(false); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + sendFailMsg2Server(message, "喊话器播放TTS音频失败:" + getIDJIErrorMsg(error)); + sendEvent2Server("喊话器播放TTS音频失败:" + getIDJIErrorMsg(error), 2); + LogUtil.log(TAG,"喊话器播放TTS音频失败qwq" + getIDJIErrorMsg(error)); + Synchronizedstatus.setSpeakTTSrunning(false); + } + }); + } + }, 1000); + } + } @Override public void onSuccess() { - LogUtil.log(TAG, "喊话器内容上传成功"); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - LogUtil.log(TAG, "开始播放音频"); - MegaphoneManager.getInstance().startPlay(new CommonCallbacks.CompletionCallback() { - @Override - public void onSuccess() { - sendMsg2Server(message); - Movement.getInstance().setTTS_status("success"); - Movement.getInstance().setStep_key("play"); - - SpeakerProgressReporter.getInstance().sendNowTTSProgress(psdkindex); - sendEvent2Server("喊话器播放TTS音频成功", 1); - LogUtil.log(TAG,"喊话器播放TTS音频成功"); - Synchronizedstatus.setSpeakTTSrunning(false); - } - - @Override - public void onFailure(@NonNull IDJIError error) { - sendFailMsg2Server(message, "喊话器播放TTS音频失败:" + getIDJIErrorMsg(error)); - sendEvent2Server("喊话器播放TTS音频失败:" + getIDJIErrorMsg(error), 2); - LogUtil.log(TAG,"喊话器播放TTS音频失败qwq" + getIDJIErrorMsg(error)); - Synchronizedstatus.setSpeakTTSrunning(false); - } - }); - } - }, 1000); } @Override @@ -636,9 +642,7 @@ public class SpeakerManager extends BaseManager { Synchronizedstatus.setSpeakTTSrunning(false); } - LogUtil.log(TAG, "设置 speakTTSrunning 为 false"); LogUtil.log(TAG, "speakerTTSPlayStart 方法执行完成"); - Synchronizedstatus.setSpeakTTSrunning(false); } public void setindex(){ diff --git a/app/src/main/java/com/aros/apron/manager/StreamManager.java b/app/src/main/java/com/aros/apron/manager/StreamManager.java index df803a81..2c15d180 100644 --- a/app/src/main/java/com/aros/apron/manager/StreamManager.java +++ b/app/src/main/java/com/aros/apron/manager/StreamManager.java @@ -52,7 +52,7 @@ public class StreamManager extends BaseManager { private final Handler streamRefreshHandler = new Handler(Looper.getMainLooper()); private Runnable streamRefreshRunnable = null; private volatile boolean isStreamRefreshing = false; - private static final long STREAM_REFRESH_INTERVAL_MS = 8000; + private static final long STREAM_REFRESH_INTERVAL_MS = 10000; private StreamManager() { } diff --git a/app/src/main/java/com/aros/apron/manager/TakeOffToPointManager.java b/app/src/main/java/com/aros/apron/manager/TakeOffToPointManager.java index 6958053f..5818d1b2 100644 --- a/app/src/main/java/com/aros/apron/manager/TakeOffToPointManager.java +++ b/app/src/main/java/com/aros/apron/manager/TakeOffToPointManager.java @@ -182,8 +182,8 @@ public class TakeOffToPointManager extends BaseManager { boolean isMissionStateValid = (missionStateCode == 2 || missionStateCode == 0 || missionStateCode == 7); boolean isPlaneMessageValid = !TextUtils.isEmpty(planeMessage) && !planeMessage.equals("无法起飞"); - boolean isGpsQualityValid = (quality == 4 || quality == 5 || quality == 10); - boolean GPSSatelliteCountValid = GPSSatelliteCount > 15; + boolean isGpsQualityValid = (quality == 4 || quality == 5 || quality == 10 ||quality == 3); + boolean GPSSatelliteCountValid = GPSSatelliteCount > 12; LogUtil.log(TAG, "isMissionStateValid" + isMissionStateValid + "isPlaneMessageValid" + isPlaneMessageValid + "isGpsQualityValid" + isGpsQualityValid); // if (isMissionStateValid && isPlaneMessageValid && isGpsQualityValid) { @@ -467,7 +467,11 @@ public class TakeOffToPointManager extends BaseManager { if (times < 5) { PreferenceUtils.getInstance().setRestartAMSTimes(times + 1); LogUtil.log(TAG, "图传仍未恢复,重启 AMS 第 " + (times + 1) + " 次"); - RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext()); + mainHandler.postDelayed(() -> + RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext()), 1000); + }else{ + sendEvent2Server("达到重启最大次数还没有获得图传", 2); + TaskFailManager.getInstance().sendTaskFailMsg2Server(-1); } } else { // 图传恢复 → 执行后续逻辑 diff --git a/app/src/main/java/com/aros/apron/mix/Aprondown.java b/app/src/main/java/com/aros/apron/mix/Aprondown.java index 2f99ec3d..3c671df7 100644 --- a/app/src/main/java/com/aros/apron/mix/Aprondown.java +++ b/app/src/main/java/com/aros/apron/mix/Aprondown.java @@ -258,12 +258,11 @@ public class Aprondown { if (ids.empty()) { LogUtil.log(TAG_LOG, "预处理失败,回退原图检测"); - corners.clear(); // 清空之前的结果 + corners.clear(); detector.detectMarkers(grayImgMat, corners, ids); LogUtil.log(TAG_LOG, "原图检测: " + (ids.empty() ? "仍未检出" : "成功,数量=" + corners.size())); } - processedMat.release(); @@ -567,7 +566,8 @@ public class Aprondown { startFastStick = false; isStartAruco = false; consecutiveTriggerCount = 0; - frameCounter = 0; // 【新增】重置帧计数 + frameCounter = 0; // 重置帧计数 + Apronmixvalue.getInstance().setIsaglinetrue(false); // 下次降落重新对准 } diff --git a/app/src/main/java/com/aros/apron/mix/Aprongim.java b/app/src/main/java/com/aros/apron/mix/Aprongim.java index 4fefcd04..ed98f9ea 100644 --- a/app/src/main/java/com/aros/apron/mix/Aprongim.java +++ b/app/src/main/java/com/aros/apron/mix/Aprongim.java @@ -91,6 +91,11 @@ public class Aprongim { // 记录上一帧满足的降落条件类型:0=无, 1=单码精准降落(15/17号), 2=几何中心降落 private int lastLandingCondition = 0; + // ========== 【新增】6个独立分支计数器 ========== + private int[] landingCounters = new int[22]; // ID作为索引 + private int counterRound = 0; + + // ========== 【新增】高度稳定性监测 ========== private long lastHeightCheckTime = 0; private double lastUltrasonicHeight = 0; @@ -249,19 +254,22 @@ public class Aprongim { if(isDoublePayload){ if (ultHeight <=5) { - LENS_OFFSET_X=-130; + LENS_OFFSET_X=-80; LENS_OFFSET_Y=120; }else if(ultHeight<10){ - LENS_OFFSET_X=-90; + LENS_OFFSET_X=-70; LENS_OFFSET_Y=80; } else if (ultHeight<20) { - LENS_OFFSET_X=-70; + LENS_OFFSET_X=-60; LENS_OFFSET_Y=60; + }else if(ultHeight<30){ + LENS_OFFSET_X=-40; + LENS_OFFSET_Y=20; } }else{ if (ultHeight <=5) { - LENS_OFFSET_X=120; + LENS_OFFSET_X=100; LENS_OFFSET_Y = 100; }else if(ultHeight<10){ LENS_OFFSET_X=80; @@ -271,7 +279,6 @@ public class Aprongim { LENS_OFFSET_Y = 60; } } - lastFuture = executor.schedule(new Runnable() { @Override public void run() { @@ -532,86 +539,203 @@ public class Aprongim { double absY = Math.abs(offsetY); double z = ultHeight / 10.0; - // 降落条件判断(连续帧) + // ========== 【6个独立分支计数器降落判定】 ========== boolean isSpecialLanding = false; double singleErrX = 0, singleErrY = 0; - // 单挂模式:检查15号 - if (!isDoublePayload && target15 != null && ultHeight <= 4) { - Mat corner = target15.getConner(); - double cx = 0, cy = 0; - for (int i = 0; i < 4; i++) { - double[] p = corner.get(0, i); - cx += p[0]; - cy += p[1]; + if (ultHeight <= 4) { + // 当前帧可见码的Map + java.util.HashMap markerMap = new java.util.HashMap<>(); + for (ArucoMarker m : markers) { + markerMap.put(m.getId(), m); } - cx /= 4.0; cy /= 4.0; - singleErrX = cx - imgWidth / 2.0 - LENS_OFFSET_X; - singleErrY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; - if (Math.abs(singleErrX) < 60 && Math.abs(singleErrY) < 60) { - isSpecialLanding = true; - offsetX = singleErrX; - offsetY = singleErrY; - absX = Math.abs(singleErrX); - absY = Math.abs(singleErrY); + boolean foundLanding = false; + int landingId = 0; + + // ===== 单挂模式:13 15 17 14 16 18 ===== + if (!isDoublePayload) { + // ---- 13号 ---- + ArucoMarker marker13 = markerMap.get(13); + if (marker13 != null) { + Mat corner = marker13.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 + 200.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[13]++; } else { landingCounters[13] = 0; } + if (landingCounters[13] >= 2 && !foundLanding) { foundLanding = true; landingId = 13; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[13] = 0; } + + // ---- 15号 ---- + ArucoMarker marker15 = markerMap.get(15); + if (marker15 != null) { + Mat corner = marker15.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - LENS_OFFSET_X; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[15]++; } else { landingCounters[15] = 0; } + if (landingCounters[15] >= 2 && !foundLanding) { foundLanding = true; landingId = 15; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[15] = 0; } + + // ---- 17号 ---- + ArucoMarker marker17 = markerMap.get(17); + if (marker17 != null) { + Mat corner = marker17.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - 200.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[17]++; } else { landingCounters[17] = 0; } + if (landingCounters[17] >= 2 && !foundLanding) { foundLanding = true; landingId = 17; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[17] = 0; } + + // ---- 14号 ---- + ArucoMarker marker14 = markerMap.get(14); + if (marker14 != null) { + Mat corner = marker14.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 + 200.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[14]++; } else { landingCounters[14] = 0; } + if (landingCounters[14] >= 2 && !foundLanding) { foundLanding = true; landingId = 14; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[14] = 0; } + + // ---- 16号 ---- + ArucoMarker marker16 = markerMap.get(16); + if (marker16 != null) { + Mat corner = marker16.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - LENS_OFFSET_X; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[16]++; } else { landingCounters[16] = 0; } + if (landingCounters[16] >= 2 && !foundLanding) { foundLanding = true; landingId = 16; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[16] = 0; } + + // ---- 18号 ---- + ArucoMarker marker18 = markerMap.get(18); + if (marker18 != null) { + Mat corner = marker18.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - 200.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[18]++; } else { landingCounters[18] = 0; } + if (landingCounters[18] >= 2 && !foundLanding) { foundLanding = true; landingId = 18; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[18] = 0; } } - } + // ===== 双挂模式:15 17 19 16 18 20 ===== + else { + // ---- 15号 ---- + ArucoMarker marker15d = markerMap.get(15); + if (marker15d != null) { + Mat corner = marker15d.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 +240.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[15]++; } else { landingCounters[15] = 0; } + if (landingCounters[15] >= 2 && !foundLanding) { foundLanding = true; landingId = 15; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[15] = 0; } - // 双挂模式:检查17号 - if (isDoublePayload && target17 != null && ultHeight <= 4) { - Mat corner = target17.getConner(); - double cx = 0, cy = 0; - for (int i = 0; i < 4; i++) { - double[] p = corner.get(0, i); - cx += p[0]; - cy += p[1]; + // ---- 17号 ---- + ArucoMarker marker17d = markerMap.get(17); + if (marker17d != null) { + Mat corner = marker17d.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - LENS_OFFSET_X; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[17]++; } else { landingCounters[17] = 0; } + if (landingCounters[17] >= 2 && !foundLanding) { foundLanding = true; landingId = 17; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[17] = 0; } + + // ---- 19号 ---- + ArucoMarker marker19d = markerMap.get(19); + if (marker19d != null) { + Mat corner = marker19d.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - 200.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[19]++; } else { landingCounters[19] = 0; } + if (landingCounters[19] >= 2 && !foundLanding) { foundLanding = true; landingId = 19; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[19] = 0; } + + // ---- 16号 ---- + ArucoMarker marker16d = markerMap.get(16); + if (marker16d != null) { + Mat corner = marker16d.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 +240.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[16]++; } else { landingCounters[16] = 0; } + if (landingCounters[16] >= 2 && !foundLanding) { foundLanding = true; landingId = 16; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[16] = 0; } + + // ---- 18号 ---- + ArucoMarker marker18d = markerMap.get(18); + if (marker18d != null) { + Mat corner = marker18d.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - LENS_OFFSET_X; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[18]++; } else { landingCounters[18] = 0; } + if (landingCounters[18] >= 2 && !foundLanding) { foundLanding = true; landingId = 18; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[18] = 0; } + + // ---- 20号 ---- + ArucoMarker marker20d = markerMap.get(20); + if (marker20d != null) { + Mat corner = marker20d.getConner(); + double cx = 0, cy = 0; + for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } + cx /= 4.0; cy /= 4.0; + double errX = cx - imgWidth / 2.0 - 200.0; + double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; + if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[20]++; } else { landingCounters[20] = 0; } + if (landingCounters[20] >= 2 && !foundLanding) { foundLanding = true; landingId = 20; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } + } else { landingCounters[20] = 0; } } - cx /= 4.0; cy /= 4.0; - singleErrX = cx - imgWidth / 2.0 - LENS_OFFSET_X; - singleErrY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; - if (Math.abs(singleErrX) < 60 && Math.abs(singleErrY) < 60) { - isSpecialLanding = true; - offsetX = singleErrX; - offsetY = singleErrY; - absX = Math.abs(singleErrX); - absY = Math.abs(singleErrY); - } - } + LogUtil.log(TAG_LOG, "【计数器】13=" + landingCounters[13] + " 14=" + landingCounters[14] + " 15=" + landingCounters[15] + " 16=" + landingCounters[16] + " 17=" + landingCounters[17] + " 18=" + landingCounters[18]+ " 19=" + landingCounters[19]+ " 20=" + landingCounters[20]); - // 连续帧判断 - int currentCondition = 0; - if (isSpecialLanding) { - currentCondition = 1; - } else if (ultHeight <= 4 && absX < 60 && absY < 60 && validCount >= 8) { - currentCondition = 2; - } - - if (currentCondition == 0 || currentCondition != lastLandingCondition) { - if (consecutiveTriggerCount > 0) { - consecutiveTriggerCount = 0; - LogUtil.log(TAG_LOG, "【计数器清零】条件变化 last=" + lastLandingCondition + " curr=" + currentCondition); - } - lastLandingCondition = currentCondition; - } - - if (currentCondition > 0) { - consecutiveTriggerCount++; - if (consecutiveTriggerCount >= TRIGGER_FRAME_THRESHOLD) { + // 触发降落 + if (foundLanding) { + LogUtil.log(TAG_LOG, "【降落触发】ID=" + landingId + " 连续2帧满足条件"); + DroneHelper.getInstance().moveVxVyYawrateHeight(0f, 0f, 0f, 0f); startFastStick = true; - consecutiveTriggerCount = 0; - lastLandingCondition = 0; - - LogUtil.log(TAG_LOG, currentCondition == 1 ? - "【降落触发】单双挂精准条件满足" : - "【降落触发】几何中心对准,码数量=" + validCount); - + for (int i = 0; i < landingCounters.length; i++) { landingCounters[i] = 0; } handler.postDelayed(() -> handler.post(runnable), 300); return; } + + // 第二帧结束,没有触发 → 重置 + counterRound++; + if (counterRound >= 2) { + counterRound = 0; + for (int i = 0; i < landingCounters.length; i++) { landingCounters[i] = 0; } + LogUtil.log(TAG_LOG, "【计数器重置】2帧未触发,重新从0开始"); + } } + double outX = 0, outY = 0, outZ = 0; // 分段PID控制(原有逻辑保持不变) @@ -943,12 +1067,16 @@ public class Aprongim { public void setDetectedBigMarkers() { startFastStick = false; isStartAruco = false; - consecutiveTriggerCount = 0; frameCounter = 0; // 【关键】重置旋转标志,下次降落重新用6号旋转 isYawAligned = false; + Apronmixvalue.getInstance().setIsaglinetrue(false); currentLandingMode = 0; - lastLandingCondition = 0; + // 重置分支计数器 + counterRound = 0; + for (int i = 0; i < landingCounters.length; i++) { + landingCounters[i] = 0; + } } private int handlerCallbackCount = 0; diff --git a/app/src/main/java/com/aros/apron/tools/ApronArucoDetectPort.java b/app/src/main/java/com/aros/apron/tools/ApronArucoDetectPort.java index 3baf5f0d..0e4355f9 100644 --- a/app/src/main/java/com/aros/apron/tools/ApronArucoDetectPort.java +++ b/app/src/main/java/com/aros/apron/tools/ApronArucoDetectPort.java @@ -177,14 +177,17 @@ public class ApronArucoDetectPort { if(isDoublePayload){ if (ultHeight <=5) { - LENS_OFFSET_X=-180; + LENS_OFFSET_X=-80; LENS_OFFSET_Y=120; }else if(ultHeight<10){ - LENS_OFFSET_X=-120; + LENS_OFFSET_X=-70; LENS_OFFSET_Y=80; } else if (ultHeight<20) { - LENS_OFFSET_X=-80; + LENS_OFFSET_X=-60; LENS_OFFSET_Y=60; + }else if(ultHeight<30){ + LENS_OFFSET_X=-40; + LENS_OFFSET_Y=20; } }else{ if (ultHeight <=5) @@ -561,7 +564,7 @@ public class ApronArucoDetectPort { double cx = 0, cy = 0; for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } cx /= 4.0; cy /= 4.0; - double errX = cx - imgWidth / 2.0 +220.0; + double errX = cx - imgWidth / 2.0 +240.0; double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; if (Math.abs(errX) < 55 && Math.abs(errY) < 70) { landingCounters[15]++; } else { landingCounters[15] = 0; } if (landingCounters[15] >= 2 && !foundLanding) { foundLanding = true; landingId = 15; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } @@ -600,7 +603,7 @@ public class ApronArucoDetectPort { double cx = 0, cy = 0; for (int i = 0; i < 4; i++) { double[] p = corner.get(0, i); cx += p[0]; cy += p[1]; } cx /= 4.0; cy /= 4.0; - double errX = cx - imgWidth / 2.0 +220.0; + double errX = cx - imgWidth / 2.0 +240.0; double errY = cy - imgHeight / 2.0 + LENS_OFFSET_Y; if (Math.abs(errX) < 70 && Math.abs(errY) < 70) { landingCounters[16]++; } else { landingCounters[16] = 0; } if (landingCounters[16] >= 2 && !foundLanding) { foundLanding = true; landingId = 16; isSpecialLanding = true; singleErrX = errX; singleErrY = errY; offsetX = singleErrX; offsetY = singleErrY; absX = Math.abs(singleErrX); absY = Math.abs(singleErrY); } @@ -659,8 +662,8 @@ public class ApronArucoDetectPort { // 分段PID控制(原有逻辑保持不变) if(z <= 0.4){ - pidControlX.setInputFilterAll((float)offsetX/1800); - pidControlY.setInputFilterAll(-(float)offsetY/1800); + pidControlX.setInputFilterAll((float)offsetX/1750); + pidControlY.setInputFilterAll(-(float)offsetY/1750); if (pidControlX.get_pid()<0){ if (pidControlX.get_pid()<-0.125){ outX=absX<120?0:-0.125; diff --git a/app/src/main/java/com/aros/apron/tools/BasePreference.java b/app/src/main/java/com/aros/apron/tools/BasePreference.java index 0df01ca6..737a4a2a 100644 --- a/app/src/main/java/com/aros/apron/tools/BasePreference.java +++ b/app/src/main/java/com/aros/apron/tools/BasePreference.java @@ -6,50 +6,57 @@ import android.content.SharedPreferences; import java.util.Calendar; /** - * SharePreference基类 - * 这里只写了对最常用的三种基本数据类型的操作。 - */ + * SharePreference基类 + * 这里只写了对最常用的三种基本数据类型的操作。 + */ public class BasePreference { private Context context; private SharedPreferences sp; private SharedPreferences.Editor editor; private String FILE_NAME = "userInfo"; - + protected BasePreference(Context context) { - this.context = context; + this.context = context; sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); } protected void userLoginOut(){ sp.edit().clear().commit(); } - + protected void setString(String key, String value) { sp.edit().putString(key, value).apply(); - } - + } + protected String getString(String key) { - return sp.getString(key, null); - } - + return sp.getString(key, null); + } + protected void setBoolean(String key, boolean value) { - sp.edit().putBoolean(key, value).commit(); - } - + sp.edit().putBoolean(key, value).commit(); + } + protected boolean getBoolean(String key) { return sp.getBoolean(key, false); - } - + } + protected void setInt(String key, int value) { - sp.edit().putInt(key, value).apply(); - } - + sp.edit().putInt(key, value).apply(); + } + protected int getInt(String key) { - return sp.getInt(key, 0); + return sp.getInt(key, 0); + } + + /** + * 同步写入(commit),适用于重启前需要确保数据落盘的场景 + */ + protected void setIntCommit(String key, int value) { + sp.edit().putInt(key, value).commit(); } protected int getYearInt(String key){ return sp.getInt(key, Calendar.getInstance().get(Calendar.YEAR)); } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/aros/apron/tools/PreferenceUtils.java b/app/src/main/java/com/aros/apron/tools/PreferenceUtils.java index 01b892ed..72871680 100644 --- a/app/src/main/java/com/aros/apron/tools/PreferenceUtils.java +++ b/app/src/main/java/com/aros/apron/tools/PreferenceUtils.java @@ -451,7 +451,7 @@ public class PreferenceUtils extends BasePreference { } public void setRestartAMSTimes(int restartAMSTimes) { - setInt(RESTART_AMS_TIMES, restartAMSTimes); + setIntCommit(RESTART_AMS_TIMES, restartAMSTimes); } public String getAttitudeHead() { diff --git a/app/src/main/java/com/aros/apron/tools/XTtsPcmGenerator.java b/app/src/main/java/com/aros/apron/tools/XTtsPcmGenerator.java index 630a4aa0..1181da16 100644 --- a/app/src/main/java/com/aros/apron/tools/XTtsPcmGenerator.java +++ b/app/src/main/java/com/aros/apron/tools/XTtsPcmGenerator.java @@ -126,6 +126,14 @@ public class XTtsPcmGenerator { } } + // 额外等待 500ms,确保回调线程的最后一批 PCM 数据写入完成 + LogUtil.log(TAG, "等待回调线程完成数据写入"); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // 关闭资源 close(); diff --git a/app/src/main/java/com/aros/apron/xclog/CrashHandler.java b/app/src/main/java/com/aros/apron/xclog/CrashHandler.java index 3dbf981d..474733ec 100644 --- a/app/src/main/java/com/aros/apron/xclog/CrashHandler.java +++ b/app/src/main/java/com/aros/apron/xclog/CrashHandler.java @@ -4,6 +4,8 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; +import com.aros.apron.tools.LogUtil; + /** * Date: 2016-12-06 * Time: 17:17 @@ -40,6 +42,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler { printWriter.close(); String stringBuilder = "------Crash------\n" + writer.toString(); + LogUtil.log(TAG, stringBuilder); XcFileLog.getInstace().e(TAG, stringBuilder); //如果处理了,让主程序继续运行3秒再退出,保证异步的写操作能及时完成 // try {