QGC地面站源码BUG——添加测绘后1号航点序号丢失的问题

添加测绘后1号航点序号丢失的问题


所有的热爱都要不遗余力,真正喜欢它便给它更高的优先级,和更多的时间吧!

关于QGC地面站其它文章请点击这里:     QGC地面站


一. 前言

● BUG介绍:

添加航点时候顺序本该为 0 1 2 3。 但添加测绘区域/走廊扫描/建筑扫描后,变为 0 2 3 4,如视频所示,一般来说缺1号航点,也不影响使用,但定制的时候,需对 0 1 2 号航点做特定的处理,就有影响了。

为了看清楚航点序号,我把字体调大了,注意看左小角的地势高度面板。

  QGC源码:

在这里插入图片描述
修改之后:

在这里插入图片描述
● 流程总结:

传入 patternDropPanel
点击工具栏的图案
点击测绘
路线一
specifyCameraModeChanged 信号连接到槽 _specifyChanged
itemCountChanged 信号连接到槽 _setDirtyAndUpdateLastSequenceNumber
只需要屏蔽 lastSequenceNumber += _cameraSection.itemCount 即可
路线二
文件: PlanView.qml
文件: ToolStrip.qml
通过dropPanel 打开 patternDropPanel
用户点击一级目录
用户点击二级目录
planview.qml函数: insertComplexItemAfterCurrent
MissionController.cc 函数: insertComplexMissionItem
MissionController.cc 函数: _insertComplexMissionItemWorker
上述函数中内容: cameraSection->setSpecifyCameraMode
CameraSection.cc中函数: _setDirtyAndUpdateItemCount
调用: lastSequenceNumber函数
_cameraSection.itemCount
itemCount++
上述函数中内容: _recalcAllWithCoordinate
MissionController.cc 函数 _recalcSequence
item->lastSequenceNumber

● 版本介绍

测试时用的版本为 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地面站

猜你喜欢

转载自blog.csdn.net/qq_16504163/article/details/111409146