因为比赛的项目需求,我需要在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项目,地图就显示出来了