Unable to assign [undefined] to QDeclarativeGeoMapType*

因为比赛的项目需求,我需要在arm平台上部署一个离线地图,我的开发板为正点原子的stm32mp157,我使用了qml中的地图示例,结合osm这个地图插件,从网上下载了高德地图的瓦片数据,将这些图片部署至本地nginx服务器上,以下是我的qml主要代码,功能包括旋转、倾斜、放大地图,路径规划,有同样需求的朋友可以参考
 

import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.12
import QtPositioning 5.6
import QtQuick.Controls 2.12 as QQC2
import PathPlanner 1.0  // 引入 C++ 类
import Qt.labs.qmlmodels 1.0
Window {
    width: 800
    height: 480
    visible: true

    // 定义 clickedLat 和 clickedLon 为全局属性
    property real clickedLat: 0.0
    property real clickedLon: 0.0

    // 地图插件配置
    Plugin {
        id: mapPlugin
        name: "osm"
        PluginParameter {
            name: "osm.mapping.custom.host"
            value: "http://192.168.0.104/gaodemap/"
        }
        PluginParameter {
            name: "osm.mapping.providersrepository.disabled"
            value: true
        }
        PluginParameter {
            name: "osm.mapping.cache.directory"
            value: "/home/root/tmp"
        }
    }
    // 实例化 CoordinateConverter 类

    RouteQuery {
        id: routeQuery
    }

    RouteModel {
        id: routeModel
        plugin: mapPlugin
        query: routeQuery
        autoUpdate: false
    }

    // 背景矩形填充白色区域
    Rectangle {
        width: parent.width
        height: 162
        z: 998
        gradient: Gradient {
            GradientStop { position: 0.0; color: "lightblue" }
            GradientStop { position: 0.5; color: Qt.rgba(173/255, 216/255, 230/255, 0.5) }
            GradientStop { position: 1.0; color: Qt.rgba(248/255, 247/255, 247/255, 0) }
        }
    }

    // 遮罩层
    Rectangle {
        id: overlay
        width: parent.width
        height: parent.height
        color: "black"
        opacity: 0.5
        visible: false
        z: 999

        MouseArea {
            anchors.fill: parent
            onClicked: {
                menu.close(); // 关闭菜单
                overlay.visible = false; // 隐藏遮罩层
            }
        }
    }

    // 地图组件
    Map {
        id: map
        width: 800
        activeMapType: supportedMapTypes[6]
        height: 480
        plugin: mapPlugin
        center: QtPositioning.coordinate(28.195301, 112.865778)
        zoomLevel: 17 // 初始值在16-18之间
        tilt: 80
        fieldOfView: 27

        // 设置层级限制
         Component.onCompleted: {
             map.zoomLevel = Math.max(16, Math.min(18, map.zoomLevel))
             if (supportedMapTypes.length > 6 && supportedMapTypes[6]) {
                  activeMapType = supportedMapTypes[6];
                  console.log("Active map type set to:", activeMapType);
              } else {
                  console.log("Invalid map type at index 6. Using the first available map type.");
                  activeMapType = supportedMapTypes[0]; // 选择第一个有效的地图类型
              }
         }

         // 如果希望用户交互时也能限制缩放级别
         onZoomLevelChanged: {
             map.zoomLevel = Math.max(16, Math.min(18, map.zoomLevel))
         }
         MapPolyline {
             id: routePolyline
             line.color: "blue"
             line.width: 5
             smooth: true
         }
        // 起点图标
        MapQuickItem {
            id: startPoint
            visible: true  // 默认不显示
            coordinate: QtPositioning.coordinate(28.194391, 112.866002)
            sourceItem: Image {
                source: "qrc:/image/marker_red.png"
                width: 30
                height: 30
                onParentChanged: {
                    if (parent) {
                        anchors.bottom = parent.bottom
                        anchors.horizontalCenter = parent.horizontalCenter
                    }
                }
            }
        }

                // PathPlanner 信号槽

        // 终点图标
        MapQuickItem {
            id: endPoint
            visible: false  // 默认不显示
            coordinate: QtPositioning.coordinate(28.195402, 112.865900)
            sourceItem: Image {
                source: "qrc:/image/mark_bs.png"
                width: 30
                height: 30
                onParentChanged: {
                    if (parent) {
                        anchors.bottom = parent.bottom
                        anchors.horizontalCenter = parent.horizontalCenter
                    }
                }
            }
        }
        PathPlanner {
            id: pathPlanner
            onPathReceived: {
                  console.log("Received path:", pathCoordinates);
                  // 将接收到的扁平化数组转换为嵌套的数组
                var pathArray = [];
                var start_coordinate = QtPositioning.coordinate(startPoint.coordinate.latitude,startPoint.coordinate.longitude);
//              pathArray.push(start_coordinate);
                for (var i = 0; i < pathCoordinates.length; i += 2) {
                      var lat = pathCoordinates[i];
                      var lon = pathCoordinates[i + 1];
                      var coordinate = QtPositioning.coordinate(lat, lon);
                      pathArray.push(coordinate);
                  }
                var end_coordinate = QtPositioning.coordinate(endPoint.coordinate.latitude,endPoint.coordinate.longitude);
//                    pathArray.push(end_coordinate);
                  // 使用 addCoordinate 来动态添加坐标
                  routePolyline.path = pathArray;

              }
        }

        MouseArea {
            id: mapMouseArea
            anchors.fill: parent
            property bool isPressed: false
            property real startX: 0
            property real startY: 0
            property real dragX: 0
            property real dragY: 0

            onPressed: {
                isPressed = true
                startX = mouse.x
                startY = mouse.y
                dragX = 0
                dragY = 0
            }

            onReleased: {
                if (isPressed && dragX < 10 && dragY < 10) {
                    var clickedCoordinate = map.toCoordinate(Qt.point(mouse.x, mouse.y));
                    console.log("Clicked Coordinate: ", clickedCoordinate.latitude, clickedCoordinate.longitude);

                    // 更新点击位置并显示菜单
                    menu.x = mouse.x - menu.width / 2;
                    menu.y = mouse.y - menu.height / 2;
                    menu.open();

                    // 更新全局坐标
                    clickedLat = clickedCoordinate.latitude;
                    clickedLon = clickedCoordinate.longitude;
                }
                isPressed = false
            }

            onPositionChanged: {
                if (isPressed) {
                    dragX = Math.abs(mouse.x - startX);
                    dragY = Math.abs(mouse.y - startY);
                }
            }
        }

        // 弹出菜单
        QQC2.Popup {
            id: menu
            width: 100
            height: 105
            visible: false
            padding: 0
            onVisibleChanged: {
                if (menu.visible) {
                    overlay.visible = true;
                }
            }

            Column {
                width: parent.width
                spacing: 0

                // 使用 Repeater 来动态生成菜单项
                Repeater {
                    model: ["设为起点", "设为途经点", "设为终点"]
                    delegate: Rectangle {
                        width: parent.width
                        height: 35
                        border.color: "black"
                        Text {
                            anchors.centerIn: parent
                            text: modelData
                        }

                        MouseArea {
                            anchors.fill: parent
                            onClicked: {
                                menu.close();
                                overlay.visible = false;

                                // 根据不同选项设置坐标并显示图标
                                if (modelData === "设为起点") {
                                    startPoint.coordinate = QtPositioning.coordinate(clickedLat, clickedLon);
                                    startPoint.visible = true;
//                                    console.log(startPoint.coordinate.latitude);
                                } else if (modelData === "设为途经点") {
                                    waypoint.coordinate = QtPositioning.coordinate(clickedLat, clickedLon);
                                    waypoint.visible = true;
                                } else if (modelData === "设为终点") {
                                    endPoint.coordinate = QtPositioning.coordinate(clickedLat, clickedLon);
                                    endPoint.visible = true;
                                }

                                if (startPoint.visible && endPoint.visible) {
                                    pathPlanner.requestRoute(startPoint.coordinate.latitude, startPoint.coordinate.longitude,
                                    endPoint.coordinate.latitude, endPoint.coordinate.longitude);
                                 }
                            }
                        }
                    }
                }
            }
        }

    }
}

我的代码在我本机上的Ubuntu虚拟机上跑是没有问题的,但是部署到arm开发板上时报如下的错

Unable to assign [undefined] to QDeclarativeGeoMapType*

 询问gpt得知是缺少了osm插件(plugin),也就是我的arm板上的qt系统其实是没有移植这个插件的,所以我需要去交叉编译一次qt系统,将我想要的插件再复制到我的arm板系统上,交叉编译qt系统我参考了【Linux】QT5移植到Linux ARM_qt5 移植-优快云博客         这篇文章,同时我要补充一下我遇到的不同的报错

首先,在前期下库的过程,我还需要多下载一个库,不然会报错

sudo apt-get install libevdev-dev

其次是博主在autoConfigure.sh这个自定义文件里加入了-skip qtlocation \这个选项,我们要删掉,因为我们需要的就是qtlocation生成的插件

然后编译过程报错

Project ERROR: Building QtQml requires Python.
Makefile:336: recipe for target 'module-qtdeclarative-make_first' failed
make: *** [module-qtdeclarative-make_first] Error 3

我们需要下载python环境

sudo apt update
sudo apt install python3
sudo ln -s /usr/bin/python3 /usr/bin/python

 重新make即可

我们可以加快编译速率使用以下命令,为编译分配更多核心线程

make -j$(nproc)

最好按照博主的文章,我得到了编译好后对的文件

我们要解决我标题的这个报错,就需要将geoservices这个文件夹移植到arm板上去,我将其打成tar包,使用scp命令传到了开发板上,我的对应的插件移植目录是在/usr/lib/plugin,我将打包好的geoservices.tar文件在此解包,重新部署我的qml项目,地图就显示出来了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值