基于嵌入式的车载导航定位系统设计

一、前言

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开发框架打造了直观易用的操作界面,并实现了实时定位、地图显示、路线规划、导航指引以及语音提示等核心功能。同时,系统的模块化设计和开放式架构保证了其易于维护和扩展,能够随时适应市场和用户需求的变化。

通过本项目的实施,不仅提升了车载导航系统的技术水平,也为用户提供了更加便捷、智能的出行体验。

相关推荐
山山而川粤1 小时前
母婴用品系统|Java|SSM|JSP|
java·开发语言·后端·学习·mysql
玉红7774 小时前
R语言的数据类型
开发语言·后端·golang
lvbu_2024war015 小时前
MATLAB语言的网络编程
开发语言·后端·golang
问道飞鱼5 小时前
【Springboot知识】Springboot进阶-实现CAS完整流程
java·spring boot·后端·cas
Q_19284999065 小时前
基于Spring Boot的电影网站系统
java·spring boot·后端
豌豆花下猫5 小时前
Python 潮流周刊#83:uv 的使用技巧(摘要)
后端·python·ai
凡人的AI工具箱5 小时前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
SomeB1oody6 小时前
【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
开发语言·后端·rust
SomeB1oody6 小时前
【Rust自学】7.3. 路径(Path)Pt.2:访问父级模块、pub关键字在结构体和枚举类型上的使用
开发语言·后端·rust
Bony-6 小时前
Go语言反射从入门到进阶
开发语言·后端·golang