Mavlink地面站编写之六---MP源码多线程读写框架分析
来源:互联网 发布:残差网络的作用 编辑:程序博客网 时间:2024/04/28 23:04
转载请注明出处!阿木开源社区 玩也要玩的专业 http://www.amovauto.com/?p=743#more-743
对于MissionPlanner这种多任务的程序,我们知道要采用多线程的方式来实现,读数据,显示数据,写数据。这是就需要一些数据同步的问题。尤其是串口数据的读写的数据同步。数据读写模型,比如常见的生产者,消费者模型。这里不再多述。我们来分析下MP代码的读线程,写线程,来实现我们社区的开源地面站的显示数据和写入指令的功能。下面看看数据读取线程的代码,这个数据线程读取的代码在MainV2.CS中的1962行左右。
while (port.BaseStream.IsOpen && port.BaseStream.BytesToRead > minbytes && port.giveComport == false) { try { port.readPacket(); } catch (Exception ex) { log.Error(ex); } } // update currentstate of sysids on the port foreach (var MAV in port.MAVlist.GetMAVStates()) { try { MAV.cs.UpdateCurrentSettings(null, false, port, MAV); } catch (Exception ex) { log.Error(ex); } }
其中port.readPacket()这个语句是把数据读到一个数据缓冲区,显示线程就可以从这个数据缓冲区拿出来显示了,具体的代码参考mavlinkinterface的内容。这个函数里面有些数据的上锁,解锁的语句,是为了完成数据同步。这是读取数据,下面我们看看如果我们要实现发送指令或者航点给飞控,也就是写数据,我们应该怎么操作。写数据一定是在另外一个线程里面。在FlightPlanne.cs中的1863行,我们可以看到写入航点的操作
private void BUT_write_Click(object sender, EventArgs e) { if ((altmode) CMB_altmode.SelectedValue == altmode.Absolute) { if (DialogResult.No == CustomMessageBox.Show("Absolute Alt is selected are you sure?", "Alt Mode", MessageBoxButtons.YesNo)) { CMB_altmode.SelectedValue = (int) altmode.Relative; } } // check for invalid grid data for (int a = 0; a < Commands.Rows.Count - 0; a++) { for (int b = 0; b < Commands.ColumnCount - 0; b++) { double answer; if (b >= 1 && b <= 7) { if (!double.TryParse(Commands[b, a].Value.ToString(), out answer)) { CustomMessageBox.Show("There are errors in your mission"); return; } } if (TXT_altwarn.Text == "") TXT_altwarn.Text = (0).ToString(); if (Commands.Rows[a].Cells[Command.Index].Value.ToString().Contains("UNKNOWN")) continue; byte cmd = (byte) (int) Enum.Parse(typeof (MAVLink.MAV_CMD), Commands.Rows[a].Cells[Command.Index].Value.ToString(), false); if (cmd < (byte) MAVLink.MAV_CMD.LAST && double.Parse(Commands[Alt.Index, a].Value.ToString()) < double.Parse(TXT_altwarn.Text)) { if (cmd != (byte) MAVLink.MAV_CMD.TAKEOFF && cmd != (byte) MAVLink.MAV_CMD.LAND && cmd != (byte) MAVLink.MAV_CMD.RETURN_TO_LAUNCH) { CustomMessageBox.Show("Low alt on WP#" + (a + 1) + "\nPlease reduce the alt warning, or increase the altitude"); return; } } } } ProgressReporterDialogue frmProgressReporter = new ProgressReporterDialogue { StartPosition = FormStartPosition.CenterScreen, Text = "Sending WP's" }; frmProgressReporter.DoWork += saveWPs; frmProgressReporter.UpdateProgressAndStatus(-1, "Sending WP's"); ThemeManager.ApplyThemeTo(frmProgressReporter); frmProgressReporter.RunBackgroundOperationAsync(); frmProgressReporter.Dispose(); MainMap.Focus(); }
上面的函数是一些验证航点逻辑准确性的操作,frmProgressReporter.DoWork += saveWPs;这是实现了一个委托。而saveWPs这个函数是数据写入函数.port.setWPTotal(写入一共的航点数量),port.setWP(写入航点), port.setParam(设置参数), port.setWPACK(给飞控应答)。
这里我们可以看到是遵循MAVLINK的读写协议的,首先地面站写入航点数量(port.setWPTotal),地面站收到航点请求指令,地面站向飞控写入航点(port.setWP),最后port.setWPACK完成应答.源码太长自行打开源码阅读参考。这是完整的写入数据的流程。其中我们还有注意一点就是 MainV2.comPort.giveComport = true;这句,在 saveWPs函数中,这是这个写入线程占用COM端口的标志,通过这句话,我发现MP的数据读写通信是半双工的。因为在数据的代码中我们会发现 while (port.BaseStream.IsOpen && port.BaseStream.BytesToRead > minbytes &&port.giveComport == false)这句话中的port.giveComport == false表示,没有数据写入,也就是COM没有占用,读数据才会有效,否则跳出数据读循环。也就是说MP的源码通port.giveComport 来判断是不可以读取数据。所以如果port.giveComport == true表示当前有数据在写入,就不会去读取数据。由此看出MP地面站的代码数据读写是半双工的。我也是在写社区地面站的时候发现这一点的,否则我采用mavlinkinterface的时候写入航点一直有问题,就出在写入数据的时候,不能读取数据。本人浅解欢迎批评指正!
- Mavlink地面站编写之六---MP源码多线程读写框架分析
- Mavlink地面站编写之五—MP源码多线程读写框架分析
- Mavlink地面站编写之三--Mission PLanner地面站构架分析之MAVLINK航点读写
- Mavlink地面站编写之二–Mission PLanner地面站构架分析之MAVLINK航点读写
- Mavlink地面站编写之–协议分析
- Mavlink地面站编写--协议分析
- Mavlink地面站编写之四--Mission PLanner地面站构架分析之MAVLINK航点写入
- Mavlink地面站编写之三–Mission PLanner地面站构架分析之MAVLINK航点写入
- Mavlink地面站编写之一--协议分析
- Mavlink地面站编写之一–协议分析
- Mavlink地面站编写之八–MAVLINK消息自定义
- Mavlink地面站编写之五-Mission Planner中ProgressReporterDialogue和读串口线程serialreaderthread的分析
- Mavlink地面站编写之四-Mission Planner中ProgressReporterDialogue和读串口线程serialreaderthread的分析
- Mavlink地面站编写之二--Mission Planner编译
- Mavlink地面站编写之七—发送控制指令
- Mavlink地面站编写之七—发送控制指令
- Android地面站-MavLink解析部分源码
- 【GamingAnywhere源码分析之知识补充六】Windows多线程信号通信与GA整体框架修改
- angularjs select option默认值
- ibatis源码分析
- RHEL7启动配置和服务管理
- Cookie未设置Domain
- js将对象所有属性(都是数字,浮点小数),将其保留整数
- Mavlink地面站编写之六---MP源码多线程读写框架分析
- MySQL之JDBC链接工具类
- Codeforces Round #352 (Div. 2) Robin Hood
- oracle通过exp导出dump,报错报错,EXP-00008: 遇到 ORACLE 错误 90 ORA-00904: "POLTYP": 标识符无效 EXP-00000: 导出终止失败
- 深入理解RunLoop
- 身体很重要~
- 表情识别数据
- Android启动时,白色背景上有蓝色一闪而过
- Asynctask异步处理类的使用