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地面站

  • 32
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 20
    评论
QGC地面站(QGroundControl)是用于控制和监控无人机系统的开地面站软件。它提供了用户界面,用户可以使用该界面与无人机进行通信,发送指令和接收数据。对于想要学习和了解QGC地面站的人来说,以下是一些学习资料建议。 首先,可以通过访问QGC官方网站(https://docs.qgroundcontrol.com/)来获取官方的学习资料。该网站提供了QGC地面站的全部文档,包括用户手册、操作指南、教程和开发者文档等。这些文档详细介绍了QGC地面站的各种功能和使用方法,对于初学者来说是很好的学习资料。 其次,QGC地面站的开性质使得有很多社区和论坛可以参考和学习。比如,可以加入QGC地面站的官方论坛(https://discuss.px4.io/c/qgc)或者无人机开发社区,与其他开发者和用户交流经验和问题。在这些社区中,你可以找到很多有关QGC地面站的讨论和指导,还可以提出自己的问题和疑问。 此外,还可以寻找一些在线教程和视频资,例如在YouTube上搜索“QGC地面站教程”等关键词,会有很多开发者分享的学习视频。在这些视频中,你可以看到具体的操作步骤和实例演示,更好地理解和掌握QGC地面站的使用方法。 最后,建议尝试实际操作QGC地面站与无人机连接和控制。实践是学习的最佳方式,只有亲自操作才能更好地理解和掌握软件的功能。可以尝试模拟连接无人机、发送指令、查看数据等操作,进一步加深对QGC地面站的理解。 综上所述,通过官方文档、社区交流、在线教程和实践操作等多种途径,可以全面了解和学习QGC地面站的使用方法和功能。有了这些学习资料的支持,相信你能够更好地掌握和应用QGC地面站

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值