文章目錄
(一)需求分析
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開發技術指南