航线执行最终版

This commit is contained in:
cuijingzhou 2025-09-10 18:44:08 +08:00
parent 8e3c1ae8f1
commit ba292d7efd
11 changed files with 545 additions and 91 deletions

Binary file not shown.

View File

@ -75,6 +75,7 @@ import com.example.longyi_groundstation.Main.View.ErrorLogDialog;
import com.example.longyi_groundstation.Main.View.FPV_Void;
import com.example.longyi_groundstation.Main.View.LandDialog;
import com.example.longyi_groundstation.Main.View.SlideToUnlockView;
import com.example.longyi_groundstation.Main.View.StartExecuteDialog;
import com.example.longyi_groundstation.Main.View.TakeOffDialog;
import com.example.longyi_groundstation.Main.View.TurnBackDialog;
import com.example.longyi_groundstation.Main.Void.AllView;
@ -137,6 +138,7 @@ public class MainActivity extends AppCompatActivity {
private TurnBackDialog turnBackDialog;//返航弹窗
private LandDialog landDialog;//降落弹窗
private BombingDialog bombingDialog;//投弹弹窗
public static StartExecuteDialog startExecuteDialog;//开始执行弹窗
private ArrayList<LogItem> LogItemList = new ArrayList<>();
private LogAdapter adapter;
@ -160,6 +162,7 @@ public class MainActivity extends AppCompatActivity {
private CreateLinkAdapter createLinkAdapter;
private List<CreateLink> createLinkList = new ArrayList<>();
private ArrayList<CreateLink> selectedLinkList = null;//当前选择的航线
public boolean isUnlock = false;//是否解锁
@Override
@ -356,6 +359,8 @@ public class MainActivity extends AppCompatActivity {
landDialog = new LandDialog(MainActivity.this);
//投弹弹窗
bombingDialog = new BombingDialog(MainActivity.this);
//开始执行弹窗
startExecuteDialog = new StartExecuteDialog(this, "10");
allView.rv_error_list.setLayoutManager(new LinearLayoutManager(this));
adapter = new LogAdapter();
@ -472,7 +477,6 @@ public class MainActivity extends AppCompatActivity {
// allView.tv_height.setText(Math.round((MyReceiver.GLOBAL_POSITION_INT_json.optDouble("relative_alt") / 100) / 10.0) + "m");
allView.tv_height.setText(flyVoid.parseSerialData[0] + "m");
}
}
//如果有相同的点位就不添加到列表里面去
@ -528,19 +532,26 @@ public class MainActivity extends AppCompatActivity {
//广播接收-setHeartbeatlistener
myReceiver_HEARTBEAT.setHeartbeatlistener(data -> {
Log.d(TAG, "myReceiver_HEARTBEAT: " + data.toString());
//判断飞控是否解锁
if (Tool.getDecToFirstBin(MyReceiver.HEARTBEAT_json.optString("base_mode")).equals("1")){
//已解锁
allView.rl_unlock.setVisibility(View.GONE);
}else {
if (allView.rl_unlock.getVisibility() == View.GONE){
//未解锁
allView.rl_unlock.setVisibility(View.VISIBLE);
allView.unlockView.resetToInitialState("滑动解锁");
isUnlock = Tool.getDecToFirstBin(MyReceiver.HEARTBEAT_json.optString("base_mode")).equals("1");
if (allView.ll_link_start.getVisibility() == VISIBLE){
Log.d(TAG, "myReceiver_HEARTBEAT: " + data.toString());
//判断飞控是否解锁
if (Tool.getDecToFirstBin(MyReceiver.HEARTBEAT_json.optString("base_mode")).equals("1")){
//已解锁
allView.rl_unlock.setVisibility(View.GONE);
allView.ll_link_start_fun2.setVisibility(VISIBLE);
}else {
if (allView.rl_unlock.getVisibility() == View.GONE){
//未解锁
allView.rl_unlock.setVisibility(View.VISIBLE);
allView.unlockView.resetToInitialState("滑动解锁");
allView.ll_link_start_fun2.setVisibility(GONE);
}
}
}
// 这里可以更新 UI 或刷新数据
switch (MyReceiver.HEARTBEAT_json.optInt("custom_mode")) {
case 0:
@ -604,13 +615,14 @@ public class MainActivity extends AppCompatActivity {
data.optDouble("throttle")/100,
1
)*100) + "%", true));
}else {
typeList.set(2, new Msg("throttle","0%", true));
}
});
//广播接收-setMissionAcklistener
myReceiver_MISSION_REQUEST.setMissionRequestlistener(data -> {
Log.d(TAG, "myReceiver_MISSION_REQUEST: "+data.toString());
// Log.d(TAG, "myReceiver_MISSION_REQUEST: "+data.toString());
});
//广播接收-setMissionAcklistener
@ -728,7 +740,9 @@ public class MainActivity extends AppCompatActivity {
// 添加航线发送功能
if (selectedLinkList != null) {
// 调用FlyVoid中的方法发送航线到飞控
flyVoid.sendMissionToFlightController(this,selectedLinkList);
flyVoid.sendMissionToFlightController(this,
selectedLinkList,
allView.et_start_execute_height.getText().toString());
}
// // 清除当前地图上的所有航点和航线
@ -742,20 +756,20 @@ public class MainActivity extends AppCompatActivity {
});
//开始执行
allView.ll_link_start_fun2.setOnClickListener(v -> {
// 添加航线发送功能
// 开始执行
if (selectedLinkList != null) {
// 调用FlyVoid中的方法发送航线到飞控
flyVoid.requestMissionStart(0,-1);
Toast.makeText(this, "开始执行", Toast.LENGTH_SHORT).show();
//flyVoid.requestMissionStart(0,0);
if (isUnlock){
startExecuteDialog.show();
}else {
Toast.makeText(this, "请先解锁", Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(this, "请先选择航线", Toast.LENGTH_SHORT).show();
}
// 清除当前地图上的所有航点和航线
clearWaypoints();
allView.v_mainDisplay.setVisibility(VISIBLE);
allView.ll_open_layout.setVisibility(VISIBLE);
allView.ll_text.setVisibility(VISIBLE);
allView.ll_link_start.setVisibility(GONE);
allView.ll_all_link_layout.setVisibility(GONE);
allView.fpvWidget.setVisibility(VISIBLE);
});
//路线执行-退出
@ -768,6 +782,7 @@ public class MainActivity extends AppCompatActivity {
allView.ll_link_start.setVisibility(GONE);
allView.ll_all_link_layout.setVisibility(GONE);
allView.fpvWidget.setVisibility(VISIBLE);
allView.rl_unlock.setVisibility(View.GONE);
});
allView.ll_left_open.setOnClickListener(v -> {
@ -1563,13 +1578,11 @@ public class MainActivity extends AppCompatActivity {
selectedLinkList = null;
// 从数据库中获取选中的航线数据
selectedLinkList = sqlClass.getCreateLinkList(listId);
if (selectedLinkList != null && !selectedLinkList.isEmpty()) {
// 在地图上显示航线
displayRouteOnMap(selectedLinkList);
if (selectedLinkList != null) {
Toast.makeText(MainActivity.this, "已加载航线: " + linkListInfoList.get(position).getListName(),
Toast.LENGTH_SHORT).show();
// 在地图上显示航线
displayRouteOnMap(selectedLinkList);
} else {
Toast.makeText(MainActivity.this, "加载航线失败", Toast.LENGTH_SHORT).show();
}

View File

@ -63,14 +63,14 @@ public class TypeAdapter extends RecyclerView.Adapter<TypeAdapter.TypeViewHolder
holder.textView.setText("纬度:" + item.getMsg());
// 设置纬度显示的最大宽度确保能完整显示坐标值
holder.textView.setMaxWidth(Integer.MAX_VALUE);
holder.textView.setMinimumWidth(400); // 设置最小宽度确保足够显示
holder.textView.setMinimumWidth(90); // 设置最小宽度确保足够显示
break;
case "lon":
holder.textView.setText("经度:" + item.getMsg());
// 设置经度显示的最大宽度确保能完整显示坐标值
holder.textView.setMaxWidth(Integer.MAX_VALUE);
holder.textView.setMinimumWidth(400); // 设置最小宽度确保足够显示
holder.textView.setMinimumWidth(90); // 设置最小宽度确保足够显示
break;
case "throttle":

View File

@ -348,6 +348,10 @@ public class MyBoundService extends Service {
//主要是应对STATUSTEXT(253)这样的特殊数据
wordT1(msg);
msgOld = msg;
if (msg.msgid == MAVLINK_MSG_ID_MISSION_ACK){
Log.d("msg.msgid", MsgList.get(msg.msgid));
}
}
}
@ -392,9 +396,7 @@ public class MyBoundService extends Service {
if (MsgList.get(MAVLINK_MSG_ID_VFR_HUD) != null) {
BroadcastUtil.Broadcast_VFR_HUD(getApplication(), MsgList.get(MAVLINK_MSG_ID_VFR_HUD));
}
if (MsgList.get(MAVLINK_MSG_ID_MISSION_ACK) != null) {
BroadcastUtil.Broadcast_MISSION_ACK(getApplication(), MsgList.get(MAVLINK_MSG_ID_MISSION_ACK));
}
Thread.sleep(50);
@ -443,11 +445,16 @@ public class MyBoundService extends Service {
}
case MAVLINK_MSG_ID_MISSION_COUNT:
Log.d(TAG, "wordT1: ");
// Log.d(TAG, "wordT1: ");
if (MsgList.get(MAVLINK_MSG_ID_MISSION_REQUEST) != null) {
BroadcastUtil.Broadcast_MISSION_REQUEST(getApplication(), MsgList.get(MAVLINK_MSG_ID_MISSION_REQUEST));
}
case MAVLINK_MSG_ID_MISSION_ACK:
if (MsgList.get(MAVLINK_MSG_ID_MISSION_ACK) != null) {
BroadcastUtil.Broadcast_MISSION_ACK(getApplication(), MsgList.get(MAVLINK_MSG_ID_MISSION_ACK));
}
default:
// Log.d("cuijigzhou_msg_all_id", "不做处理:"+msg.msgid);

View File

@ -61,7 +61,7 @@ public class SlideToUnlockView extends View {
// 初始化默认圆角弧度
cornerRadius = dpToPx(20); // 默认背景圆角
thumbCornerRadius = dpToPx(10); // 默认滑块圆角
thumbCornerRadius = dpToPx(20); // 默认滑块圆角
}

View File

@ -0,0 +1,141 @@
package com.example.longyi_groundstation.Main.View;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.example.longyi_groundstation.Main.Void.FlyVoid;
import com.example.longyi_groundstation.Main.Void.MyTool;
import com.example.longyi_groundstation.R;
public class StartExecuteDialog {
private final Activity context;
private String title;
private String message;
private String positiveButtonText;
private String height = "10";
private FlyVoid flyVoid = new FlyVoid();
public StartExecuteDialog(Activity context, String height) {
this.context = context;
this.title = "错误日志";
this.message = "";
this.height = height;
this.positiveButtonText = "确定";
}
// 设置弹窗标题
public StartExecuteDialog setTitle(String title) {
this.title = title;
return this;
}
// 设置弹窗内容
public StartExecuteDialog setMessage(String message) {
this.message = message;
return this;
}
// 设置确认按钮文字
public StartExecuteDialog setPositiveButtonText(String text) {
this.positiveButtonText = text;
return this;
}
// 显示弹窗
public void show() {
MyTool.hideBottomNavigationBar( context);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
// 使用自定义布局
View view = LayoutInflater.from(context).inflate(R.layout.dialog_start_execute, null);
@SuppressLint({"MissingInflatedId", "LocalSuppress"}) TextView tvMessage = view.findViewById(R.id.tv_message);
// 滑动模块
@SuppressLint({"MissingInflatedId", "LocalSuppress"}) SlideToUnlockView unlockView = view.findViewById(R.id.unlockView);
// 高度
// @SuppressLint({"MissingInflatedId", "LocalSuppress"}) EditText et_height = view.findViewById(R.id.et_height);
// 完成下拉
@SuppressLint({"MissingInflatedId", "LocalSuppress"}) Spinner sp_protect = view.findViewById(R.id.sp_protect);
// 完成文字
@SuppressLint({"MissingInflatedId", "LocalSuppress"}) TextView tv_protect = view.findViewById(R.id.tv_protect);
//初始化下拉
String[] onePowerOptions = {"返航", "降落", "继续飞行"};
ArrayAdapter<String> onePowerAdapter = new ArrayAdapter<>(context,
android.R.layout.simple_spinner_item, onePowerOptions);
onePowerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sp_protect.setAdapter(onePowerAdapter);
// 为Spinner设置选择监听器
sp_protect.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
tv_protect.setText(parent.getItemAtPosition(position).toString());
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// 什么都不做
}
});
//点击弹出下拉
tv_protect.setOnClickListener(v -> {
sp_protect.performClick();
});
builder.setView(view);
AlertDialog dialog = builder.create();
dialog.show();
// 设置宽高
Window window = dialog.getWindow();
if (window != null) {
WindowManager.LayoutParams layoutParams = window.getAttributes();
layoutParams.width = MyTool.dpToPx(context, 300); // 或具体像素值
layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; // 或具体像素值
window.setAttributes(layoutParams);
window.setBackgroundDrawableResource(R.drawable.ffffffff_4round_bg);
}
unlockView.setText("滑动执行");
unlockView.setOnUnlockListener(new SlideToUnlockView.OnUnlockListener() {
@Override
public void onUnlock() {
// // 发送命令
// 调用FlyVoid中的方法发送航线到飞控
flyVoid.requestMissionStart(0,0);
MyTool.hideBottomNavigationBar( context);
dialog.dismiss();
// 滑动到阈值后触发如关闭对话框或执行操作
Toast.makeText(context, "开始执行航线", Toast.LENGTH_SHORT).show();
}
});
;
//取消按钮
tvMessage.setOnClickListener(v -> {
dialog.dismiss();
MyTool.hideBottomNavigationBar(context);
});
}
private void initSpinners() {
}
}

View File

@ -2,6 +2,7 @@ package com.example.longyi_groundstation.Main.Void;
import android.app.Activity;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
@ -96,6 +97,7 @@ public class AllView {
public SlideToUnlockView unlockView;
public RelativeLayout rl_unlock;
public EditText et_start_execute_height;
@ -177,7 +179,7 @@ public class AllView {
ll_link_start_back = activity.findViewById(R.id.ll_link_start_back);
unlockView = activity.findViewById(R.id.unlockView);
rl_unlock = activity.findViewById(R.id.rl_unlock);
et_start_execute_height = activity.findViewById(R.id.et_start_execute_height);
}
}

View File

@ -57,9 +57,15 @@ public class CoordinateConverter {
double sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((A * (1 - EE)) / (magic * sqrtmagic) * PI);
dlng = (dlng * 180.0) / (A / sqrtmagic * Math.cos(radlat) * PI);
return new double[]{lng + dlng, lat + dlat};
// 保留小数点后7位
double convertedLng = Math.round((lng + dlng) * 10000000) / 10000000.0;
double convertedLat = Math.round((lat + dlat) * 10000000) / 10000000.0;
return new double[]{convertedLng, convertedLat};
}
private static boolean outOfChina(double lng, double lat) {
return lng < 72.004 || lng > 137.8347 || lat < 0.8293 || lat > 55.8271;
}

View File

@ -1,5 +1,6 @@
package com.example.longyi_groundstation.Main.Void;
import static com.example.longyi_groundstation.MAVLink.common.msg_mission_ack.MAVLINK_MSG_ID_MISSION_ACK;
import static com.example.longyi_groundstation.MAVLink.common.msg_mission_count.MAVLINK_MSG_ID_MISSION_COUNT;
import static com.example.longyi_groundstation.MAVLink.common.msg_mission_item_int.MAVLINK_MSG_ID_MISSION_ITEM_INT;
import static com.example.longyi_groundstation.MAVLink.common.msg_mission_request.MAVLINK_MSG_ID_MISSION_REQUEST;
@ -7,6 +8,7 @@ import static com.example.longyi_groundstation.MAVLink.common.msg_mission_reques
import static com.example.longyi_groundstation.MAVLink.enums.MAV_CMD.MAV_CMD_NAV_LAND;
import static com.example.longyi_groundstation.MAVLink.enums.MAV_CMD.MAV_CMD_NAV_RETURN_TO_LAUNCH;
import static com.example.longyi_groundstation.MAVLink.enums.MAV_CMD.MAV_CMD_NAV_TAKEOFF;
import static com.example.longyi_groundstation.Main.Activity.MainActivity.startExecuteDialog;
import static com.example.longyi_groundstation.Main.Service.MyBoundService.MsgList;
import static com.example.longyi_groundstation.Main.Service.MyBoundService.type;
@ -35,6 +37,7 @@ import com.example.longyi_groundstation.MAVLink.common.msg_param_set;
import com.example.longyi_groundstation.MAVLink.enums.MAV_CMD;
import com.example.longyi_groundstation.MAVLink.enums.MAV_COMPONENT;
import com.example.longyi_groundstation.MAVLink.enums.MAV_FRAME;
import com.example.longyi_groundstation.MAVLink.enums.MAV_MISSION_TYPE;
import com.example.longyi_groundstation.Main.Activity.MainActivity;
import com.example.longyi_groundstation.Main.Base.CreateLink;
import com.example.longyi_groundstation.Main.Service.MyBoundService;
@ -362,10 +365,13 @@ public class FlyVoid {
* @param createLinkList 航线航点列表
* @cuijingzhou
*/
public void sendMissionToFlightController(Activity context, ArrayList<CreateLink> createLinkList) {
public void sendMissionToFlightController(Activity context, ArrayList<CreateLink> createLinkList, String height) {
if (createLinkList == null || createLinkList.isEmpty()) {
return;
}
if (height == null){
height = "10";
}
// 创建 ProgressDialog
android.app.ProgressDialog progressDialog = new android.app.ProgressDialog(context);
@ -376,18 +382,24 @@ public class FlyVoid {
progressDialog.setMax(100);
progressDialog.show();
MsgList.set(MAVLINK_MSG_ID_MISSION_REQUEST,null);
String finalHeight = height;
new Thread(() -> {
try {
// 2. 发送航点计数
msg_mission_count count = new msg_mission_count();
count.target_system = 1;
count.target_component = 1;
count.count = createLinkList.size() + 1; // 航点数量
count.count = createLinkList.size() + 2; // 航点数量
sendMavlinkMessage(type, count);
Log.d("Missions-count", "--" + ( createLinkList.size() + 2));
// 在FlyVoid.java的sendMissionToFlightController方法中找到以下代码块并修改
boolean isOk = true;
int sentWaypoints = 0;
int totalWaypoints = createLinkList.size() + 1;
int totalWaypoints = createLinkList.size() + 2;
int lastSeq = -1; // 添加这一行来记录上一次的seq值
while (isOk) {
try {
@ -395,7 +407,15 @@ public class FlyVoid {
if (msgRequest != null) {
JSONObject jsonObject = new JSONObject(msgRequest);
int seq = jsonObject.optInt("seq");
upDataLinkPoint(seq, createLinkList);
// 添加判断如果seq值没有改变跳过本次循环
if (seq == lastSeq) {
Thread.sleep(100); // 短暂休眠避免过度占用CPU
continue; // 跳过本次循环
}
upDataLinkPoint(seq, createLinkList, finalHeight);
lastSeq = seq; // 更新lastSeq值
sentWaypoints = seq + 1;
// 更新发送进度
@ -404,9 +424,8 @@ public class FlyVoid {
progressDialog.setProgress(progress);
});
Log.d("Missions", "--" + seq);
// 如果当前序号+1大于等于航点总数则结束循环
if ((seq + 1) > createLinkList.size()) {
if ((seq + 1) >= createLinkList.size()+2) {
isOk = false;
}
}
@ -420,10 +439,13 @@ public class FlyVoid {
}
}
context.runOnUiThread(() -> {
progressDialog.setMessage("正在校验航线...");
});
Log.d("Missions", "verifyResult");
// 校验点位是否正常上传
boolean verifyResult = verifyPoint(createLinkList);
@ -434,6 +456,7 @@ public class FlyVoid {
if (verifyResult) {
Toast.makeText(context, "航线已发送到飞控并校验通过", Toast.LENGTH_SHORT).show();
startExecuteDialog.show();
} else {
Toast.makeText(context, "航线发送完成但校验失败", Toast.LENGTH_SHORT).show();
}
@ -457,17 +480,19 @@ public class FlyVoid {
*
* @cuijingzhou
*/
private void upDataLinkPoint(int i,ArrayList<CreateLink> createLinkList) throws InterruptedException {
private void upDataLinkPoint(int i,ArrayList<CreateLink> createLinkList,String height) throws InterruptedException {
// Log.d("Missions", "--" + i);
// Log.d("Missions", "myReceiver_MISSION_ACK: ");
//由于第一个点是home点所以要从第2个点开始上传
if (i == 0){
msg_mission_item_int waypoint = new msg_mission_item_int();
waypoint.target_system = 1; // 无人机系统ID
waypoint.target_component = 1; // 无人机组件ID
waypoint.seq = 0; // 航点序号
waypoint.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系
waypoint.command = MAV_CMD.MAV_CMD_NAV_WAYPOINT; // 航点指令
waypoint.current = 0; // 第一个航点设为当前航点
waypoint.current = 1 ; // 第一个航点设为当前航点
waypoint.autocontinue = 1; // 自动继续到下一个航点
waypoint.param1 = 0; // 停留时间()
waypoint.param2 = 0; // 接受半径(m)
@ -477,11 +502,32 @@ public class FlyVoid {
waypoint.y = 0;
waypoint.z = 0; // 高度(相对)
sendMavlinkMessage(type, waypoint);
Thread.sleep(50);
Log.d("Missions", i+"--"+ waypoint.toString());
Thread.sleep(100);
} else if (i == 1) {
msg_mission_item_int waypoint1 = new msg_mission_item_int();
waypoint1.target_system = 1; // 无人机系统ID
waypoint1.target_component = 1; // 无人机组件ID
waypoint1.seq = i; // 航点序号
waypoint1.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系
waypoint1.command = MAV_CMD.MAV_CMD_NAV_TAKEOFF; // 航点指令
waypoint1.current = 0; // 第一个航点设为当前航点
waypoint1.autocontinue = 1; // 自动继续到下一个航点
waypoint1.param1 = 0; // 停留时间()
waypoint1.param2 = 0; // 接受半径(m)
waypoint1.param3 = 0; // 通过半径(m)
waypoint1.param4 = 0; // 航向角
waypoint1.x = 0;
waypoint1.y = 0;
waypoint1.z = Float.parseFloat(height); // 高度(相对)
waypoint1.mission_type = MAV_MISSION_TYPE.MAV_MISSION_TYPE_MISSION;
sendMavlinkMessage(type, waypoint1);
Log.d("Missions", i+"--"+ waypoint1.toString());
Thread.sleep(100);
}
//正常上传
else {
CreateLink link = createLinkList.get(i-1);
CreateLink link = createLinkList.get(i-2);
LatLng latLng = link.getLatLng();
double[] doubles = CoordinateConverter.gcj02ToWgs84(latLng.longitude, latLng.latitude);
if (doubles != null) {
@ -502,10 +548,13 @@ public class FlyVoid {
// 经度
waypoint.z = (float) link.getHeight(); // 高度(相对)
sendMavlinkMessage(type, waypoint);
Thread.sleep(50);
Log.d("Missions", i+"--"+ waypoint.toString());
Thread.sleep(100);
}
}
}
/**
@ -533,13 +582,13 @@ public class FlyVoid {
int count = countObject.optInt("count", 0);
// 检查飞控上的航点数是否与本地一致
if ((count-1) != createLinkList.size()) {
if ((count-2) != createLinkList.size()) {
Log.e("VerifyPoint", "航点数量不一致:本地=" + createLinkList.size() + ", 飞控=" + count);
return false;
}
// 逐一比对每个航点
for (int i = 1; i < count; ) {
for (int i = 2; i < count; ) {
// 请求飞控发送特定序号的航点
// 这里需要飞控支持自动发送或我们主动请求
// 由于MAVLink协议通常是飞控在收到MISSION_REQUEST_LIST后自动发送MISSION_ITEM
@ -553,11 +602,9 @@ public class FlyVoid {
// 发送消息请求航点列表
sendMavlinkMessage(type, requestLists);
// 等待一段时间让飞控发送对应序号的航点信息
Thread.sleep(50);
// 从MsgList获取飞控发送的航点信息
String missionItemMsg = MsgList.get(MAVLINK_MSG_ID_MISSION_ITEM_INT);
if (missionItemMsg != null) {
@ -565,7 +612,7 @@ public class FlyVoid {
int seq = missionItemObject.optInt("seq", -1);
Log.e("VerifyPoint", "第几个:" + seq + "+"+ i);
// 确保是当前要检查的序号
// 修复确保seq有效且i在有效范围内
// 修复确保seq有效且i在有效范围内因为第一个点是起飞
if (seq == i) {
// 获取飞控发送的航点坐标
double flyLat = Double.parseDouble(missionItemObject.optString("x")) / 10000000;
@ -574,7 +621,7 @@ public class FlyVoid {
Log.e("VerifyPoint", "坐标"+seq+"-" + flyLat + "+"+flyLng);
// 获取本地对应序号的航点
CreateLink localLink = createLinkList.get(i-1);
CreateLink localLink = createLinkList.get(i-2);
LatLng localLatLng = localLink.getLatLng();
double localHeight = localLink.getHeight();
@ -667,7 +714,7 @@ public class FlyVoid {
* 方法执行航线任务指定起始和结束点
*
* @param startSeq 起始航点序号从0开始
* @param endSeq 结束航点序号-1表示到最后一个航点
* @param endSeq 结束航点序号0表示到最后一个航点
* @cuijingzhou
*/
public void requestMissionStart(int startSeq, int endSeq) {
@ -690,5 +737,32 @@ public class FlyVoid {
}
/**
* 方法切换无人机飞行模式
*
* @param mode 飞行模式 (例如: 0=手动, 1=定高, 2=定点, 3=返航, 4=任务模式等)
* @cuijingzhou
*/
public void setFlightMode(int mode) {
// 构造命令
msg_command_long command = new msg_command_long();
command.target_system = 1; // 目标系统ID飞控
command.target_component = 1; // 目标组件ID
command.command = MAV_CMD.MAV_CMD_DO_SET_MODE; // 设置模式命令
command.confirmation = 0; // 确认位
command.param1 = 1; // MAV_MODE: 1表示使用自定义模式
command.param2 = mode; // 自定义模式 (具体值取决于飞控固件)
command.param3 = 0; // 保留
command.param4 = 0; // 保留
command.param5 = 0; // 保留
command.param6 = 0; // 保留
command.param7 = 0; // 保留
// 发送命令
sendMavlinkMessage(MyBoundService.type, command);
}
}

View File

@ -53,14 +53,14 @@
<!-- 底部数据栏 -->
<LinearLayout
android:visibility="visible"
android:id="@+id/ll_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:elevation="10dp"
android:paddingLeft="160dp">
android:paddingLeft="160dp"
android:visibility="visible">
<LinearLayout
android:layout_width="wrap_content"
@ -319,7 +319,7 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_type_list"
android:layout_width="160dp"
android:layout_width="195dp"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:layout_marginRight="10dp"
@ -548,18 +548,19 @@
<!-- 滑动解锁飞机 -->
<RelativeLayout
android:visibility="gone"
android:id="@+id/rl_unlock"
android:layout_below="@+id/ll_title"
android:layout_centerHorizontal="true"
android:layout_width="120dp"
android:layout_height="42dp">
android:layout_height="42dp"
android:layout_below="@+id/ll_title"
android:layout_centerHorizontal="true">
<com.example.longyi_groundstation.Main.View.SlideToUnlockView
android:background="#00000000"
android:id="@+id/unlockView"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_margin="8dp" />
android:layout_margin="8dp"
android:background="#00000000" />
</RelativeLayout>
@ -613,8 +614,8 @@
android:id="@+id/ll_all_link_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="3dp"
android:layout_marginLeft="3dp"
android:layout_marginTop="3dp"
android:background="@drawable/xbb303030_4round_bg"
android:orientation="vertical"
android:visibility="gone">
@ -897,7 +898,6 @@
<!-- 右侧布局 -->
<LinearLayout
android:visibility="visible"
android:id="@+id/ll_open_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -905,7 +905,8 @@
android:layout_alignParentRight="true"
android:layout_marginTop="3dp"
android:elevation="100dp"
android:orientation="horizontal">
android:orientation="horizontal"
android:visibility="visible">
<LinearLayout
android:id="@+id/ll_left_open"
@ -1505,14 +1506,14 @@
<!-- 路线规划 -->
<LinearLayout
android:id="@+id/ll_link"
android:visibility="gone"
android:layout_marginRight="10dp"
android:layout_below="@+id/ll_title"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_title"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:orientation="vertical">
android:layout_marginRight="10dp"
android:orientation="vertical"
android:visibility="gone">
<LinearLayout
android:id="@+id/ll_link_save"
@ -1539,9 +1540,9 @@
<LinearLayout
android:id="@+id/ll_link_fun1"
android:layout_marginTop="10dp"
android:layout_width="60dp"
android:layout_height="25dp"
android:layout_marginTop="10dp"
android:background="@drawable/b2101010_4round_1stroke_bg"
android:gravity="center"
android:orientation="horizontal">
@ -1559,9 +1560,9 @@
<LinearLayout
android:id="@+id/ll_link_fun2"
android:layout_marginTop="4dp"
android:layout_width="60dp"
android:layout_height="25dp"
android:layout_marginTop="4dp"
android:background="@drawable/b2101010_4round_1stroke_bg"
android:gravity="center"
android:orientation="horizontal">
@ -1579,9 +1580,9 @@
<LinearLayout
android:id="@+id/ll_link_back"
android:layout_marginTop="4dp"
android:layout_width="60dp"
android:layout_height="25dp"
android:layout_marginTop="4dp"
android:background="@drawable/b2101010_4round_1stroke_bg"
android:gravity="center"
android:orientation="horizontal">
@ -1601,45 +1602,78 @@
<!-- 路线执行 -->
<LinearLayout
android:gravity="center_horizontal"
android:id="@+id/ll_link_start"
android:visibility="gone"
android:layout_marginRight="10dp"
android:layout_below="@+id/ll_title"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/ll_title"
android:layout_alignParentRight="true"
android:layout_marginTop="10dp"
android:orientation="vertical">
android:layout_marginRight="10dp"
android:gravity="center_horizontal"
android:orientation="vertical"
android:visibility="gone">
<LinearLayout
android:id="@+id/ll_link_start_fun1"
android:layout_marginTop="4dp"
android:padding="2dp"
android:layout_width="65dp"
android:layout_height="28dp"
android:layout_marginTop="4dp"
android:background="@drawable/ffffffff_4round_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/et_start_execute_height"
android:layout_weight="1"
android:gravity="center"
android:text="10"
android:textSize="7sp"
android:textColor="#303030"
android:background="#ffffff"
android:layout_width="0dp"
android:layout_height="28dp" />
<TextView
android:paddingRight="5dp"
android:text="米"
android:textSize="9sp"
android:textColor="#303030"
android:background="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_link_start_fun1"
android:layout_width="65dp"
android:layout_height="28dp"
android:layout_marginTop="4dp"
android:background="@drawable/ff60b964_4round_1stroke_bg"
android:gravity="center"
android:orientation="horizontal">
<TextView
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="28dp"
android:gravity="center"
android:text="上传航线"
android:textColor="#ffffff"
android:textSize="9sp" />
android:textSize="9sp"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:visibility="gone"
android:id="@+id/ll_link_start_fun2"
android:layout_marginTop="4dp"
android:layout_width="65dp"
android:layout_height="28dp"
android:layout_marginTop="4dp"
android:background="@drawable/ff03a9f4_4round_1stroke_bg"
android:gravity="center"
android:orientation="horizontal">
@ -1656,9 +1690,9 @@
<LinearLayout
android:id="@+id/ll_link_start_back"
android:layout_marginTop="10dp"
android:layout_width="60dp"
android:layout_height="25dp"
android:layout_marginTop="10dp"
android:background="@drawable/b2101010_4round_1stroke_bg"
android:gravity="center"
android:orientation="horizontal">
@ -1668,7 +1702,7 @@
android:layout_width="wrap_content"
android:layout_height="25dp"
android:gravity="center"
android:text="退出执行"
android:text="退出页面"
android:textColor="#ffffff"
android:textSize="8sp" />

View File

@ -0,0 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="300dp"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/ff029a45_4round_bg"
android:gravity="center"
android:padding="8dp"
android:text="执行航线"
android:textColor="#fff"
android:textSize="13sp" />
<LinearLayout
android:layout_margin="12dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:textColor="#052011"
android:textSize="12sp"
android:text=" 当前点位已经上传完毕是否开始执行? 滑动后即可执行航线任务"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<LinearLayout
android:visibility="gone"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:paddingRight="5dp"
android:text="起飞高度:"
android:textSize="10sp"
android:textColor="#303030"
android:background="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<LinearLayout
android:padding="2dp"
android:layout_width="65dp"
android:layout_height="24dp"
android:background="@drawable/ffffffff_4round_bg"
android:gravity="center_vertical"
android:orientation="horizontal">
<EditText
android:id="@+id/et_height"
android:inputType="number"
android:layout_weight="1"
android:gravity="center"
android:text="10"
android:textSize="10sp"
android:textColor="#303030"
android:background="#ffffff"
android:layout_width="0dp"
android:layout_height="match_parent" />
<TextView
android:paddingRight="5dp"
android:text="米"
android:textSize="10sp"
android:textColor="#303030"
android:background="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:visibility="gone"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:paddingRight="5dp"
android:text="完成动作:"
android:textSize="10sp"
android:textColor="#303030"
android:background="#ffffff"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="65dp"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/rl_protect"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_protect"
android:background="@drawable/ff60b964_4round_1stroke_bg"
android:gravity="center"
android:textColor="#ffffff"
android:textSize="10sp"
android:text="返航"
android:layout_width="65dp"
android:padding="5dp"
android:layout_height="wrap_content"/>
<ImageView
android:layout_marginRight="5dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true"
android:src="@mipmap/icon_spinner_dowm"
android:layout_width="10dp"
android:layout_height="10dp"/>
</RelativeLayout>
<Spinner
android:id="@+id/sp_protect"
android:layout_below="@+id/rl_protect"
android:layout_width="65dp"
android:layout_height="0dp"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<com.example.longyi_groundstation.Main.View.SlideToUnlockView
android:background="#ffffff"
android:id="@+id/unlockView"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_margin="8dp" />
<TextView
android:id="@+id/tv_message"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_gravity="center"
android:background="#C3606060"
android:gravity="center"
android:text="取消"
android:textColor="#ffffff"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>