一、前言
1.1 項目介紹
【1】項目背景
隨著汽車工業(yè)的飛速發(fā)展和智能化技術(shù)的不斷突破,車載導(dǎo)航系統(tǒng)作為現(xiàn)代汽車不可或缺的一部分,在人們的日常生活中扮演著越來越重要的角色。它不僅能夠提供精確的路線導(dǎo)航,還能提供豐富的地理信息和娛樂服務(wù),為駕駛者帶來了極大的便利和樂趣。
傳統(tǒng)的車載導(dǎo)航系統(tǒng)主要依賴于內(nèi)置的地圖數(shù)據(jù)和GPS定位技術(shù),但隨著移動互聯(lián)網(wǎng)的普及和智能設(shè)備的快速發(fā)展,用戶對車載導(dǎo)航系統(tǒng)的要求也在不斷提高。希望車載導(dǎo)航系統(tǒng)能夠具備更高的定位精度、更豐富的地圖信息、更便捷的操作體驗以及更強的可擴展性。
開發(fā)一款基于嵌入式技術(shù)的車載導(dǎo)航定位系統(tǒng),以滿足現(xiàn)代用戶對高效、智能、個性化導(dǎo)航服務(wù)的需求,成為了當(dāng)前行業(yè)發(fā)展的一個重要方向。本項目就是通過集成高性能的主控開發(fā)板、精準(zhǔn)的GPS定位模塊以及強大的Qt開發(fā)框架,實現(xiàn)一個功能豐富、性能穩(wěn)定、用戶體驗優(yōu)越的車載導(dǎo)航系統(tǒng)。
【2】設(shè)計實現(xiàn)的功能
(1)實時定位與地圖顯示:通過外接的北斗GPS模塊,系統(tǒng)能夠?qū)崟r接收并解析衛(wèi)星信號,獲取車輛的精確位置信息。這些信息將實時顯示在基于Qt開發(fā)的主界面上,與百度地圖API無縫對接,為用戶呈現(xiàn)清晰、準(zhǔn)確的地圖畫面。
(2)路線規(guī)劃與導(dǎo)航:用戶可以通過主界面輸入目的地信息,系統(tǒng)根據(jù)百度地圖API提供的路徑規(guī)劃服務(wù),計算出最優(yōu)的行駛路線,并在地圖上進(jìn)行高亮顯示。在導(dǎo)航過程中,系統(tǒng)能夠?qū)崟r追蹤車輛位置,提供轉(zhuǎn)向、距離等導(dǎo)航指令,確保用戶能夠準(zhǔn)確、快速地到達(dá)目的地。
(3)地圖預(yù)覽與縮放:系統(tǒng)支持地圖的縮放和拖動功能,用戶可以根據(jù)需要調(diào)整地圖的顯示范圍,查看不同級別的地理細(xì)節(jié)。同時,系統(tǒng)還提供了多種地圖視圖模式(如白天模式、夜間模式等),以滿足用戶在不同場景下的使用需求。
(4)語音提示與交互:為了提升用戶體驗,系統(tǒng)集成了語音提示功能,能夠在關(guān)鍵導(dǎo)航節(jié)點(如轉(zhuǎn)彎、路口等)給予用戶語音指令,減少用戶操作干擾。此外,系統(tǒng)還支持通過語音指令進(jìn)行簡單的交互操作,如查詢附近的餐飲、加油站等設(shè)施。
(5)個性化設(shè)置與偏好管理:用戶可以根據(jù)自己的使用習(xí)慣,在系統(tǒng)設(shè)置中調(diào)整界面風(fēng)格、導(dǎo)航偏好等參數(shù)。系統(tǒng)還會記錄用戶的行駛歷史,為用戶提供個性化的推薦和服務(wù)。
(6)系統(tǒng)穩(wěn)定性與擴展性:基于嵌入式Linux系統(tǒng)的開發(fā)框架,保證了系統(tǒng)的穩(wěn)定性和可靠性。同時,開放式的架構(gòu)設(shè)計使得系統(tǒng)易于擴展和升級,能夠隨時集成新的功能模塊和服務(wù),滿足用戶不斷增長的需求。
本項目設(shè)計的基于嵌入式的車載導(dǎo)航定位系統(tǒng),通過集成高性能硬件和先進(jìn)的軟件開發(fā)技術(shù),實現(xiàn)了實時定位、路線規(guī)劃、地圖預(yù)覽、語音提示、個性化設(shè)置等多項功能,為用戶提供了高效、智能、個性化的導(dǎo)航服務(wù)體驗。
【3】項目硬件模塊組成
(1)主控開發(fā)板:采用GEC6818開發(fā)板,該開發(fā)板搭載了三星Cortex-A53系列高性能八核處理器S5P6818,最高主頻高達(dá)1.4GHz。主控開發(fā)板作為整個系統(tǒng)的核心,負(fù)責(zé)處理導(dǎo)航定位系統(tǒng)的所有運算和控制任務(wù),確保系統(tǒng)的穩(wěn)定運行。
(2)GPS模塊:采用北斗GPS模塊,該模塊負(fù)責(zé)接收并解析衛(wèi)星信號,獲取車輛的精確位置信息。通過與主控開發(fā)板的連接,將位置數(shù)據(jù)實時傳輸給系統(tǒng)進(jìn)行處理和顯示。
(3)顯示屏:用于呈現(xiàn)地圖、導(dǎo)航指令以及其他相關(guān)信息。顯示屏與主控開發(fā)板相連,通過Qt開發(fā)的界面,將系統(tǒng)的各項功能直觀地展示給用戶。
(4)網(wǎng)卡: 用于上網(wǎng),調(diào)用百度地圖,這是開發(fā)板本身自帶。
(5)語音播報模塊: 利用開發(fā)板本身的聲卡播放導(dǎo)航提示。
1.2 設(shè)計思路
(1)需求分析:對車載導(dǎo)航定位系統(tǒng)的需求進(jìn)行深入分析。確定系統(tǒng)需要具備的功能,如實時定位、路線規(guī)劃、地圖顯示、語音提示等。同時,考慮到用戶的操作習(xí)慣和駕駛過程中的安全性,對界面的設(shè)計、交互的流暢性等方面也進(jìn)行了充分考慮。
(2)硬件選型:根據(jù)需求分析的結(jié)果,選擇適合的硬件組件。主控開發(fā)板選用GEC6818開發(fā)板,其高性能的處理器和嵌入式Linux系統(tǒng)為系統(tǒng)的穩(wěn)定運行提供了有力支持。GPS模塊選用北斗GPS模塊,以確保定位的準(zhǔn)確性和穩(wěn)定性。同時,選擇高質(zhì)量的顯示屏和其他輔助模塊,以滿足系統(tǒng)的各項需求。
(3)軟件架構(gòu)設(shè)計:采用Qt作為軟件開發(fā)框架,利用其強大的圖形界面開發(fā)能力和跨平臺特性,實現(xiàn)系統(tǒng)的主界面和各項功能。通過集成百度地圖API,實現(xiàn)地圖的加載、顯示和路徑規(guī)劃等功能。同時,設(shè)計合理的軟件架構(gòu),確保各個模塊之間的協(xié)同工作和數(shù)據(jù)傳輸的高效性。
(4)功能模塊劃分:將系統(tǒng)劃分為多個功能模塊,如定位模塊、導(dǎo)航模塊、地圖顯示模塊、語音提示模塊等。每個模塊負(fù)責(zé)實現(xiàn)特定的功能,并通過接口與其他模塊進(jìn)行交互。這種模塊化的設(shè)計方式便于后期的維護(hù)和擴展。
1.3 系統(tǒng)功能總結(jié)
功能模塊 | 功能描述 | 技術(shù)實現(xiàn)與特點 |
---|---|---|
實時定位 | 通過北斗GPS模塊獲取車輛精確位置信息。 | 利用北斗衛(wèi)星導(dǎo)航系統(tǒng),提供高精度、穩(wěn)定的定位服務(wù)。 |
地圖顯示 | 在顯示屏上呈現(xiàn)百度地圖,展示地理信息。 | 集成百度地圖API,實現(xiàn)地圖的加載、縮放、拖動等功能。 |
路線規(guī)劃 | 根據(jù)用戶輸入的目的地,計算最優(yōu)行駛路線。 | 利用百度地圖API的路徑規(guī)劃服務(wù),提供多種路線選擇。 |
導(dǎo)航指引 | 提供轉(zhuǎn)向、距離等導(dǎo)航指令,輔助用戶駕駛。 | 實時追蹤車輛位置,根據(jù)規(guī)劃路線提供準(zhǔn)確的導(dǎo)航指引。 |
語音提示 | 通過語音輸出導(dǎo)航指令和其他相關(guān)信息。 | 集成語音合成技術(shù),實現(xiàn)人性化的交互體驗。 |
地圖預(yù)覽與縮放 | 支持地圖的預(yù)覽、縮放和拖動操作。 | 提供多種地圖視圖模式,滿足不同場景下的使用需求。 |
個性化設(shè)置 | 用戶可根據(jù)喜好設(shè)置系統(tǒng)界面和導(dǎo)航偏好。 | 提供豐富的設(shè)置選項,滿足用戶的個性化需求。 |
系統(tǒng)穩(wěn)定性 | 確保系統(tǒng)在各種環(huán)境下的穩(wěn)定運行。 | 基于嵌入式Linux系統(tǒng)開發(fā),具備高度的穩(wěn)定性和可靠性。 |
擴展性 | 系統(tǒng)設(shè)計易于擴展和升級,適應(yīng)未來需求變化。 | 開放的架構(gòu)設(shè)計,支持新功能模塊和服務(wù)的集成。 |
1.4 原理圖
二、Linux下Qt開發(fā)環(huán)境搭建
養(yǎng)老院出行管理系統(tǒng)項目是在Linux下開發(fā),接下來需要搭建Linux下的開發(fā)環(huán)境。
(1)第一步,安裝VM虛擬機
(2)第二步,在VM虛擬機里安裝Ubuntu18.04系統(tǒng)
(3)第三步,在Ubuntu18.04系統(tǒng)里安裝QT開發(fā)環(huán)境
2.1 安裝VMware虛擬機軟件
VMware軟件下載地址: https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html
當(dāng)前電腦使用的vmware版本為: 15.5
2.2 安裝Ubuntu18.04系統(tǒng)
18.04最新長期支持版本: http://mirrors.aliyun.com/ubuntu-releases/18.04/
2.3 安裝Qt5.12開發(fā)環(huán)境
注意,安裝Qt之前要先安裝以下工具(如果之前安裝了就不用再安裝了):
sudo apt install make
sudo apt install gcc
sudo apt install g++
Qt安裝包下載地址:http://download.qt.io/archive/qt/5.12/5.12.6/
2.4 Qt編譯常見問題解決
如果在編譯運行程序時, 提示缺少 cannot find -lGL 庫報錯, 可以按照下面方法解決:
在命令行執(zhí)行: locate libGL.so //這一步是查看本地系統(tǒng)里有沒有這個庫
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1 //如果提示這兩行, 說明系統(tǒng)有這個庫
/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
如果系統(tǒng)里沒有查找到庫, 就在命令行敲下面命令進(jìn)行在線安裝:
sudo apt-get install libgl1-mesa-dev
三、代碼設(shè)計
3.1 地圖API調(diào)用
下面使用Qt的網(wǎng)絡(luò)模塊來發(fā)送HTTP請求,并使用Qt的GUI模塊來顯示地圖圖片。 需要在百度地圖開放平臺上注冊應(yīng)用程序,并獲取到百度地圖API密鑰(AK)。
// 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); // 設(shè)置地圖圖片顯示位置和大小
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();
}
創(chuàng)建了一個MainWindow
類,其中包含一個用于顯示地圖圖片的QLabel
和一個QNetworkAccessManager
用于發(fā)送HTTP請求。在構(gòu)造函數(shù)中,通過QUrl
構(gòu)建了百度地圖API接口的URL,并添加了必要的參數(shù),例如地圖中心位置、圖片大小和縮放級別。使用QNetworkRequest
發(fā)送了一個GET請求,并在onMapImageReceived
槽函數(shù)中處理收到的地圖圖片數(shù)據(jù),并將其顯示在QLabel
上。
3.2 導(dǎo)航提示音播放
使用alsa-lib庫在Linux下調(diào)用聲卡驅(qū)動來播放聲音。
#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設(shè)備
err = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
printf("Error: Failed to open PCM device. %sn", snd_strerror(err));
return -1;
}
// 配置PCM設(shè)備參數(shù)
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. %sn", 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. %sn", 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. %sn", 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. %sn", 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. %sn", 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. %sn", 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. %sn", 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. %sn", snd_strerror(err));
return -1;
}
// 獲取PCM設(shè)備緩沖區(qū)大小和周期大小
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. %sn", 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) { // 發(fā)生錯誤,重新配置PCM設(shè)備
printf("Error: Failed to write audio data to PCM device. %sn", snd_strerror(n));
snd_pcm_prepare(pcm_handle);
} else {
frames -= n;
buffer += n * channels * 2; // 每個采樣點為16位(2字節(jié)),乘以通道數(shù)
}
}
}
// 關(guān)閉PCM設(shè)備和音頻文件
snd_pcm_close(pcm_handle);
close(fd);
free(buffer);
return 0;
}
使用alsa-lib庫來調(diào)用Linux聲卡驅(qū)動來播放聲音。
(1)打開PCM設(shè)備并配置參數(shù),然后通過snd_pcm_get_params
函數(shù)獲取緩沖區(qū)大小和周期大小。
(2)打開音頻文件并循環(huán)讀取文件中的數(shù)據(jù),每次將一定數(shù)量的數(shù)據(jù)寫入PCM設(shè)備進(jìn)行播放。在播放過程中,如果發(fā)生錯誤們需要重新配置PCM設(shè)備并重新開始播放。
3.3 GPS導(dǎo)航模塊
#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) { // 緯度數(shù)據(jù)在第3個字段
latitude = atof(token);
} else if (count == 4) { // 經(jīng)度數(shù)據(jù)在第5個字段
longitude = atof(token);
}
token = strtok(NULL, ",");
count++;
}
printf("Latitude: %f, Longitude: %fn", 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 portn");
return -1;
}
err = sp_open(port, SP_MODE_READ);
if (err != SP_OK) {
fprintf(stderr, "Error: Failed to open serial port for readingn");
sp_free_port(port);
return -1;
}
// 設(shè)置串口參數(shù)
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數(shù)據(jù)
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
}
// 關(guān)閉串口
sp_close(port);
sp_free_port(port);
return 0;
}
四、總結(jié)
隨著智能化和移動互聯(lián)網(wǎng)技術(shù)的飛速發(fā)展,車載導(dǎo)航定位系統(tǒng)已經(jīng)成為現(xiàn)代駕駛不可或缺的一部分。本項目通過集成高性能的GEC6818開發(fā)板、北斗GPS模塊以及百度地圖API,成功設(shè)計并實現(xiàn)了一個功能全面、性能穩(wěn)定的車載導(dǎo)航定位系統(tǒng)。
在項目實施過程中,注重用戶體驗和系統(tǒng)穩(wěn)定性,通過Qt開發(fā)框架打造了直觀易用的操作界面,并實現(xiàn)了實時定位、地圖顯示、路線規(guī)劃、導(dǎo)航指引以及語音提示等核心功能。同時,系統(tǒng)的模塊化設(shè)計和開放式架構(gòu)保證了其易于維護(hù)和擴展,能夠隨時適應(yīng)市場和用戶需求的變化。
通過本項目的實施,不僅提升了車載導(dǎo)航系統(tǒng)的技術(shù)水平,也為用戶提供了更加便捷、智能的出行體驗。