一、前言
1.1 项目介绍
【1】项目背景
随着汽车工业的飞速发展和智能化技术的不断突破,车载导航系统作为现代汽车不可或缺的一部分,在人们的日常生活中扮演着越来越重要的角色。它不仅能够提供精确的路线导航,还能提供丰富的地理信息和娱乐服务,为驾驶者带来了极大的便利和乐趣。
传统的车载导航系统主要依赖于内置的地图数据和GPS定位技术,但随着移动互联网的普及和智能设备的快速发展,用户对车载导航系统的要求也在不断提高。希望车载导航系统能够具备更高的定位精度、更丰富的地图信息、更便捷的操作体验以及更强的可扩展性。
开发一款基于嵌入式技术的车载导航定位系统,以满足现代用户对高效、智能、个性化导航服务的需求,成为了当前行业发展的一个重要方向。本项目通过集成高性能的主控开发板、精准的GPS定位模块以及强大的Qt开发框架,实现一个功能丰富、性能稳定、用户体验优越的车载导航系统。
【2】设计实现的功能
(1)实时定位与地图显示:通过外接的北斗GPS模块,系统能够实时接收并解析卫星信号,获取车辆的精确位置信息。这些信息将实时显示在基于Qt开发的主界面上,与百度地图API无缝对接,为用户呈现清晰、准确的地图画面。
(2)路线规划与导航:用户可以通过主界面输入目的地信息,系统根据百度地图API提供的路径规划服务,计算出最优的行驶路线,并在地图上进行高亮显示。在导航过程中,系统能够实时追踪车辆位置,提供转向、距离等导航指令,确保用户能够准确、快速地到达目的地。
(3)地图预览与缩放:系统支持地图的缩放和拖动功能,用户可以根据需要调整地图的显示范围,查看不同级别的地理细节。同时,系统还提供了多种地图视图模式(如白天模式、夜间模式等),以满足用户在不同场景下的使用需求。
(4)语音提示与交互:为了提升用户体验,系统集成了语音提示功能,能够在关键导航节点(如转弯、路口等)给予用户语音指令,减少用户操作干扰。此外,系统还支持通过语音指令进行简单的交互操作,如查询附近的餐饮、加油站等设施。
(5)个性化设置与偏好管理:用户可以根据自己的使用习惯,在系统设置中调整界面风格、导航偏好等参数。系统还会记录用户的行驶历史,为用户提供个性化的推荐和服务。
(6)系统稳定性与扩展性:基于嵌入式Linux系统的开发框架,保证了系统的稳定性和可靠性。同时,开放式的架构设计使得系统易于扩展和升级,能够随时集成新的功能模块和服务,满足用户不断增长的需求。
本项目设计的基于嵌入式的车载导航定位系统,通过集成高性能硬件和先进的软件开发技术,实现了实时定位、路线规划、地图预览、语音提示、个性化设置等多项功能,为用户提供了高效、智能、个性化的导航服务体验。
【3】项目硬件模块组成
(1)主控开发板:采用GEC6818开发板,该开发板搭载了三星Cortex-A53系列高性能八核处理器S5P6818,最高主频高达1.4GHz。主控开发板作为整个系统的核心,负责处理导航定位系统的所有运算和控制任务,确保系统的稳定运行。
(2)GPS模块:采用北斗GPS模块,该模块负责接收并解析卫星信号,获取车辆的精确位置信息。通过与主控开发板的连接,将位置数据实时传输给系统进行处理和显示。
(3)显示屏:用于呈现地图、导航指令以及其他相关信息。显示屏与主控开发板相连,通过Qt开发的界面,将系统的各项功能直观地展示给用户。
(4)网卡: 用于上网,调用百度地图,这是开发板本身自带。
(5)语音播报模块: 利用开发板本身的声卡播放导航提示。
1.2 设计思路
(1)需求分析:对车载导航定位系统的需求进行深入分析。确定系统需要具备的功能,如实时定位、路线规划、地图显示、语音提示等。同时,考虑到用户的操作习惯和驾驶过程中的安全性,对界面的设计、交互的流畅性等方面也进行了充分考虑。
(2)硬件选型:根据需求分析的结果,选择适合的硬件组件。主控开发板选用GEC6818开发板,其高性能的处理器和嵌入式Linux系统为系统的稳定运行提供了有力支持。GPS模块选用北斗GPS模块,以确保定位的准确性和稳定性。同时,选择高质量的显示屏和其他辅助模块,以满足系统的各项需求。
(3)软件架构设计:采用Qt作为软件开发框架,利用其强大的图形界面开发能力和跨平台特性,实现系统的主界面和各项功能。通过集成百度地图API,实现地图的加载、显示和路径规划等功能。同时,设计合理的软件架构,确保各个模块之间的协同工作和数据传输的高效性。
(4)功能模块划分:将系统划分为多个功能模块,如定位模块、导航模块、地图显示模块、语音提示模块等。每个模块负责实现特定的功能,并通过接口与其他模块进行交互。这种模块化的设计方式便于后期的维护和扩展。
1.3 系统功能总结
功能模块 | 功能描述 | 技术实现与特点 |
---|---|---|
实时定位 | 通过北斗GPS模块获取车辆精确位置信息。 | 利用北斗卫星导航系统,提供高精度、稳定的定位服务。 |
地图显示 | 在显示屏上呈现百度地图,展示地理信息。 | 集成百度地图API,实现地图的加载、缩放、拖动等功能。 |
路线规划 | 根据用户输入的目的地,计算最优行驶路线。 | 利用百度地图API的路径规划服务,提供多种路线选择。 |
导航指引 | 提供转向、距离等导航指令,辅助用户驾驶。 | 实时追踪车辆位置,根据规划路线提供准确的导航指引。 |
语音提示 | 通过语音输出导航指令和其他相关信息。 | 集成语音合成技术,实现人性化的交互体验。 |
地图预览与缩放 | 支持地图的预览、缩放和拖动操作。 | 提供多种地图视图模式,满足不同场景下的使用需求。 |
个性化设置 | 用户可根据喜好设置系统界面和导航偏好。 | 提供丰富的设置选项,满足用户的个性化需求。 |
系统稳定性 | 确保系统在各种环境下的稳定运行。 | 基于嵌入式Linux系统开发,具备高度的稳定性和可靠性。 |
扩展性 | 系统设计易于扩展和升级,适应未来需求变化。 | 开放的架构设计,支持新功能模块和服务的集成。 |
1.4 原理图
二、Linux下Qt开发环境搭建
养老院出行管理系统项目是在Linux下开发,接下来需要搭建Linux下的开发环境。
(1)第一步,安装VM虚拟机
(2)第二步,在VM虚拟机里安装Ubuntu18.04系统
(3)第三步,在Ubuntu18.04系统里安装QT开发环境
2.1 安装VMware虚拟机软件
VMware软件下载地址: www.vmware.com/products/wo...
当前电脑使用的vmware版本为: 15.5
2.2 安装Ubuntu18.04系统
18.04最新长期支持版本: mirrors.aliyun.com/ubuntu-rele...
2.3 安装Qt5.12开发环境
注意,安装Qt之前要先安装以下工具(如果之前安装了就不用再安装了):
cpp
sudo apt install make
sudo apt install gcc
sudo apt install g++
Qt安装包下载地址:download.qt.io/archive/qt/...
2.4 Qt编译常见问题解决
cpp
如果在编译运行程序时, 提示缺少 cannot find -lGL 库报错, 可以按照下面方法解决:
在命令行执行: locate libGL.so //这一步是查看本地系统里有没有这个库
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 //如果提示这两行, 说明系统有这个库
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0
下面只需要做一个链接即可:
sudo ln -s /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 /usr/lib/libGL.so
如果系统里没有查找到库, 就在命令行敲下面命令进行在线安装:
sudo apt-get install libgl1-mesa-dev
三、代码设计
3.1 地图API调用
下面使用Qt的网络模块来发送HTTP请求,并使用Qt的GUI模块来显示地图图片。 需要在百度地图开放平台上注册应用程序,并获取到百度地图API密钥(AK)。
cpp
// mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QImage>
#include <QLabel>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void onMapImageReceived(QNetworkReply *reply);
private:
QLabel *mapLabel;
QNetworkAccessManager *networkManager;
};
#endif // MAINWINDOW_H
cppCopy Code// mainwindow.cpp
#include "mainwindow.h"
#include <QUrl>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
mapLabel = new QLabel(this);
mapLabel->setGeometry(10, 10, 600, 400); // 设置地图图片显示位置和大小
networkManager = new QNetworkAccessManager(this);
connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onMapImageReceived);
QString mapUrl = "http://api.map.baidu.com/staticimage/v2";
QUrl url(mapUrl);
url.addQueryItem("ak", "your_baidu_map_api_key"); // 替换为你的百度地图API密钥
url.addQueryItem("center", "北京"); // 地图中心位置
url.addQueryItem("width", "600"); // 图片宽度
url.addQueryItem("height", "400"); // 图片高度
url.addQueryItem("zoom", "11"); // 缩放级别
QNetworkRequest request(url);
networkManager->get(request);
}
MainWindow::~MainWindow()
{
}
void MainWindow::onMapImageReceived(QNetworkReply *reply)
{
if (reply->error() == QNetworkReply::NoError) {
QByteArray imageData = reply->readAll();
QImage mapImage;
mapImage.loadFromData(imageData);
mapLabel->setPixmap(QPixmap::fromImage(mapImage));
} else {
qDebug() << "Error: " << reply->errorString();
}
reply->deleteLater();
}
创建了一个MainWindow
类,其中包含一个用于显示地图图片的QLabel
和一个QNetworkAccessManager
用于发送HTTP请求。在构造函数中,通过QUrl
构建了百度地图API接口的URL,并添加了必要的参数,例如地图中心位置、图片大小和缩放级别。使用QNetworkRequest
发送了一个GET请求,并在onMapImageReceived
槽函数中处理收到的地图图片数据,并将其显示在QLabel
上。
3.2 导航提示音播放
使用alsa-lib库在Linux下调用声卡驱动来播放声音。
cpp
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <alsa/asoundlib.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[])
{
int err;
int fd;
snd_pcm_t *pcm_handle;
snd_pcm_hw_params_t *hw_params;
unsigned int rate = 44100;
unsigned int channels = 2;
unsigned int buffer_time = 500000; // 500ms
unsigned int period_time = 100000; // 100ms
snd_pcm_uframes_t buffer_size;
snd_pcm_uframes_t period_size;
char *buffer;
buffer = (char *)malloc(BUFFER_SIZE);
if (!buffer) {
printf("Error: Failed to allocate memory.\n");
return -1;
}
// 打开PCM设备
err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
printf("Error: Failed to open PCM device. %s\n", snd_strerror(err));
return -1;
}
// 配置PCM设备参数
snd_pcm_hw_params_alloca(&hw_params);
err = snd_pcm_hw_params_any(pcm_handle, hw_params);
if (err < 0) {
printf("Error: Failed to get PCM device parameters. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_access(pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err < 0) {
printf("Error: Failed to set PCM device access mode. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_format(pcm_handle, hw_params, SND_PCM_FORMAT_S16_LE);
if (err < 0) {
printf("Error: Failed to set PCM device sample format. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_channels(pcm_handle, hw_params, channels);
if (err < 0) {
printf("Error: Failed to set PCM device channel count. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_rate_near(pcm_handle, hw_params, &rate, 0);
if (err < 0) {
printf("Error: Failed to set PCM device sample rate. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hw_params, &buffer_time, 0);
if (err < 0) {
printf("Error: Failed to set PCM device buffer time. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params_set_period_time_near(pcm_handle, hw_params, &period_time, 0);
if (err < 0) {
printf("Error: Failed to set PCM device period time. %s\n", snd_strerror(err));
return -1;
}
err = snd_pcm_hw_params(pcm_handle, hw_params);
if (err < 0) {
printf("Error: Failed to set PCM device parameters. %s\n", snd_strerror(err));
return -1;
}
// 获取PCM设备缓冲区大小和周期大小
err = snd_pcm_get_params(pcm_handle, &buffer_size, &period_size);
if (err < 0) {
printf("Error: Failed to get PCM device buffer and period sizes. %s\n", snd_strerror(err));
return -1;
}
// 打开音频文件
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
printf("Error: Failed to open audio file.\n");
return -1;
}
// 播放音频
while (1) {
long frames = read(fd, buffer, BUFFER_SIZE);
if (frames == 0) { // 播放完成
break;
} else if (frames < 0) { // 读取错误
printf("Error: Failed to read audio data.\n");
break;
}
while (frames > 0) {
long n = snd_pcm_writei(pcm_handle, buffer, frames);
if (n < 0) { // 发生错误,重新配置PCM设备
printf("Error: Failed to write audio data to PCM device. %s\n", snd_strerror(n));
snd_pcm_prepare(pcm_handle);
} else {
frames -= n;
buffer += n * channels * 2; // 每个采样点为16位(2字节),乘以通道数
}
}
}
// 关闭PCM设备和音频文件
snd_pcm_close(pcm_handle);
close(fd);
free(buffer);
return 0;
}
使用alsa-lib库来调用Linux声卡驱动来播放声音。
(1)打开PCM设备并配置参数,然后通过snd_pcm_get_params
函数获取缓冲区大小和周期大小。
(2)打开音频文件并循环读取文件中的数据,每次将一定数量的数据写入PCM设备进行播放。在播放过程中,如果发生错误们需要重新配置PCM设备并重新开始播放。
3.3 GPS导航模块
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <libserialport.h>
void parse_gps_data(char *data) {
char *token;
token = strtok(data, ",");
int count = 0;
double latitude, longitude;
while (token != NULL) {
if (count == 2) { // 纬度数据在第3个字段
latitude = atof(token);
} else if (count == 4) { // 经度数据在第5个字段
longitude = atof(token);
}
token = strtok(NULL, ",");
count++;
}
printf("Latitude: %f, Longitude: %f\n", latitude, longitude);
}
int main() {
struct sp_port *port;
int err;
// 打开串口
err = sp_get_port_by_name("/dev/ttyUSB0", &port);
if (err != SP_OK) {
fprintf(stderr, "Error: Failed to open serial port\n");
return -1;
}
err = sp_open(port, SP_MODE_READ);
if (err != SP_OK) {
fprintf(stderr, "Error: Failed to open serial port for reading\n");
sp_free_port(port);
return -1;
}
// 设置串口参数
struct sp_port_config *config;
sp_new_config(&config);
sp_set_config_baudrate(config, 9600);
sp_set_config_bits(config, 8);
sp_set_config_parity(config, SP_PARITY_NONE);
sp_set_config_stopbits(config, 1);
sp_set_config(port, config);
// 读取GPS数据
char data[256];
int bytes_read;
while (1) {
bytes_read = sp_input_waiting(port);
if (bytes_read > 0) {
sp_blocking_read(port, data, sizeof(data), 0);
parse_gps_data(data);
}
usleep(100000); // 延时100ms
}
// 关闭串口
sp_close(port);
sp_free_port(port);
return 0;
}
四、总结
随着智能化和移动互联网技术的飞速发展,车载导航定位系统已经成为现代驾驶不可或缺的一部分。本项目通过集成高性能的GEC6818开发板、北斗GPS模块以及百度地图API,成功设计并实现了一个功能全面、性能稳定的车载导航定位系统。
在项目实施过程中,注重用户体验和系统稳定性,通过Qt开发框架打造了直观易用的操作界面,并实现了实时定位、地图显示、路线规划、导航指引以及语音提示等核心功能。同时,系统的模块化设计和开放式架构保证了其易于维护和扩展,能够随时适应市场和用户需求的变化。
通过本项目的实施,不仅提升了车载导航系统的技术水平,也为用户提供了更加便捷、智能的出行体验。