文章目录
(一)需求分析
1、项目背景
基于当今的社会需求,没有人再会小看营销的重要性。而二维图像和视频等营销方式已经吸引不了客户的眼球。随着支付宝AR红包和任天堂的《精灵宝可梦》游戏的火速走红,AR已经成为了营销者中的新宠儿。公司主营业务便是VR相关,但是为了更好的开展业务和增加技术储备。于是,一种新型的基于地理位置的AR App便诞生了。
2、本项目应用场景
- 旅游景点
- 房地产看房
- AR地图导航
- 其他
3、用户使用场景描述
- 用于旅游景点
用户来到景区,通过扫描相应的二维码,系统反馈带有AR效果的标签,比如可以看附近的公厕、停车场或者其他标志性建筑物,用户点击标签,会进入VR场景,查看相应标签做对应的景点或建筑物。 - 用于房地产看房
用户买房一般非现房,用户想知道建成之后什么效果。用户仅需要扫描二维码或者通过图像识别接口扫描实物,系统反馈AR效果的房间内物品标签,用户点击可查看建成后效果图(VR图片或视频展示或其他广告展示) - 用于地图导航
用户使用该软件搜索目的地进行AR导航(导航部分还未开发)
4、技术&商业价值
- 可广泛用于当前新式广告营销
- 可储备相应技术,迎接5G时代,与5G结合
- 为以后开发AR/VR相关产品做技术积累
(二)概要设计
1、用户操作流程图设计
下面是完整的设计思路。
注:该程序上述部分功能还未实现(图片识别、导航、看全景),不过已经在其他开发的APP中实现,本文主要介绍显示动态标签功能实现。
2、APP端设计
3、服务端设计
4、数据库设计
主要是由三张表组成,分别是扫描信息详情表、位置信息详情表、人员详情表。
(三)实现所用主要技术
1、APP端
- Z-Xing扫描二维码插件
- fastJson+Volley网络通信框架
- 仿微信弹出框插件
- lombok
- 将GPS坐标转换成导航坐标算法
- 基于Android的应用技术
2、服务端
- springboot后端开发框架
- lombok插件
- mysql jdbc
- maven项目管理工具
- jpa
- junit单元测试工具
- IDEA
- Java Web开发技术
3、数据库
- MySQL5.7
- Navicat for Mysql5.7
4、其他
- xmind
- processOn
(四)详细设计&实现难点
1、APP端核心模块功能分析
- 解析后端发来的数据
主要是json格式的解析
/**
* 数据解析操作
*/
public class HandleResultData implements Runnable{
@Override
public void run(){
String RequestUrl="http://uae5f2.natappfree.cc/ar/client/location/show?scanId=1";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(
//第一个参数,请求的网址
RequestUrl,
//第二个参数
null,
//响应正确时的处理
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d("TAG", response.toString());
/**
* 解析Json为Object
*/
String mJSON = response.toString();
ResultBean resultBean=new ResultBean();
resultBean = JSON.parseObject(mJSON,ResultBean.class);
//响应错误时的处理
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("TAG", error.getMessage(), error);
mHandler.obtainMessage(MSG_FAILURE).sendToTarget();
}
});
//把这个请求加到Volley队列即可
jsonObjectRequest.setTag(TAG);
mQueue.add(jsonObjectRequest);
}
- AR浮窗效果实现
主要是将导航坐标显示在浮层上以实现AR效果。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (currentLocation == null) {
return;
}
final int radius = 30;
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
paint.setTextSize(60);
for (int i = 0; i < arPoints.size(); i ++) {
float[] currentLocationInECEF = LocationHelper.WSG84toECEF(currentLocation);
float[] pointInECEF = LocationHelper.WSG84toECEF(arPoints.get(i).getLocation());
float[] pointInENU = LocationHelper.ECEFtoENU(currentLocation, currentLocationInECEF, pointInECEF);
float[] cameraCoordinateVector = new float[4];
Matrix.multiplyMV(cameraCoordinateVector, 0, rotatedProjectionMatrix, 0, pointInENU, 0);
// cameraCoordinateVector[2] is z, that always less than 0 to display on right position
// if z > 0, the point will display on the opposite
if (cameraCoordinateVector[2] < 0) {
float x = (0.5f + cameraCoordinateVector[0]/cameraCoordinateVector[3]) * canvas.getWidth();
float y = (0.5f - cameraCoordinateVector[1]/cameraCoordinateVector[3]) * canvas.getHeight();
canvas.drawCircle(x, y, radius, paint);
canvas.drawText(arPoints.get(i).getName(), x - (30 * arPoints.get(i).getName().length() / 2), y - 80, paint);
}
}
}
2、服务端核心模块功能分析
- 请求数据API
我设计了一个数据请求的API格式,data链表中夹杂着一个locationlist链表,双层链表实现。
{
"code":0,
"msg":"success",
"data":{
"name": "黄河路",
"type": 1,
"locationList":[
{
"id":"123456",
"name":"丹尼斯",
"latitude":12.335,
"longitude":34.225,
"altitude":5.2,
"description":"一个购物的地方",
"icon":"http://www.dennis.com.cn/u/cms/www/201707/191157482x37.jpg",
"link":"http://122.114.223.188/toShow?VRourEditor=206",
"people":[
{
"name":"jack",
"responsibility":"doctor",
"phone":"13052312154"
},
{
"name":"evan",
"responsibility":"护士",
"phone":"13565667488"
}
]
},
{
"id":"123457",
"name":"微阿科技",
"latitude":44.123,
"longtitude":33.124,
"altitude":5.2,
"description":"公司",
"icon":"http://www.dennis.com.cn/u/cms/www/201707/191157482x37.jpg",
"link":"http://122.114.223.188/toShow?VRourEditor=206",
"people":[
{
"name":"linda",
"responsibility":"doctor",
"phone":"1325355555"
},
{
"name":"tim",
"responsibility":"护士",
"phone":"13561125488"
}
]
}
]
}
}
3、核心算法分析
- 将gps坐标转换成手机导航坐标实现
其实就是先将GPS坐标即大地中心系WGS84(WorldGeodeticCoordinateSystem1984)转化为地球中心坐标系ECEF(Earth-Centered, Earth-Fixed),然后再将地球中心坐标系ECEF转换成局部切线平面ENU(东、北、天)坐标系,再将其转化为手机导航坐标系x、y轴。
上述图片参考:无人机常见坐标系
更详细的介绍我放在了我的项目中,可以参考:
https://github.com/Evanlovea/AR-App/tree/master/ARNavigation/app/src/main/res/docs
/**
* 将GPS坐标系转换为ECEF
* (ECEF(Earth-Centered,Earth-Fixed),以地球为中心,符合地球,
* 是一个笛卡尔坐标系,也称为“普通地表”系统)
* @param location
* @return
*/
public static float[] WSG84toECEF(Location location) {
double radLat = Math.toRadians(location.getLatitude());
double radLon = Math.toRadians(location.getLongitude());
float clat = (float) Math.cos(radLat);
float slat = (float) Math.sin(radLat);
float clon = (float) Math.cos(radLon);
float slon = (float) Math.sin(radLon);
float N = (float) (WGS84_A / Math.sqrt(1.0 - WGS84_E2 * slat * slat));
float x = (float) ((N + location.getAltitude()) * clat * clon);
float y = (float) ((N + location.getAltitude()) * clat * slon);
float z = (float) ((N * (1.0 - WGS84_E2) + location.getAltitude()) * slat);
return new float[] {x , y, z};
}
/**
* 将ECEF坐标系转换为ENU(站心坐标系)坐标系
*
* @param currentLocation
* @param ecefCurrentLocation
* @param ecefPOI
* @return
*/
public static float[] ECEFtoENU(Location currentLocation, float[] ecefCurrentLocation, float[] ecefPOI) {
double radLat = Math.toRadians(currentLocation.getLatitude());
double radLon = Math.toRadians(currentLocation.getLongitude());
float clat = (float)Math.cos(radLat);
float slat = (float)Math.sin(radLat);
float clon = (float)Math.cos(radLon);
float slon = (float)Math.sin(radLon);
float dx = ecefCurrentLocation[0] - ecefPOI[0];
float dy = ecefCurrentLocation[1] - ecefPOI[1];
float dz = ecefCurrentLocation[2] - ecefPOI[2];
float east = -slon*dx + clon*dy;
float north = -slat*clon*dx - slat*slon*dy + clat*dz;
float up = clat*clon*dx + clat*slon*dy + slat*dz;
return new float[] {east , north, up, 1};
}
4、效果展示
下面是某商业APP的图,我的没它那么花里胡哨的(我做的UI比较简单 ),不过原理应该差不多,不过这个APP实现应该是基于某地图的SDK的,而我的可以动态添加地理位置信息,不知道它的可不可以。可参考。(主要是我懒得搭服务器部署运行了 )。
5、其他模块实现
可以参考我的github地址:基于地理位置的AR app项目
(五)参考文献
【1】http://www.gogocity.cn/flash/video2.mp4
【2】无人导航常见坐标系
【3】DSTO-TN-0432.pdf
【4】Android开发技术指南