所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多的时间吧!
关于QGC地面站其它文章请点击这里: QGC地面站
一. 前言
● BUG介绍:
添加航点时候顺序本该为 0 1 2 3。 但添加测绘区域/走廊扫描/建筑扫描后,变为 0 2 3 4,如视频所示,一般来说缺1号航点,也不影响使用,但定制的时候,需对 0 1 2 号航点做特定的处理,就有影响了。
为了看清楚航点序号,我把字体调大了,注意看左小角的地势高度面板。
QGC源码:
修改之后:
● 流程总结:
● 版本介绍
测试时用的版本为 v4.0.0, 查看最新代码 v4.0.11 也没有解决此问题。
接下来让我们顺着添加测绘区域的调用逻辑,来解决此BUG,并分析其执行流程(只显示关键代码),如果只想结果,可以点击这里,跳到最后。
二. 流程分析
可以对照上面流程总结一起看
1. QML前端
//PlanView.qml :565
ToolStrip {
id: toolStrip
...
model: [
{
dropPanelComponent: _singleComplexItem ? undefined : patternDropPanel
...
...
//ToolStrip.qml :113
onClicked: {
if (modelData.dropPanelComponent === undefined) {
...
} else if (checked) {
dropPanel.show(panelEdgeTopPoint, height, modelData.dropPanelComponent)
}
}
dropPanel 中Loader了 modelData.dropPanelComponent;另外还绘制那个外框,还包括了三角形:
而 modelData.dropPanelComponent 就是 planview.qml 下的 patternDropPanel 它定义如下:
Component {
id: patternDropPanel
...
Repeater {
model: _missionController.complexMissionItemNames
QGCButton {
onClicked: {
insertComplexItemAfterCurrent(modelData)
...
}
可以直接按照数组的方式直接取model中的项,如下:
_missionController.complexMissionItemNames[0] // 测绘
_missionController.complexMissionItemNames[1] // 走廊扫描
_missionController.complexMissionItemNames[2] // 建筑扫描
insertComplexItemAfterCurrent 中:
function insertComplexItemAfterCurrent(complexItemName) {
...
_missionController.insertComplexMissionItem(complexItemName, mapCenter(), nextIndex, true /* makeCurrentItem */)
}
2. c++后端
src\MissionManager\MissionController.cc:463 中:
VisualMissionItem* MissionController::insertComplexMissionItem(QString itemName, QGeoCoordinate mapCenterCoordinate, int visualItemIndex, bool makeCurrentItem)
{
...
//实例化测绘的复杂航点
if (itemName == patternSurveyName) {
newItem = new SurveyComplexItem(_controllerVehicle, _flyView, QString() /* kmlFile */, _visualItems /* parent */);
}
_insertComplexMissionItemWorker(mapCenterCoordinate, newItem, visualItemIndex, makeCurrentItem);
...
}
_insertComplexMissionItemWorker 函数:
void MissionController::_insertComplexMissionItemWorker(const QGeoCoordinate& mapCenterCoordinate, ComplexMissionItem* complexItem, int visualItemIndex, bool makeCurrentItem)
{
...
//经调试发现问题出在这里
cameraSection->setSpecifyCameraMode(true);
...
}
如何确认问题了? 可以debug单步调试,查看关键变量,这样很耗电脑资源。我是直接打印调试的。可以在部分语句或者每条语句下加入如下:
qDebug() << "[2]count" <<_visualItems->count();
for (int i=0; i < _visualItems->count(); i++) {
VisualMissionItem* visualItem = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
qDebug() << "i:" << i << " " << visualItem->sequenceNumber();
}
具体操作如下:
setSpecifyCameraMode 函数定义:
void CameraSection::setSpecifyCameraMode(bool specifyCameraMode)
{
if (specifyCameraMode != _specifyCameraMode) {
_specifyCameraMode = specifyCameraMode;
emit specifyCameraModeChanged(specifyCameraMode);
}
}
● 第一条路:specifyCameraModeChanged 信号的流程
可以点击这里查看流程图
//CameraSection.cc
connect(this, &CameraSection::specifyCameraModeChanged, this, &CameraSection::_specifyChanged);
specifyCameraModeChanged 信号的槽为_specifyChanged函数:
//CameraSection.cc
void CameraSection::_specifyChanged(void)
{
_setDirtyAndUpdateItemCount();
_updateSettingsSpecified();
}
继续:_setDirtyAndUpdateItemCount函数
//CameraSection.cc
void CameraSection::_setDirtyAndUpdateItemCount(void)
{
emit itemCountChanged(itemCount());
setDirty(true);
}
itemCountChanged 信号的槽为 _setDirtyAndUpdateLastSequenceNumber,如下:
// MissionSettingsItem.cc
connect(&_cameraSection, &CameraSection::itemCountChanged, this, &MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber);
// MissionSettingsItem.cc
void MissionSettingsItem::_setDirtyAndUpdateLastSequenceNumber(void)
{
emit lastSequenceNumberChanged(lastSequenceNumber());
setDirty(true);
}
而关键就是lastSequenceNumber() 函数:
//MissionSettingsItem.cc
int MissionSettingsItem::lastSequenceNumber(void) const
{
int lastSequenceNumber = _sequenceNumber;
lastSequenceNumber += _cameraSection.itemCount();
lastSequenceNumber += _speedSection.itemCount();
return lastSequenceNumber;
}
//CameraSection.cc:92
int CameraSection::itemCount(void) const
{
if (_specifyGimbal) {
itemCount++;
}
...
return itemCount;
}
答案就明显了,MissionSettingItem代表的是第一个航点的设置,也就是起始的launch点,而我们序号乱的问题也出在了launch点后。 而 MissionSettingsItem 也是继承了复杂航点 ComplexMissionItem 。
如下注释后,在添加测绘区域/走廊扫描/建筑扫描后,航点顺序为 0 1 2 号,完全正确。
//MissionSettingsItem.cc:63
int MissionSettingsItem::lastSequenceNumber(void) const
{
int lastSequenceNumber = _sequenceNumber;
// lastSequenceNumber += _cameraSection.itemCount();
// lastSequenceNumber += _speedSection.itemCount();
return lastSequenceNumber;
}
而未修改的时候,再指定相机模式下,launch点后,确实多算了一个航点总数,我个人认为是一个BUG,因为没有发现哪里有 new 一下1号航点。如果确实用到了,欢迎指正~
● 再看第二条路, _recalcAllWithCoordinate(mapCenterCoordinate)
void MissionController::_insertComplexMissionItemWorker(const QGeoCoordinate& mapCenterCoordinate, ComplexMissionItem* complexItem, int visualItemIndex, bool makeCurrentItem)
{
...
//第一条路已分析
cameraSection->setSpecifyCameraMode(true);
//第二条路
_recalcAllWithCoordinate(mapCenterCoordinate);
}
为什么是它?也是一样的调试发现的(需要关闭第一条路的影响哦)
void MissionController::_recalcAllWithCoordinate(const QGeoCoordinate& coordinate)
{
_recalcSequence();
...
}
// This will update the sequence numbers to be sequential starting from 0
void MissionController::_recalcSequence(void)
{
...
for (int i=0; i<_visualItems->count(); i++) {
VisualMissionItem* item = qobject_cast<VisualMissionItem*>(_visualItems->get(i));
item->setSequenceNumber(sequenceNumber);
sequenceNumber = item->lastSequenceNumber() + 1;
}
}
item[0] 就是 MissionSettingsItem,就是调用了:
int MissionSettingsItem::lastSequenceNumber(void) const
{
int lastSequenceNumber = _sequenceNumber;
// lastSequenceNumber += _cameraSection.itemCount();
// lastSequenceNumber += _speedSection.itemCount();
return lastSequenceNumber;
}
上文已介绍哦!
三. 总结
你也可以不看流程的分析,只需要注释如下,再添加测绘区域/走廊扫描/建筑扫描后,则航点顺序为 0 1 2 号,完全正确。//MissionSettingsItem.cc:63
int MissionSettingsItem::lastSequenceNumber(void) const
{
int lastSequenceNumber = _sequenceNumber;
// lastSequenceNumber += _cameraSection.itemCount();
// lastSequenceNumber += _speedSection.itemCount();
return lastSequenceNumber;
}
如果对QGC地面站有开发需求,欢迎点个关注哈,后面会不定时更新的~
关于QGC地面站其它文章请点击这里: QGC地面站