原创 高德导航、路径规划运用在单片机及APP上,快速开发导航应用项目

2024-10-28 08:20 427 0 分类: MCU/ 嵌入式 文集: 教程
前言
(一)在当今这个瞬息万变的数字化时代,导航技术已经深入到我们生活的方方面面,从日常出行到物流配送,再到应急救援,无不彰显其重要性。
随着智能手机和物联网技术的飞速发展,对于导航系统的需求不再仅仅局限于简单的路线指引,而是更加追求精准性、实时性和智能化。在此背景下,将高德导航的路径规划算法高效应用于单片机系统及移动APP中,不仅是对传统导航技术的一次革新,更是推动智慧城市、智能交通系统建设的关键一环。

(二)单片机,作为嵌入式系统的核心,凭借其体积小、功耗低、集成度高等特点,在车载设备、智能家居、工业自动化等领域发挥着不可替代的作用。
将高德导航的路径规划功能集成到单片机上,意味着可以实现更为紧凑、低功耗的导航解决方案,为车辆自主导航、无人机路径规划等应用场景提供强有力的技术支持。这不仅要求算法在保持高精度的同时,还需进行深度优化以适应单片机有限的计算资源和存储能力。

(三)所以本文将给大家分享一下,我将高德开放平台的导航、路径规划功能运用到单片机及APP上,从而可以快速开发导航类、规划类的项目。当然方法有非常多种,我本次分享的仅仅是高德的冰山一角,高德提供的API,甚至可以让单片机不需要APP支持,独立运行导航、路径规划等项目

本文末尾,有项目所有代码的下载地址

效果展示
(一)APP展示
由于是快速开发,所以没有任何美化,仅是实现功能。APP开发平台:App Inventor
图:设定目的地后,会自动规划最近的路线,然后实时定位导航

(二)单片机展示
单片机:ESP32
图:APP开始导航后,将导航信息发送到ESP32


项目大纲
APP设定目的地→→地理编码API→→APP定位经纬度→→坐标转换API→→路径规划API→→APP显示静态图→→提交单片机显示
为了不泄露信息,最好对高德API进行封装,然后通过自己的API来操作。同时APP和单片机的通信也用到API。http://api.xemowo.top

(一)获取高德开放平台API
①路径规划API:https://lbs.amap.com/api/webservice/guide/api/direction
对步行、公交路径规划,返回从原地到目的地的信息(方向,距离,时间,步行指示等)

②地理编码API:https://lbs.amap.com/api/webservice/guide/api/georegeo
将地址信息,转化为经纬度等信息。如:中山市港口镇政府,返回信息:"location" :"113.384324,22.584733"

③坐标转换API:https://lbs.amap.com/api/webservice/guide/api/convert
将用户输入的非高德坐标(GPS 坐标、mapbar 坐标、baidu 坐标)转换成高德坐标。

④静态地图:https://lbs.amap.com/api/webservice/guide/api/staticmaps
项目可以不用静态地图,因为路径规划API也会返回带有标记的静态图

(二)封装API(因人而异,后面我会放出PHP源码)
①地址查询经纬度:http://api.xemowo.top/api/gaode/chaxun.php
文档:http://api.xemowo.top/api/chaxun.html

②坐标转换:http://api.xemowo.top/api/gaode/gps.php
文档:http://api.xemowo.top/api/GPS.html

③路径规划:http://api.xemowo.top/api/gaode/walk.php
文档:http://api.xemowo.top/api/walk.html

④单片机接收信息:http://api.xemowo.top/api/gaode/esp_walk.php
文档:http://api.xemowo.top/api/esp_walk.html

(三)制作APP
App Inventor,Android编程工具https://www.17coding.net/
采用图形化积木式的拖放组件,完全在线开发的Android编程环境,无需复杂的软件安装,可以通过浏览器直接访问并进行编程。

(四)单片机编程
Arduino IDE,内置很多库函数,对编程极其方便,速成项目,并且资料很多,对初学者帮助非常大


高德API
(一)注册高德开放平台的账号https://lbs.amap.com/

(二)应用管理----创建新应用

(三)添加key,选择web服务(请勿泄露key)
(四)寻找所需的API,本期项目我们需要4个高德API
注意个人用户调用的限量,企业用户会多一些,超过限量可能被禁止使用
①路径规划API:https://lbs.amap.com/api/webservice/guide/api/direction
对步行、公交路径规划,返回从原地到目的地的信息(方向,距离,时间,步行指示等)

②地理编码API:https://lbs.amap.com/api/webservice/guide/api/georegeo
将地址信息,转化为经纬度等信息。如:中山市港口镇政府,返回信息:"location" :"113.384324,22.584733"

③坐标转换API:https://lbs.amap.com/api/webservice/guide/api/convert
将用户输入的非高德坐标(GPS 坐标、mapbar 坐标、baidu 坐标)转换成高德坐标。

④静态地图:https://lbs.amap.com/api/webservice/guide/api/staticmaps
项目可以不用静态地图,因为路径规划API也会返回带有标记的静态图


制作API
搭建API(网站)需要一台服务器,并且需要开发环境
我这里的环境如下:
系统:Orange Pi 1.0.2 Jammy (aarch64)
WEB平台:OpenResty
PHP:PHP-72
域名:API.XEMOWO.TOP

(一)坐标转换API (http://api.xemowo.top/api/GPS.html)
示例:http://api.xemowo.top/api/gaode/gps.php?gps=113.38472,22.59476&photo=0
php
error_reporting(0);//屏蔽报错

$photo=$_GET["photo"];

$gps=$_GET["gps"];
if($gps==""){exit("GPS地址为空");}

$apiKey = 'xxxxxxxxxxxxxxxxxxx';  //高德API密钥

$html = file_get_contents("https://restapi.amap.com/v3/assistant/coordinate/convert?locations=".$gps."&coordsys=gps&output=json&key=".$apiKey."");  //高德坐标转换

$arr = json_decode($html, true);    // 将获取到的 JSON 数据解析成数组

$status = $arr["status"];
$info = $arr["info"];
$infocode = $arr["infocode"];
$locations = $arr["locations"];

//https://restapi.amap.com/v3/staticmap?location=".$gps."&zoom=15&size=400*400&markers=mid,,A:".$gps."&key=".$apiKey."

if($photo == 1)
{
  
// 构建图片URL  
$gps=$_GET["gps"];
if($gps==""){exit("GPS地址为空");}
  $apiKey = 'xxxxxxxxxxxxxxxxxxx';  
$ip = $location; $savePath = 'gps_map.png'; // 例如 'images/map.png' $imageUrl = "https://restapi.amap.com/v3/staticmap?location=".$locations."&zoom=15&size=400*400&markers=mid,,A:".$locations."&key=".$apiKey.""; // 使用file_get_contents获取图片内容 $imageContent = file_get_contents($imageUrl); // 使用file_put_contents将图片内容保存到文件 $saveResult = file_put_contents($savePath, $imageContent); $map = file_get_contents("http://api.xemowo.top/api/gaode/gps_map.png"); //保存图片 // 将图像数据转换为 Base64 编码 $base64 = base64_encode($map); // 嵌入到 img 标签中 echo ''" width="400" height="400" />'; //给图片加上base64,让图片刷新 exit(); } $data = array( 'status' => $status, 'info' => $info, 'infocode' => $infocode, 'locations' => $locations, ); echo json_encode($data, JSON_UNESCAPED_UNICODE); exit();

file_get_contents函数读取API信息,json_decode函数将获取的API转成JSON,然后获取JSON的信息保存在变量内

如果photo=1时,则网页返回图片,图片地址在http://api.xemowo.top/api/gaode/gps_map.png
构建图片采用高德静态图的API:https://lbs.amap.com/api/webservice/guide/api/staticmaps
注意,末尾的echo输出,一定要用到base64编码,否则在输出时,图片可能没有变化

(二)地址查询经纬度 (http://api.xemowo.top/api/chaxun.html)
示例:http://api.xemowo.top/api/gaode/chaxun.php?address=广东省珠海市香洲区中山大学&photo=0
php
error_reporting(0);//屏蔽报错

$photo=$_GET["photo"];
$address=$_GET["address"];

$apiKey = 'xxxxxxxxxxxxxxx';  



if($address==""){exit("地址为空");}

$html = file_get_contents("https://restapi.amap.com/v3/geocode/geo?address=".$address."&output=json&key=".$apiKey."");

$arr = json_decode($html, true);    // 将获取到的 JSON 数据解析成数组


$formatted_address = $arr["geocodes"][0]["formatted_address"];
$location = $arr["geocodes"][0]["location"];
$level = $arr["geocodes"][0]["level"];

$data = array(
'level' => $level,
'formatted_address' => $formatted_address,
'location' => $location,
);



  

if($photo == 1)
{
// 构建图片URL  
$ip = $location;
$savePath = 'chakan_map.png'; // 例如 'images/map.png'  

$apiKey = 'xxxxxxxxxxxxxxx';  
$imageUrl = "https://restapi.amap.com/v3/staticmap?location=".$location."&zoom=15&size=400*400&markers=mid,,A:".$location."&key=".$apiKey.""; // 使用file_get_contents获取图片内容 $imageContent = file_get_contents($imageUrl); // 使用file_put_contents将图片内容保存到文件 $saveResult = file_put_contents($savePath, $imageContent); $map = file_get_contents("http://api.xemowo.top/api/gaode/chakan_map.png"); // 将图像数据转换为 Base64 编码 $base64 = base64_encode($map); // 嵌入到 img 标签中 echo ''" width="400" height="400" />'; exit(); } echo json_encode($data, JSON_UNESCAPED_UNICODE); exit();

地址查询和坐标转换的JSON解析数据差不多,但是注意3项数据都在geocodes下,所以JSON取值在["geocodes"][0]

如果photo=1时,则网页返回图片,图片地址在http://api.xemowo.top/api/gaode/chakan_map.png
构建图片采用高德静态图的API:https://lbs.amap.com/api/webservice/guide/api/staticmaps
注意,末尾的echo输出,一定要用到base64编码,否则在输出时,图片可能没有变化

(三)路径规划 (http://api.xemowo.top/api/walk.html)
示例:http://api.xemowo.top/api/gaode/walk.php?origin=113.388247,22.589615&destination=113.388317,22.587233&mark=1&photo=0
php
error_reporting(0);//屏蔽报错
$photo=$_GET["photo"];
$oled=$_GET["oled"];
$all=$_GET["all"];
$esp32=$_GET["esp32"];
$mark = $_GET["mark"];

if($esp32 == 1)
{
  if (file_exists($filename)) {  
    // 读取文件内容  
    $content = file_get_contents($filename);  
    $aa = mb_substr("".$instruction."",0,10,'utf-8');
    $bb = mb_substr("".$instruction."",10,10,'utf-8');
    $cc = mb_substr("".$instruction."",20,10,'utf-8');
    $dd = mb_substr("".$instruction."",30,10,'utf-8');

$data = array(

    'content' => $content,
    'oled_a' => $aa,
    'oled_b' => $bb,
    'oled_c' => $cc,
    'oled_d' => $dd,
  
       );
  
  
  echo json_encode($data, JSON_UNESCAPED_UNICODE);
 
    exit();
  }
  
}

$origin=$_GET["origin"];
if($origin==""){exit("起点origin地址为空");}

$destination=$_GET["destination"];
if($destination==""){exit("目的地destination地址为空");}

$apiKey = 'xxxxxxxxxxxxxxx';  

if($all == 1)
{
$html = file_get_contents("https://restapi.amap.com/v3/direction/walking?origin=".$origin."&destination=".$destination."&key=".$apiKey."");

echo $html;
exit();
}

$html = file_get_contents("https://restapi.amap.com/v3/direction/walking?origin=".$origin."&destination=".$destination."&key=".$apiKey."");
$arr = json_decode($html, true);    // 将获取到的 JSON 数据解析成数组

$distance = $arr["route"]["paths"][0]["distance"];//步行距离
$duration = $arr["route"]["paths"][0]["duration"];//步行预计
$instruction = $arr["route"]["paths"][0]["steps"][0]["instruction"];//路段步行指示
$orientation = $arr["route"]["paths"][0]["steps"][0]["orientation"];//方向
$polyline = $arr["route"]["paths"][0]["steps"][0]["polyline"];//坐标点

if($mark == 1)
{

// 定义文件名  
$filename = "walk.txt";  
  
// 使用文件写入模式打开文件。如果文件不存在,会自动创建  
$file = fopen($filename, "w");  
  
// 检查文件是否成功打开  
if ($file) {  
    // 将文本写入文件  
    fwrite($file, $instruction);  
      
    // 关闭文件  
    fclose($file);  

}  

}







if($photo == 1)
{
  
// 构建图片URL  
  $apiKey = 'xxxxxxxxxxxx';  
  $ip = $location;
  $savePath = 'walk_map.png';  
$imageUrl = "https://restapi.amap.com/v3/staticmap?zoom=16&size=400*400&paths=10,0x0000ff,1,,:".$polyline."&key=".$apiKey."";  

// 使用file_get_contents获取图片内容  
$imageContent = file_get_contents($imageUrl);  
// 使用file_put_contents将图片内容保存到文件  
$saveResult = file_put_contents($savePath, $imageContent);  

$map = file_get_contents("http://api.xemowo.top/api/gaode/walk_map.png");  
  
// 将图像数据转换为 Base64 编码  
$base64 = base64_encode($map);  
  
// 嵌入到 img 标签中  
echo ''" width="400" height="400" />';
               exit();
}


//适配oled
if($oled == 1)
{
    $aa = mb_substr("".$instruction."",0,10,'utf-8');
    $bb = mb_substr("".$instruction."",10,10,'utf-8');
    $cc = mb_substr("".$instruction."",20,10,'utf-8');
    $dd = mb_substr("".$instruction."",30,10,'utf-8');

$data = array(
    'distance' => $distance,
    'duration' => $duration,
    'instruction' => $instruction,
    'orientation' => $orientation,
    'polyline' => $polyline,

    'oled_a' => $aa,
    'oled_b' => $bb,
    'oled_c' => $cc,
    'oled_d' => $dd,

     );


echo json_encode($data, JSON_UNESCAPED_UNICODE);

  exit();
  
}else{


$data = array(
    'distance' => $distance,
    'duration' => $duration,
    'instruction' => $instruction,
    'orientation' => $orientation,
    'polyline' => $polyline,


     );


echo json_encode($data, JSON_UNESCAPED_UNICODE);

  exit();


}

此段为测试适配屏幕的代码,用在单片机显示上,在walk_esp的api上

all=1会返回所有高德api的数据,用于测试

如果使用单片机,或者搭配walk_esp使用的话,就需要让make=1,将数据写入到walk.txt文本中

(四)单片机数据 (http://api.xemowo.top/api/esp_walk.html)
示例:http://api.xemowo.top/api/gaode/esp_walk.php?esp32=1
"esp32"];
$mark = $_GET["mark"];
$filename = "walk.txt";  
if($esp32 == 1)
{
  if (file_exists($filename)) {  
    // 读取文件内容  
    $content = file_get_contents($filename);  
    $aa = mb_substr("".$content."",0,10,'utf-8');
    $bb = mb_substr("".$content."",10,10,'utf-8');
    $cc = mb_substr("".$content."",20,10,'utf-8');
    $dd = mb_substr("".$content."",30,10,'utf-8');

$data = array(

    'content' => $content,
    'oled_a' => $aa,
    'oled_b' => $bb,
    'oled_c' => $cc,
    'oled_d' => $dd,
  
       );
  
  
  echo json_encode($data, JSON_UNESCAPED_UNICODE);
 
    exit();
  }
  
}

此单片机API,需要walk.php的make=1,然后读取walk写入到wake.txt的内容
并且将数据转换成0.96OLED屏幕适配的数据,oled_a代表屏幕第一行,以此类推


制作APP
如果要速成一个APP,快速实现功能,那么我推荐用app Inventor,使用拖拽式、搭积木式编程,对没开发过APP的师傅,就非常合适
目前app Inventor有几个版本,官方版http://code.appinventor.mit.edu,社区版http://ai2.17coding.net/?locale=zh_CN,各种私人版本(收费)
所以我们用社区版就够了,可以实现大多数功能http://ai2.17coding.net/?locale=zh_CN

(一)做项目前,注意,每做一步大的步骤,就必须导出项目保存,因为内置的保存项目关闭浏览器后就没了!!!
然后继续做的时候,再导入项目,文件名不要中文

(二)建议下载调试软件----AI伴侣
下载地址:https://wwmg.lanzouj.com/iopRp2dlfrih

(三)拖拽组件
按照我的组件列表添加组件,并且按照自己喜欢的位置放置组件

(四)编写程序
①先读取输入框的内容,并且用地址查询经纬度API来将输入的地址转为经纬度信息

②APP读取手机的位置信息,将手机GPS信息转化为高德经纬度信息

③当地址查询经纬度和GPS信息都完成后,汇总一起到路径规划API内,然后访问路径规划API
顺便返回路径规划图,photo=1
此时web浏览款会实时显示导航信息,当手机定位发生变化时,就会改变地图

④软件使用示例


单片机接收导航信息
我这里使用ESP32,因为ESP32具有wifi功能,而且内存和性能也足够强大,可以完全加载中文库,很方便的显示中文路径信息
代码平台使用Arduino IDE,可以直接调用所需的库文件,用少量的代码就能完美的实现功能
屏幕使用0.96OLED,可以显示中文信息,而且API已经适配了此屏幕,显示更加完美

#include //wifi库
#include //json解析库
#include //http连接库
#include 

#include //u8g2oled库
#include 

#define BOARD_I2C_SCL   22
#define BOARD_I2C_SDA   21   
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ BOARD_I2C_SCL, /* data=*/ BOARD_I2C_SDA, /* reset=*/ U8X8_PIN_NONE);   // All Boards without Reset of the Display

const char * ID = "XEMOWO_PC";//wifi账号
const char * PASSWORD = "1SUNjiajun";//wifi密码

const char*  one;//api第一行内容
const char*  two;//api第二行内容
const char*  three;//api第三行内容
const char*  four;//api第四行内容

String API = "";
String url_xinzhi = "";
String WeatherURL = "";


HTTPClient http;
String GitURL(String api)
{
  url_xinzhi =  "http://api.xemowo.top/api/gaode/esp_walk.php?esp32=1";//oled=1则表示使用oled专属格式
  return url_xinzhi;
}



void ParseWeather(String url)
{  
  
  http.begin(url);
 
  int httpGet = http.GET();
  if(httpGet > 0)
  {
    Serial.printf("HTTPGET is %d",httpGet);
    
    if(httpGet == HTTP_CODE_OK)
    {
      StaticJsonDocument<500> doc;    
      

      String json = http.getString();
      Serial.println("解析");
      Serial.println(json);
        
      deserializeJson(doc, json);
     one = doc["oled_a"]; // "人生就是一列开往坟墓"
     two = doc["oled_b"]; // "的列车,路途上会有很"
     three = doc["oled_c"]; // "多站,很难有人可以至"
     four = doc["oled_d"]; // "始至终陪着走完。\n"
      
    }
    else
    {
      Serial.printf("ERROR1!!");
       ParseWeather(WeatherURL);
    }
  }
  else
  {
    Serial.printf("ERROR2!!");


     ParseWeather(WeatherURL);

  }
  http.end();
}






void setup() {
  // put your setup code here, to run once:
  u8g2.setFont( u8g2_font_wqy12_t_gb2312 );//设置为中文字体
  u8g2.begin();
  u8g2.enableUTF8Print();

  Serial.begin(115200);
  Serial.println("Init u8g2 ....");
  Serial.println("WiFi:");
  Serial.println(ID);
  Serial.println("PASSWORLD:");
  Serial.println(PASSWORD);


  WiFi.begin(ID,PASSWORD);

    u8g2.setCursor (0, 10);
    u8g2.println("连接wifi中");
    u8g2.sendBuffer();
    
  while(WiFi.status()!=WL_CONNECTED)
  {

    delay(10000);//延迟大一点,不然联网连不上!
    Serial.println("正在连接...");

    u8g2.setCursor (0, 10);
    u8g2.println("连接wifi中");
    u8g2.sendBuffer();
    
  }
 
  Serial.println("连接成功!");
  //==================wifi连接==================
  u8g2.clearBuffer();
  WeatherURL = GitURL(API); 
  



  delay(100);
}

void loop() {
    ParseWeather(WeatherURL);
    Serial.println(WeatherURL);
    u8g2.clearBuffer();//清平
    delay(10);
    
    u8g2.setCursor (0, 10);
    u8g2.println(one);

    u8g2.setCursor (0, 25);
    u8g2.println(two);

    u8g2.setCursor (0, 40);
    u8g2.println(three);

    u8g2.setCursor (0, 55);
    u8g2.println(four);   

    u8g2.sendBuffer();//将内容上传到缓存区


  
  delay(5000);
}


 

①下载库文件,项目所需的库,都可以在内置的库文件管理器中找到

②屏幕接口采用硬件IIC引脚,屏幕方向为R0正向

③定义wifi账号以及wifi密码,还有屏幕的显示内容变量

④设置esp_walk的api,此API实时接收导航内容并让屏幕显示导航内容

⑤接收到API返回的内容后,进行JSON解析到变量内

⑥SETUP函数
将屏幕的字库设置为中文字库,并且启用
设置wifi账号密码,若wifi未连接,则一直循环连接直到连接成功

⑦LOOP函数
一直访问API,并且将更新后的API数据显示到屏幕上,每行10字,4行

⑧显示效果


总结
首先感谢您能看到这里,意味着您认真看了我的文章,有不足之处,欢迎指点
(一)项目采用了高德开放平台的多项API,从而完成一个导航的项目,但是高德平台其实针对导航有更完整的API,文章仅为大家呈现多种API配合、多设备实现导航
(二)文章采用的所有代码,包括API源码、APP代码、单片机代码均开源、分享,让大家一起学习、交流
(三)本项目通过高德导航与路径规划技术在单片机及APP上的成功应用,不仅验证了技术融合的可行性,也为未来导航服务在物联网领域的广泛应用奠定了坚实基础。
(四)本项目所有代码下载地址,https://wwmg.lanzouj.com/in1Dl2dlmvkf

作者: 小恶魔owo, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-4067534.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论0条评论)

登录后参与讨论
我要评论
0
0
关闭 站长推荐上一条 /2 下一条