add new func of ezhou airport and upgrade the aiSdkVersion to fit demo server

This commit is contained in:
zhongchao
2021-08-05 10:50:05 +08:00
parent 78e869a3b4
commit ea4e380b35
73 changed files with 2634 additions and 829 deletions

View File

@@ -1,8 +1,8 @@
package com.mogo.module.common.uploadintime;
package com.mogo.module.common.datacenter;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.realtime.entity.CloudLocationInfo;
import com.mogo.service.locationinfo.CloudLocationInfo;
import com.mogo.utils.logger.Logger;
import org.json.JSONObject;
@@ -16,20 +16,20 @@ import java.util.List;
*
* 实时坐标数据处理中心
*/
public class SnapshotLocationController {
public class SnapshotLocationDataCenter {
private static final String TAG = "SnapshotLocationController";
private static volatile SnapshotLocationController sInstance;
private static volatile SnapshotLocationDataCenter sInstance;
private SnapshotLocationController() {
private SnapshotLocationDataCenter() {
}
public static SnapshotLocationController getInstance() {
public static SnapshotLocationDataCenter getInstance() {
if (sInstance == null) {
synchronized (SnapshotLocationController.class) {
synchronized (SnapshotLocationDataCenter.class) {
if (sInstance == null) {
sInstance = new SnapshotLocationController();
sInstance = new SnapshotLocationDataCenter();
}
}
}

View File

@@ -1,24 +1,29 @@
package com.mogo.module.common.drawer;
import android.os.Build;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.commons.debug.DebugConfig;
import com.mogo.map.MogoLatLng;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.map.marker.MogoMarkerOptions;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.constants.DataTypes;
import com.mogo.module.common.utils.SimpleHandlerThreadPool;
import com.mogo.realtime.entity.ADASRecognizedResult;
import com.mogo.utils.logger.Logger;
import com.mogo.module.common.drawer.bean.SpeedData;
import com.mogo.module.common.utils.Trigonometric;
import com.mogo.service.adas.entity.ADASRecognizedResult;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import static com.mogo.cloud.socket.entity.SocketDownDataHelper.FROM_ADAS;
public
/**
@@ -29,20 +34,25 @@ public
*/
class AdasRecognizedResultDrawer extends BaseDrawer {
private static final String TAG = "AdasRecognizedResultDrawer";
private static final String TAG = "RecognizedResultDrawer";
private static volatile AdasRecognizedResultDrawer sInstance;
/**
* 上一帧数据的缓存
*/
private static Map<String, IMogoMarker> mMarkersCaches = new ConcurrentHashMap<>();
public AdasRecognizedResultDrawer() {
super();
}
private final Map< String, ADASRecognizedResult > mLastPositions = new ConcurrentHashMap<>();
private final Map<String, ADASRecognizedResult> mLastPositions = new ConcurrentHashMap<>();
public static AdasRecognizedResultDrawer getInstance() {
if ( sInstance == null ) {
synchronized ( AdasRecognizedResultDrawer.class ) {
if ( sInstance == null ) {
if (sInstance == null) {
synchronized (AdasRecognizedResultDrawer.class) {
if (sInstance == null) {
sInstance = new AdasRecognizedResultDrawer();
}
}
@@ -59,212 +69,268 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
return sInstance;
}
public boolean hasCached( String uniqueKey ) {
return mMarkersCaches.containsKey( uniqueKey );
public boolean hasCached(String uniqueKey) {
return mMarkersCaches.containsKey(uniqueKey);
}
/**
* 渲染 adas 识别的数据
*
* @param resultList
* @param resultList adas感知融合数据
*/
public void renderAdasRecognizedResult( List< ADASRecognizedResult > resultList ) {
if ( resultList == null || resultList.isEmpty() || !DebugConfig.isUseAdasRecognize() ) {
public void renderAdasRecognizedResult(List<ADASRecognizedResult> resultList) {
final long start = System.nanoTime();
if (resultList == null || resultList.isEmpty() || !DebugConfig.isUseAdasRecognize()) {
clearOldMarker();
return;
}
if ( !MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
if (!MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
clearOldMarker();
return;
}
Map< String, IMogoMarker > newAdasRecognizedMarkersCaches = new HashMap<>();
List< ADASRecognizedResult > newDiffSet = new ArrayList<>();
for ( ADASRecognizedResult recognizedListResult : resultList ) {
// List<ADASRecognizedResult> allDatumsList = new ArrayList<>();
// prepareData(resultList, allDatumsList);
if ( isUselessValue( recognizedListResult ) ) {
Map<String, IMogoMarker> newAdasRecognizedMarkersCaches = new ConcurrentHashMap<>();
List<ADASRecognizedResult> newDiffSet = new ArrayList<>();
for (ADASRecognizedResult recognizedListResult : resultList) {
if (isUselessValue(recognizedListResult)) {
continue;
}
// 复用之前存在的 marker
String uniqueKey = recognizedListResult.uuid;
IMogoMarker marker = mMarkersCaches.remove( uniqueKey );
if ( marker != null && !marker.isDestroyed() ) {
renderAdasOneFrame( marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches );
IMogoMarker marker = mMarkersCaches.remove(uniqueKey);
if (marker != null && !marker.isDestroyed()) {
// Log.d(TAG, "发现缓存marker id : " + uniqueKey);
updateCacheMarkerRes(marker, recognizedListResult);
renderAdasOneFrame(marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches);
} else {
// 新增差集
newDiffSet.add( recognizedListResult );
// 新增添加进差集
newDiffSet.add(recognizedListResult);
}
}
removeUselessMarker();
// 能复用的 marker 数量
int cachedMarkerSize = mMarkersCaches.size();
// 需要新增的 marker 数量
removeUselessMarker(mMarkersCaches);
removeUselessLastRecord();
int newDiffSetSize = newDiffSet.size();
// 能复用的数量
int size = cachedMarkerSize >= newDiffSetSize ? newDiffSetSize : cachedMarkerSize;
// Log.d(TAG, "原数据量 " + resultList.size() + " 新增marker数量 " + newDiffSetSize);
// 复用过期 marker
if ( newDiffSetSize > 0 ) {
Iterator< Map.Entry< String, IMogoMarker > > entryIterator = mMarkersCaches.entrySet().iterator();
for ( int i = 0; i < size; i++ ) {
ADASRecognizedResult recognizedListResult = newDiffSet.get( i );
if (newDiffSetSize > 0) {
for (int i = 0; i < newDiffSetSize; i++) {
ADASRecognizedResult recognizedListResult = newDiffSet.get(i);
String uniqueKey = recognizedListResult.uuid;
Map.Entry< String, IMogoMarker > entry = entryIterator.next();
entryIterator.remove();
ADASRecognizedResult old = mLastPositions.remove( entry.getKey() );
IMogoMarker marker = entry.getValue();
if ( marker == null ) {
IMogoMarker marker = drawAdasRecognizedDataMarker(recognizedListResult);
if (marker == null) {
continue;
}
// 更新资源内容
if ( old == null || old.type != recognizedListResult.type ) {
String resIdVal = null;
int resId = getModelRes( recognizedListResult.type );
resIdVal = resId + "";
String resName = mMarkerCachesResMd5Values.get( resIdVal );
if ( !TextUtils.isEmpty( resName ) ) {
if ( !TextUtils.equals( resName, marker.getMarkerResName() ) ) {
marker.use3DResource( resName );
}
} else {
resName = marker.use3DResource( resId );
mMarkerCachesResMd5Values.put( resIdVal, resName );
}
}
renderAdasOneFrame( marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches );
}
// 复用过后还需新增的 marker
for ( int i = size; i < newDiffSetSize; i++ ) {
ADASRecognizedResult recognizedListResult = newDiffSet.get( i );
String uniqueKey = recognizedListResult.uuid;
IMogoMarker marker = drawAdasRecognizedDataMarker( recognizedListResult );
if ( marker == null ) {
continue;
}
renderAdasOneFrame( marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches );
// Log.d(TAG, "新增marker id : " + uniqueKey);
renderAdasOneFrame(marker, uniqueKey, recognizedListResult, newAdasRecognizedMarkersCaches);
}
}
if ( cachedMarkerSize - size > 0 ) {
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
}
sendMessage(MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches);
mMarkersCaches.clear();
mMarkersCaches = newAdasRecognizedMarkersCaches;
Log.d("ADAS数据延时绘制", "render 接收数据 -> 处理结束 " + TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - start)) + "ms");
}
private boolean isUselessValue( ADASRecognizedResult recognizedListResult ) {
if ( recognizedListResult == null ) {
return true;
}
if ( !isRenderType( recognizedListResult.type ) ) {
return true;
}
/**
* 对数据补点
*
* @param in
* @param out
*/
private void prepareData(List<ADASRecognizedResult> in, List<ADASRecognizedResult> out) {
// foreCastPoint(in);
out.addAll(in);
}
String uniqueKey = recognizedListResult.uuid;
if ( TextUtils.isEmpty( uniqueKey ) ) {
private final static String FORECAST = "adasForecast";
/**
* 基于工控机识别的数据点速度预测当前位置和距离自车距离
*
* @param in 数据源
*/
private void foreCastPoint(List<ADASRecognizedResult> in) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
for (ADASRecognizedResult adasResult : in) {
Log.d(FORECAST, "ready to foreCast current uuid : " + adasResult.uuid);
long internal = getCurSatelliteTime() - adasResult.satelliteTime;
if (internal <= 0) {
Log.d(FORECAST, "time internal less than 0 , uuid : " + adasResult.uuid);
continue;
}
long startTime = System.currentTimeMillis();
// 预测点
Log.d(FORECAST, "time internal : " + internal + " speed : " + adasResult.speed);
double foreCastDistance = adasResult.speed * internal / 1000;
Log.d(FORECAST, "foreCastDistance : " + foreCastDistance);
MogoLatLng mogoLatLng = new MogoLatLng(adasResult.lat, adasResult.lon);
MogoLatLng foreCastMogoLatLon = Trigonometric.getNewLocation(mogoLatLng, foreCastDistance, adasResult.heading);
// 计算与自车距离
float distanceFromSelf = CoordinateUtils.calculateLineDistance(getCurCoordinates()[0], getCurCoordinates()[1]
, foreCastMogoLatLon.getLon(), foreCastMogoLatLon.getLat());
long foreCastInternal = System.currentTimeMillis() - startTime;
Log.d(FORECAST, "foreCastInternal :" + foreCastInternal); //todo 耗时1~2毫秒 需要测试是否由于补点算法造成
adasResult.lat = foreCastMogoLatLon.getLat();
adasResult.lon = foreCastMogoLatLon.getLon();
adasResult.satelliteTime = (getCurSatelliteTime() - foreCastInternal);
adasResult.distance = distanceFromSelf;
}
}
}
/**
* todo 后面涉及到此类变化的数据均改动
*
* @param marker
* @param recognizedListResult
*/
private void updateCacheMarkerRes(IMogoMarker marker, ADASRecognizedResult recognizedListResult) {
String resIdVal;
int resId = getModelRes(recognizedListResult.type);
resIdVal = resId + "";
String resName = mMarkerCachesResMd5Values.get(resIdVal);
if (!TextUtils.isEmpty(resName)) {
if (!TextUtils.equals(resName, marker.getMarkerResName())) {
marker.use3DResource(resName);
}
} else {
resName = marker.use3DResource(resId);
mMarkerCachesResMd5Values.put(resIdVal, resName);
}
}
private void removeUselessLastRecord() { // todo 最好重新设计一个数据结构用于多线程数据过期失效的场景参见redis数据过期
if (mLastPositions.isEmpty()) {
return;
}
Iterator<ADASRecognizedResult> iterator = mLastPositions.values().iterator();
Log.d("EmArrow", "removeUselessLastRecord size : " + mLastPositions.size());
while (iterator.hasNext()) {
ADASRecognizedResult result = iterator.next();
long internal = result.satelliteTime - getCurSatelliteTime();
if (internal > 3000) { //防止帧率过低导致误删除上一个节点对象,从而出现跳跃现象
iterator.remove();
}
}
}
/**
* 过滤无用数据
*
* @param recognizedListResult {@link ADASRecognizedResult}
* @return useless
*/
private boolean isUselessValue(ADASRecognizedResult recognizedListResult) {
if (recognizedListResult == null) {
return true;
}
return false;
if (nonRenderType(recognizedListResult.type)) {
return true;
}
String uniqueKey = recognizedListResult.uuid;
return TextUtils.isEmpty(uniqueKey);
}
/**
* 绘制某个物体的一个数据
*
* @param recognizedListResult
* @param newAdasRecognizedMarkersCaches
* @param recognizedListResult {@link ADASRecognizedResult}
* @param newAdasRecognizedMarkersCaches 缓存集合
*/
private void renderAdasOneFrame( IMogoMarker marker,
String uniqueKey,
ADASRecognizedResult recognizedListResult,
Map< String, IMogoMarker > newAdasRecognizedMarkersCaches ) {
private void renderAdasOneFrame(IMogoMarker marker,
String uniqueKey,
ADASRecognizedResult recognizedListResult,
Map<String, IMogoMarker> newAdasRecognizedMarkersCaches) {
final long start = System.nanoTime();
// Log.d(TAG, "renderAdasOneFrame uuid : " + uniqueKey + " type : " + recognizedListResult.type + " heading : " + recognizedListResult.heading);
ADASRecognizedResult lastPosition = mLastPositions.remove(uniqueKey);
// 道路吸附
// double lastLon = -1;
// double lastLat = -1;
// if (lastPosition != null) {
// lastLon = lastPosition.lon;
// lastLat = lastPosition.lat;
// }
// double[] matchLonLat = getMatchLonLat(recognizedListResult.uuid, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading, lastLon, lastLat);
//
// recognizedListResult.lon = matchLonLat[0];
// recognizedListResult.lat = matchLonLat[1];
// Log.d( "matchRoad", "cost = %s", System.currentTimeMillis() - start );
final long start = System.currentTimeMillis();
ADASRecognizedResult lastPosition = mLastPositions.remove( uniqueKey );
double lastLon = -1;
double lastLat = -1;
if ( lastPosition != null ) {
lastLon = lastPosition.lon;
lastLat = lastPosition.lat;
}
double[] matchLonLat = getMatchLonLat( recognizedListResult.uuid, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading, lastLon, lastLat );
recognizedListResult.lon = matchLonLat[0];
recognizedListResult.lat = matchLonLat[1];
mLastPositions.put( uniqueKey, recognizedListResult );
// Logger.d( "matchRoad", "cost = %s", System.currentTimeMillis() - start );
newAdasRecognizedMarkersCaches.put( uniqueKey, marker );
if ( lastPosition != null ) {
long interval = computeAnimDuration( lastPosition.systemTime, recognizedListResult.systemTime, lastPosition.satelliteTime, recognizedListResult.satelliteTime );
final MogoLatLng renderLoc = new MogoLatLng( recognizedListResult.lat, recognizedListResult.lon );
long cost = System.currentTimeMillis() - start;
final long intervalRef = interval - cost;
SimpleHandlerThreadPool.getInstance().postRender( () -> {
marker.addDynamicAnchorPosition( renderLoc, ( float ) recognizedListResult.heading, intervalRef );
} );
} else {
marker.setRotateAngle( ( ( float ) recognizedListResult.heading ) );
marker.setPosition( recognizedListResult.lat, recognizedListResult.lon );
mLastPositions.put(uniqueKey, recognizedListResult);
// Log.d(TAG, "使用缓存 id : " + uniqueKey);
long interval = 45;
if (lastPosition != null) {
interval = computeAnimDuration(lastPosition.satelliteTime, recognizedListResult.satelliteTime);
}
final MogoLatLng renderLoc = new MogoLatLng(recognizedListResult.lat, recognizedListResult.lon);
long cost = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
Log.d("ADAS动画数据","cost : " + cost);
final long intervalRef = interval - cost;
Log.d("ADAS动画数据", "最终赋值 : " + intervalRef + " 两帧间隔 : " + interval + " uuid : " + recognizedListResult.uuid);
marker.addDynamicAnchorPosition(renderLoc, (float) recognizedListResult.heading, intervalRef);
String carColor = recognizedListResult.color;
if ( TextUtils.isEmpty( carColor ) ) {
carColor = getModelRenderColor( recognizedListResult.type, recognizedListResult.speed, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading );
if (TextUtils.isEmpty(carColor)) {
carColor = getModelRenderColor(recognizedListResult.type, FROM_ADAS, recognizedListResult.drawlevel);
}
marker.setAnchorColor( carColor );
marker.setAnchorColor(carColor);
if ( shouldShowSpeed( recognizedListResult.type ) ) {
newAdasRecognizedMarkersCaches.put(uniqueKey, marker);
if (shouldShowSpeed(recognizedListResult.type)) {
Message msg = mRenderThreadHandler.obtainMessage();
SpeedData obj = new SpeedData();
obj.context = mContext;
obj.marker = marker;
obj.speed = recognizedListResult.speed;
msg.obj = obj;
msg.obj = new SpeedData(marker
, recognizedListResult.speed
, recognizedListResult.uuid
, recognizedListResult.type
, recognizedListResult.heading
, MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode());
msg.what = MSG_DISPLAY_SPEED;
msg.sendToTarget();
}
Log.d("ADAS数据延时", "render 刷新一台车 cost : " + TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - start)));
}
/**
* 绘制 marker
*
* @param recognizedListResult
* @return
* @param recognizedListResult {@link ADASRecognizedResult}
* @return {@link IMogoMarker}
*/
private IMogoMarker drawAdasRecognizedDataMarker( ADASRecognizedResult recognizedListResult ) {
if ( recognizedListResult == null ) {
private IMogoMarker drawAdasRecognizedDataMarker(ADASRecognizedResult recognizedListResult) {
long start = System.nanoTime();
if (recognizedListResult == null) {
return null;
}
String resIdVal = null;
int resId = getModelRes( recognizedListResult.type );
resIdVal = resId + "";
int resId = getModelRes(recognizedListResult.type);
String resIdVal = resId + "";
String carColor = recognizedListResult.color;
if ( TextUtils.isEmpty( carColor ) ) {
carColor = getModelRenderColor( recognizedListResult.type, recognizedListResult.speed, recognizedListResult.lon, recognizedListResult.lat, recognizedListResult.heading );
if (TextUtils.isEmpty(carColor)) {
carColor = getModelRenderColor(recognizedListResult.type, FROM_ADAS, recognizedListResult.drawlevel);
}
MogoMarkerOptions options = new MogoMarkerOptions()
.owner( DataTypes.TYPE_MARKER_ADAS )
.anchor( 0.5f, 0.5f )
.set3DMode( true )
.gps( true )
.anchorColor( carColor )
.controlAngle( true )
.resName( mMarkerCachesResMd5Values.get( resIdVal ) )
.icon3DRes( resId )
.rotate( ( float ) recognizedListResult.heading )
.position( new MogoLatLng( recognizedListResult.lat, recognizedListResult.lon ) );
IMogoMarker marker = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMarkerManager( mContext ).addMarker( DataTypes.TYPE_MARKER_ADAS, options );
cacheMarkerIconResMd5Val( resIdVal, marker );
.owner(DataTypes.TYPE_MARKER_ADAS)
.anchor(0.5f, 0.5f)
.set3DMode(true)
.gps(true)
.anchorColor(carColor)
.controlAngle(true)
.resName(mMarkerCachesResMd5Values.get(resIdVal))
.icon3DRes(resId)
.rotate((float) recognizedListResult.heading)
.position(new MogoLatLng(recognizedListResult.lat, recognizedListResult.lon));
IMogoMarker marker = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMarkerManager(mContext).addMarker(DataTypes.TYPE_MARKER_ADAS, options);
cacheMarkerIconResMd5Val(resIdVal, marker);
Log.d("ADAS数据延时", "创建一个新 marker cost : " + TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - start)));
return marker;
}
@@ -279,12 +345,10 @@ class AdasRecognizedResultDrawer extends BaseDrawer {
* 清除旧的 marker 数据
*/
public void clearOldMarker() {
if ( mMarkersCaches != null ) {
if (mMarkersCaches != null) {
mMarkersCaches.clear();
}
if ( mLastPositions != null ) {
mLastPositions.clear();
}
sendMessage( MSG_REMOVE_DIRTY_MARKERS, DataTypes.TYPE_MARKER_ADAS );
mLastPositions.clear();
sendMessage(MSG_REMOVE_DIRTY_MARKERS, DataTypes.TYPE_MARKER_ADAS);
}
}

View File

@@ -1,5 +1,8 @@
package com.mogo.module.common.drawer;
import static com.mogo.cloud.socket.entity.SocketDownDataHelper.FROM_ADAS;
import static java.lang.Math.PI;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Typeface;
@@ -10,23 +13,21 @@ import android.util.Log;
import android.view.ViewGroup;
import android.widget.TextView;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.map.marker.IMogoMarker;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.R;
import com.mogo.module.common.constants.AdasRecognizedType;
import com.mogo.module.common.uploadintime.SnapshotLocationController;
import com.mogo.module.common.datacenter.SnapshotLocationDataCenter;
import com.mogo.module.common.drawer.bean.SpeedData;
import com.mogo.utils.WorkThreadHandler;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import static java.lang.Math.PI;
import java.util.concurrent.ConcurrentHashMap;
public
/*
@@ -37,40 +38,19 @@ public
*/
class BaseDrawer {
/**
* 速度显示对象
*/
public class SpeedData {
public IMogoMarker marker;
public Context context;
double speed;
public void showSpeed() {
try {
showSelfSpeed(context,
marker,
speed,
MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode());
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 移除过期的 marker
public static final int MSG_REMOVE_DIRTY_MARKERS = 9990;
/**
* 显示速度
*/
public static final int MSG_DISPLAY_SPEED = 11;
/**
* 地图刷新频率
*/
public static final int MAP_RENDER_FRAME_FREQUENCY = 30;
/**
* 显示速度
*/
public static final int MSG_DISPLAY_SPEED = 11;
/**
* 移动点的时间间隔
*/
@@ -79,23 +59,30 @@ class BaseDrawer {
/**
* 地图内部资源md5缓存便于资源复用
*/
protected static final Map<String, String> mMarkerCachesResMd5Values = new HashMap<>();
/**
* 上一帧数据的缓存
*/
protected Map<String, IMogoMarker> mMarkersCaches = new HashMap<>();
protected static final ConcurrentHashMap<String, String> mMarkerCachesResMd5Values = new ConcurrentHashMap<>();
protected final Context mContext;
protected static Handler mRenderThreadHandler = null;
private static TextView mSpeedView;
public BaseDrawer() {
mContext = AbsMogoApplication.getApp();
initWorkThreadHandler();
initView();
}
private void initView() {
if (mSpeedView == null) {
mSpeedView = new TextView(mContext);
mSpeedView.setSingleLine(false);
mSpeedView.setTextColor(Color.WHITE);
mSpeedView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
mSpeedView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
private static Handler mWorkThreadHandler;
protected static Handler mRenderThreadHandler = null;
/**
* 处理 marker 移除的线程
@@ -140,30 +127,29 @@ class BaseDrawer {
}
}
/**
* 显示速度
*
* @param data {@link SpeedData}
*/
private static void showSpeed(SpeedData data) {
if (data == null) {
return;
}
data.showSpeed();
private static void showSpeed(SpeedData speedData) {
showSelfSpeed(speedData.getMarker()
, speedData.getSpeed()
, speedData.getUuid()
, speedData.getType()
, speedData.getHeading()
, speedData.getIsVrMode());
}
/**
* 清除无效[为 null 或者 已被销毁]的 marker
*/
protected void removeUselessMarker() {
protected void removeUselessMarker(Map<String, IMogoMarker> mMarkersCaches) {
if (mMarkersCaches == null || mMarkersCaches.isEmpty()) {
return;
}
Iterator<IMogoMarker> iterator = mMarkersCaches.values().iterator();
while (iterator.hasNext()) {
IMogoMarker marker = iterator.next();
if (marker == null || marker.isDestroyed()) {
if (marker != null) {
iterator.remove();
marker.remove();
marker.destroy();
}
}
}
@@ -187,29 +173,29 @@ class BaseDrawer {
* @param type {@link AdasRecognizedType}
* @return render
*/
public boolean isRenderType(int type) {
public boolean nonRenderType(int type) {
AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom(type);
return recognizedType == AdasRecognizedType.classIdCar
|| recognizedType == AdasRecognizedType.classIdMoto
|| recognizedType == AdasRecognizedType.classIdBicycle
|| recognizedType == AdasRecognizedType.classIdPerson
|| recognizedType == AdasRecognizedType.classIdTrafficBus
|| recognizedType == AdasRecognizedType.classIdTrafficTruck
|| recognizedType == AdasRecognizedType.classIdUnKnow; //todo unKnow物体绘制
return recognizedType != AdasRecognizedType.classIdCar
&& recognizedType != AdasRecognizedType.classIdMoto
&& recognizedType != AdasRecognizedType.classIdBicycle
&& recognizedType != AdasRecognizedType.classIdPerson
&& recognizedType != AdasRecognizedType.classIdTrafficBus
&& recognizedType != AdasRecognizedType.classIdTrafficTruck
&& recognizedType != AdasRecognizedType.classIdUnKnow;
}
/**
* 是否展示车速
* 是否展示车速UUID以及类型
*
* @param type {@link AdasRecognizedType}
* @return showSpeed
*/
public boolean shouldShowSpeed(int type) {
AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom(type);
return recognizedType != AdasRecognizedType.classIdBicycle
&& recognizedType != AdasRecognizedType.classIdMoto
&& recognizedType != AdasRecognizedType.classIdPerson
&& recognizedType != AdasRecognizedType.classIdUnKnow; //todo unKnow物体不绘制车速
return true; //todo 验证行人预警,对行人和自行车不做infoWindow过滤
// AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom(type);
// return recognizedType != AdasRecognizedType.classIdPerson;
// &&recognizedType != AdasRecognizedType.classIdBicycle //todo Bicycle显示
// && recognizedType != AdasRecognizedType.classIdMoto //todo moto显示
}
/**
@@ -220,64 +206,53 @@ class BaseDrawer {
*/
public int getModelRes(int type) {
AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom(type);
if (recognizedType == AdasRecognizedType.classIdCar
|| recognizedType == AdasRecognizedType.classIdTrafficTruck) {
return R.raw.othercar;
if (recognizedType == AdasRecognizedType.classIdCar) {
// TODO 这里临时替换模型解决穿模现象
return R.raw.tachexiaoche;
} else if (recognizedType == AdasRecognizedType.classIdTrafficBus) {
return R.raw.bus;
} else if (recognizedType == AdasRecognizedType.classIdBicycle
|| recognizedType == AdasRecognizedType.classIdMoto) {
} else if (recognizedType == AdasRecognizedType.classIdMoto) {
return R.raw.motorbike;
} else if (recognizedType == AdasRecognizedType.classIdStopLine) {
return R.raw.stopline;
} else if (recognizedType == AdasRecognizedType.classIdWarningArrows) {
return R.raw.arraw;
} else if (recognizedType == AdasRecognizedType.classIdUnKnow) { //todo unKnow物体3D模型
return R.raw.othercar;
} else if (recognizedType == AdasRecognizedType.classIdUnKnow) {
return R.raw.tache;
} else if (recognizedType == AdasRecognizedType.classIdBicycle) {
return R.raw.zixingche;
} else if (recognizedType == AdasRecognizedType.classIdTrafficTruck) {
// TODO 这里临时替换模型解决穿模现象
return R.raw.daba;
}
return R.raw.people;
}
/**
* 根据速度、经纬度计算距离判断车辆颜色
* 根据数据源判断车辆预警颜色
*
* @param speed 车速 TODO 这里很可能是adas的策略
* @param lon 经度
* @param lat 纬度
* @param type 车辆类型
* @param fromType 数据来源
* @param drawLevel 危险等级
* @return 实际车辆颜色
*/
protected String getModelRenderColor(int type, double speed, double lon, double lat, double angle) {
protected String getModelRenderColor(int type, int fromType, int drawLevel) {
AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom(type);
if (recognizedType == AdasRecognizedType.classIdTrafficBus) {
return "#D8D8D8FF";
if (recognizedType == AdasRecognizedType.classIdUnKnow) {
return Car3DModelColor.Normal.color;
}
if (recognizedType == AdasRecognizedType.classIdUnKnow){ //todo unKnow颜色绘制
return "#FF2894FF";
}
// 距离策略
double[] coordinates = getCurCoordinates();
double distance = CoordinateUtils.calculateLineDistance(lon, lat, coordinates[0], coordinates[1]) * 100;
if (distance < 50) {
return Car3DModelColor.Dangerous.color;
} else if (distance < 100 && distance >= 50) {
return Car3DModelColor.Warming.color;
}
// 他车车速和自车车速对比速度策略
// 自车速度 >= 50% 危险
// 10% < 自车速度 < 50% 警告
double curSpeed = getCurSpeed();
if (curSpeed > 0 && speed > curSpeed) {
double rate = ((speed - curSpeed) / curSpeed) * 100;
if (rate >= 50) {
return Car3DModelColor.Dangerous.color;
} else if (rate > 10 && rate < 50) {
return Car3DModelColor.Warming.color;
if (fromType == FROM_ADAS) {
switch (drawLevel) {
case 1:
return Car3DModelColor.Normal.color;
case 2:
return Car3DModelColor.Warming.color;
case 3:
return Car3DModelColor.Dangerous.color;
default:
return Car3DModelColor.Error.color;
}
}
// 默认颜色
return Car3DModelColor.Normal.color;
}
@@ -286,10 +261,10 @@ class BaseDrawer {
*
* @return isCurSpeed
*/
private double getCurSpeed() {
protected double getCurSpeed() {
double speed = MogoApisHandler.getInstance().getApis().getAdasControllerApi().getLastSpeed();
if (speed <= 0) {
speed = SnapshotLocationController.getInstance().getCurSpeed();
speed = SnapshotLocationDataCenter.getInstance().getCurSpeed();
}
return speed;
}
@@ -297,20 +272,32 @@ class BaseDrawer {
/**
* 返回当前自车经纬度
*
* @return
* @return 0:lon 1:lat
*/
private double[] getCurCoordinates() {
protected double[] getCurCoordinates() {
double[] coordinates = {
MogoApisHandler.getInstance().getApis().getAdasControllerApi().getLastLon(),
MogoApisHandler.getInstance().getApis().getAdasControllerApi().getLastLat(),
};
if (coordinates[0] <= 0) {
coordinates[0] = SnapshotLocationController.getInstance().getCurLon();
coordinates[1] = SnapshotLocationController.getInstance().getCurLat();
coordinates[0] = SnapshotLocationDataCenter.getInstance().getCurLon();
coordinates[1] = SnapshotLocationDataCenter.getInstance().getCurLat();
}
return coordinates;
}
/**
* 返回当前自车SNTP时间
*
* @return SNTP时间
*/
protected long getCurSatelliteTime() {
String satelliteTime = MogoApisHandler.getInstance().getApis().getAdasControllerApi().getSatelliteTime();
if (TextUtils.isEmpty(satelliteTime)) {
return System.currentTimeMillis();
}
return Long.parseLong(satelliteTime);
}
/**
* 模型颜色
@@ -319,26 +306,26 @@ class BaseDrawer {
Normal("#D8D8D8FF"),
Warming("#FFD53EFF"),
Dangerous("#FF3C45FF");
Dangerous("#FF3C45FF"),
Error("#00000000");
private final String color;
Car3DModelColor(String color) {
this.color = color;
}
}
private TextView mSpeedView = null;
}
/**
* 展示车辆速度
*
* @param context 上下文
* @param mogoMarker {@link IMogoMarker}
* @param speed 是否显示速度
* @param isVrMode 是否是vrMode
*/
public void showSelfSpeed(Context context, IMogoMarker mogoMarker, double speed, boolean isVrMode) {
public static void showSelfSpeed(IMogoMarker mogoMarker, double speed, String uuid, int type, double heading, boolean isVrMode) {
Log.d("EmArrow", "showSelf uuid : " + uuid + " speed : " + speed);
if (mogoMarker == null || mogoMarker.isDestroyed()) {
return;
}
@@ -347,26 +334,15 @@ class BaseDrawer {
return;
}
int speedIntVal = (int) (speed * 3.6);
if (speedIntVal <= 0) {
if (speedIntVal <= 0) { //速度为0 隐藏InfoWindow
mogoMarker.hideInfoWindow();
return;
}
String speedVal = speedIntVal + "";
String infoResName = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMapUIController().getMarkerInfoResName(speedVal);
mogoMarker.setInfoWindowOffset(0, 20);
if (TextUtils.isEmpty(infoResName)) {
if (mSpeedView == null) {
mSpeedView = new TextView(context);
mSpeedView.setTextColor(Color.WHITE);
mSpeedView.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
mSpeedView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
mSpeedView.setText(speedVal);
mogoMarker.updateInfoWindowView(mSpeedView);
MogoApisHandler.getInstance().getApis().getMapServiceApi().getMapUIController().setMarkerInfoResName(speedVal, mogoMarker.getMarkerInfoResName());
} else {
mogoMarker.updateInfoWindowView(infoResName);
}
// String text = "speed : " + speedIntVal + "\n" + uuid + "\n" + "type : " + type + "\n" + "heading : " + heading;
String text = uuid + " " + (int) heading;
mSpeedView.setText(text);
mogoMarker.updateInfoWindowView(mSpeedView);
}
/**
@@ -395,8 +371,8 @@ class BaseDrawer {
/**
* 缓存绘制 marker 的 id 和 marker 资源缓存的 md5 的关系
*
* @param id
* @param marker
* @param id 缓存资源ID
* @param marker {@link IMogoMarker}
*/
protected static void cacheMarkerIconResMd5Val(String id, IMogoMarker marker) {
if (marker == null || marker.isDestroyed()) {
@@ -412,11 +388,11 @@ class BaseDrawer {
/**
* 道路匹配到车道中心点
*
* @param lon
* @param lat
* @param angle
* @param isRtk
* @return
* @param lon 经度
* @param lat 纬度
* @param angle 方向角
* @param isRtk 是否是RTK
* @return 匹配经纬度值
*/
public double[] matchRoad(String id, double lon, double lat, double angle, boolean isRtk) {
final long start = System.currentTimeMillis();
@@ -432,25 +408,27 @@ class BaseDrawer {
/**
* 清理缓存路段数据
*
* @param id
* @param id 缓存数据Key
*/
public static void clearRoadCacheById(String id) {
MogoApisHandler.getInstance().getApis().getMapServiceApi().getMapUIController().clearRoadCacheById(id);
}
/**
* 使用系统时间或卫星时间计算出动画的运动时间
* 使用系统时间或卫星时间计算出动画的运动时间最小值45防止两个点距离过近设置的最小动画执行时间
*
* @param lastSystemTime
* @param curSystemTime
* @param lastSatelliteTime
* @param curSatelliteTime
* @return
* @param lastSatelliteTime 上一个点SNTP时间精确值
* @param curSatelliteTime 当前点SNTP时间精确值
* @return 动画运动时间
*/
public long computeAnimDuration(long lastSystemTime, long curSystemTime, long lastSatelliteTime, long curSatelliteTime) {
long systemTimeInterval = curSystemTime - lastSystemTime;
long satelliteTimeInterval = curSatelliteTime - lastSatelliteTime;
long interval = systemTimeInterval < satelliteTimeInterval || satelliteTimeInterval == 0 ? systemTimeInterval : satelliteTimeInterval;
public long computeAnimDuration(long lastSatelliteTime, long curSatelliteTime) {
if (lastSatelliteTime == 0 || curSatelliteTime == 0) {
Log.d("ADAS动画数据", "卫星时间存在错误");
return 45;
}
long interval = curSatelliteTime - lastSatelliteTime;
Log.d("ADAS动画数据", "lastSatelliteTime : " + lastSatelliteTime +
" ---- curSatelliteTime : " + curSatelliteTime + " ===== 插值 " + interval);
if (interval < 45) {
interval = 45;
}
@@ -460,13 +438,13 @@ class BaseDrawer {
/**
* 根据位置信息、车头朝向计算道路吸附
*
* @param id
* @param lon
* @param lat
* @param heading
* @param lastLon
* @param lastLat
* @return
* @param id UUID
* @param lon 经度
* @param lat 纬度
* @param heading 方向角
* @param lastLon 上一个点经度
* @param lastLat 上一个点纬度
* @return 匹配经纬度
*/
protected double[] getMatchLonLat(String id, double lon, double lat, double heading, double lastLon, double lastLat) {
double[] matchedPoint = matchRoad(id, lon,
@@ -475,7 +453,7 @@ class BaseDrawer {
true
);
boolean match = false;
boolean match;
if (matchedPoint != null) {
// Logger.d( TAG, "matchPoint %s distance = %s",lineCounter, matchedPoint[2] );
match = matchedPoint[2] < 1 && matchedPoint[2] > 0;

View File

@@ -1,11 +1,17 @@
package com.mogo.module.common.drawer;
import android.os.Message;
import static com.mogo.module.common.constants.DataTypes.TYPE_MARKER_CLOUD_DATA;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import com.mogo.cloud.commons.utils.CoordinateUtils;
import com.mogo.cloud.socket.entity.SocketDownData;
import com.mogo.cloud.socket.entity.SocketDownDataHelper;
import com.mogo.commons.AbsMogoApplication;
import com.mogo.map.MogoLatLng;
import com.mogo.map.marker.IMogoMarker;
@@ -15,9 +21,8 @@ import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.R;
import com.mogo.module.common.api.CallChatApi;
import com.mogo.module.common.constants.DataTypes;
import com.mogo.module.common.utils.SimpleHandlerThreadPool;
import com.mogo.realtime.entity.CloudRoadData;
import com.mogo.realtime.entity.MogoSnapshotSetData;
import com.mogo.module.common.utils.Trigonometric;
import com.mogo.service.adas.IMogoADASController;
import com.mogo.service.statusmanager.IMogoStatusChangedListener;
import com.mogo.service.statusmanager.StatusDescriptor;
import com.mogo.utils.ViewUtils;
@@ -26,11 +31,11 @@ import com.zhidao.carchattingprovider.ICarsChattingProvider;
import com.zhidao.carchattingprovider.MogoDriverInfo;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
* @author congtaowang
@@ -50,13 +55,13 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
super();
MogoApisHandler.getInstance().getApis()
.getStatusManagerApi()
.registerStatusChangedListener( TAG, StatusDescriptor.VR_MODE, this );
.registerStatusChangedListener(TAG, StatusDescriptor.VR_MODE, this);
}
public static SnapshotSetDataDrawer getInstance() {
if ( sInstance == null ) {
synchronized ( SnapshotSetDataDrawer.class ) {
if ( sInstance == null ) {
if (sInstance == null) {
synchronized (SnapshotSetDataDrawer.class) {
if (sInstance == null) {
sInstance = new SnapshotSetDataDrawer();
}
}
@@ -68,41 +73,34 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
sInstance = null;
}
private Object readResolve() {
// 阻止反序列化,必须实现 Serializable 接口
return sInstance;
}
/**
* 上一帧数据的缓存
*/
private static final Map<String, IMogoMarker> mMarkersCaches = new ConcurrentHashMap<>();
private final Map< String, CloudRoadData > mLastPositions = new ConcurrentHashMap<>();
private boolean mIsVrMode = false;
private final Map<String, SocketDownData.CloudRoadDataProto> mLastPositions = new ConcurrentHashMap<>();
/**
* 注册StatusDescriptor.VR_MODE类型VR_MODE状态改变回调
*
* @param descriptor 状态类型
* @param isTrue true - accOn、adas ui show、voice ui show、push ui show、v2x ui show
*/
@Override
public void onStatusChanged( StatusDescriptor descriptor, boolean isTrue ) {
Logger.d( TAG, "%s - %s", descriptor, isTrue );
public void onStatusChanged(StatusDescriptor descriptor, boolean isTrue) {
Logger.d(TAG, "%s - %s", descriptor, isTrue);
mChangeCarModeStatus = true;
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
mMarkersCaches = new HashMap<>();
if ( mLastPositions != null ) {
mLastPositions.clear();
}
sendMessage(MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches);
removeUselessMarker(mMarkersCaches);
mLastPositions.clear();
AdasRecognizedResultDrawer.getInstance().notifyVrModeChanged(); //清除ADAS old marker data
}
public boolean isVrMode() {
return mIsVrMode;
}
public boolean isChangeCarModeStatus() {
return mChangeCarModeStatus;
}
public void setChangeCarModeStatus( boolean mChangeCarModeStatus ) {
public void setChangeCarModeStatus(boolean mChangeCarModeStatus) {
this.mChangeCarModeStatus = mChangeCarModeStatus;
}
@@ -112,240 +110,279 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
* @param data 自车周边数据
* @return 清除结果
*/
private boolean clear( MogoSnapshotSetData data ) {
if ( !MogoApisHandler.getInstance().getApis().getStatusManagerApi().isMainPageLaunched() ) {
if ( mMarkersCaches == null ) {
private boolean clear(SocketDownData.LauncherSnapshotProto data) {
if (!MogoApisHandler.getInstance().getApis().getStatusManagerApi().isMainPageLaunched()) {
if (mMarkersCaches == null) {
return false;
}
if ( mMarkersCaches != null ) {
mMarkersCaches.clear();
}
if ( mLastPositions != null ) {
mLastPositions.clear();
}
sendMessage( MSG_REMOVE_DIRTY_MARKERS, DataTypes.TYPE_MARKER_CLOUD_DATA );
mMarkersCaches.clear();
mLastPositions.clear();
sendMessage(MSG_REMOVE_DIRTY_MARKERS, DataTypes.TYPE_MARKER_CLOUD_DATA);
return true;
}
if ( data == null || (
( data.getAllList() == null || data.getAllList().isEmpty() ) &&
( data.getNearList() == null || data.getNearList().isEmpty() ) ) ) {
if ( mMarkersCaches != null ) {
if (data == null || (
(data.getAllListList() == null || data.getAllListList().isEmpty()) &&
(data.getNearListList() == null || data.getNearListList().isEmpty()))) {
if (mMarkersCaches != null) {
mMarkersCaches.clear();
}
if ( mLastPositions != null ) {
mLastPositions.clear();
}
sendMessage( MSG_REMOVE_DIRTY_MARKERS, DataTypes.TYPE_MARKER_CLOUD_DATA );
mLastPositions.clear();
sendMessage(MSG_REMOVE_DIRTY_MARKERS, DataTypes.TYPE_MARKER_CLOUD_DATA);
return true;
}
return false;
}
/**
* mogo 他车、mogo 他车识别的社会车辆、路边单元识别的车辆
* 绘制来自云端的 mogo 他车、mogo 他车识别的社会车辆、路边单元识别的车辆
*
* @param data 自车周边数据
*/
public void renderSnapshotData( MogoSnapshotSetData data ) {
if ( clear( data ) ) {
public void renderSnapshotData(SocketDownData.LauncherSnapshotProto data) {
final long start = System.nanoTime();
if (clear(data)) {
return;
}
List< CloudRoadData > allDatumsList = new ArrayList<>();
prepareData( data.getAllList(), allDatumsList );
if (!MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
return;
}
Map< String, IMogoMarker > newMarkersCaches = new HashMap<>( allDatumsList.size() );
List< CloudRoadData > newDiffSet = new ArrayList<>();
List<SocketDownData.CloudRoadDataProto> allDatumsList = new ArrayList<>();
prepareData(data.getAllListList(), allDatumsList);
for ( CloudRoadData cloudRoadData : allDatumsList ) {
if ( isUselessValue( cloudRoadData ) ) {
Map<String, IMogoMarker> newMarkersCaches = new ConcurrentHashMap<>(allDatumsList.size());
List<SocketDownData.CloudRoadDataProto> newDiffSet = new ArrayList<>();
for (SocketDownData.CloudRoadDataProto cloudRoadData : allDatumsList) {
if (isUselessValue(cloudRoadData)) {
continue;
}
String uniqueKey = cloudRoadData.getUniqueKey();
IMogoMarker marker = mMarkersCaches.remove( uniqueKey );
if ( marker != null && !marker.isDestroyed() ) {
renderSnapshotOneFrame( marker, uniqueKey, cloudRoadData, newMarkersCaches );
String uniqueKey = cloudRoadData.getUuid();
IMogoMarker marker = mMarkersCaches.remove(uniqueKey);
if (marker != null && !marker.isDestroyed()) {
updateCacheMarkerRes(marker, cloudRoadData);
renderSnapshotOneFrame(marker, uniqueKey, cloudRoadData, newMarkersCaches);
} else {
newDiffSet.add( cloudRoadData );
newDiffSet.add(cloudRoadData);
}
}
removeUselessMarker();
// 能复用的 marker 数量
int cachedMarkerSize = mMarkersCaches.size();
// 需要新增的 marker 数量
int newDiffSetSize = newDiffSet.size();
// 能复用的数量
int size = Math.min(cachedMarkerSize, newDiffSetSize);
// 复用过期 marker
if ( newDiffSetSize > 0 ) {
Iterator< Map.Entry< String, IMogoMarker > > entryIterator = mMarkersCaches.entrySet().iterator();
for ( int i = 0; i < size; i++ ) {
CloudRoadData cloudRoadData = newDiffSet.get( i );
String uniqueKey = cloudRoadData.getUniqueKey();
Map.Entry< String, IMogoMarker > entry = entryIterator.next();
entryIterator.remove();
CloudRoadData old = mLastPositions.remove( entry.getKey() );
IMogoMarker marker = entry.getValue();
if ( marker == null ) {
continue;
}
// 更新资源内容
if ( old == null || old.getType() != cloudRoadData.getType() ) {
String resIdVal;
int resId = getModelRes( cloudRoadData.getType() );
resIdVal = resId + "";
String resName = mMarkerCachesResMd5Values.get( resIdVal );
if ( !TextUtils.isEmpty( resName ) ) {
if ( !TextUtils.equals( resName, marker.getMarkerResName() ) ) {
marker.use3DResource( resName );
}
} else {
resName = marker.use3DResource( resId );
mMarkerCachesResMd5Values.put( resIdVal, resName );
}
}
renderSnapshotOneFrame( marker, uniqueKey, cloudRoadData, newMarkersCaches );
}
if (newDiffSetSize > 0) {
// 复用过后还需新增的 marker
for ( int i = size; i < newDiffSetSize; i++ ) {
CloudRoadData cloudRoadData = newDiffSet.get( i );
String uniqueKey = cloudRoadData.getUniqueKey();
IMogoMarker marker = drawSnapshotDataMarker( cloudRoadData );
if ( marker == null ) {
for (int i = 0; i < newDiffSetSize; i++) {
SocketDownData.CloudRoadDataProto cloudRoadData = newDiffSet.get(i);
String uniqueKey = cloudRoadData.getUuid();
IMogoMarker marker = drawSnapshotDataMarker(cloudRoadData);
if (marker == null) {
continue;
}
renderSnapshotOneFrame( marker, uniqueKey, cloudRoadData, newMarkersCaches );
renderSnapshotOneFrame(marker, uniqueKey, cloudRoadData, newMarkersCaches);
}
}
if ( cachedMarkerSize - size > 0 ) {
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
mMarkersCaches.putAll(newMarkersCaches);
// 移除超时 marker
delayRemoveUselessMarker();
removeUselessLastRecord();
Log.d("云端数据延时绘制", "render 接收数据 -> 处理结束 " + TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - start)) + "ms");
}
/**
* todo 后面涉及到此类变化的数据均改动
*
* @param marker {@link IMogoMarker}
* @param cloudRoadDataProto {@link SocketDownData.CloudRoadDataProto}
*/
private void updateCacheMarkerRes(IMogoMarker marker, SocketDownData.CloudRoadDataProto cloudRoadDataProto) {
String resIdVal;
int resId = getModelRes(cloudRoadDataProto.getType());
resIdVal = resId + "";
String resName = mMarkerCachesResMd5Values.get(resIdVal);
if (!TextUtils.isEmpty(resName)) {
if (!TextUtils.equals(resName, marker.getMarkerResName())) {
marker.use3DResource(resName);
}
} else {
resName = marker.use3DResource(resId);
mMarkerCachesResMd5Values.put(resIdVal, resName);
}
}
sendMessage( MSG_REMOVE_DIRTY_MARKERS, mMarkersCaches );
mMarkersCaches = newMarkersCaches;
private void delayRemoveUselessMarker() {
if (mMarkersCaches.isEmpty()) {
return;
}
IMogoADASController adasControllerApi = MogoApisHandler.getInstance().getApis().getAdasControllerApi();
if (TextUtils.isEmpty(adasControllerApi.getSatelliteTime())) {
return;
}
Iterator<IMogoMarker> iterator = mMarkersCaches.values().iterator();
while (iterator.hasNext()) {
IMogoMarker result = iterator.next();
SocketDownData.CloudRoadDataProto proto = ((SocketDownData.CloudRoadDataProto) result.getObject());
if(proto == null){ // 后续有业务数据在操作,更新数据,不做处理
continue;
}
long internal = Long.parseLong(adasControllerApi.getSatelliteTime()) - proto.getSatelliteTime();
Log.d("MogoArrow", "delayRemoveUselessMarker uuid : " + proto.getUuid()
+ " localTime : " + adasControllerApi.getSatelliteTime()
+ " originTime : " + proto.getSatelliteTime()
+ " internal : " + internal);
if (internal > 5000) {
iterator.remove();
result.destroy();
}
}
}
private void removeUselessLastRecord() { // todo 最好重新设计一个数据结构用于多线程数据过期失效的场景参见redis数据过期
if (mLastPositions.isEmpty()) {
return;
}
IMogoADASController adasControllerApi = MogoApisHandler.getInstance().getApis().getAdasControllerApi();
if (TextUtils.isEmpty(adasControllerApi.getSatelliteTime()) || adasControllerApi.getSatelliteTime().equals("0")) {
return;
}
Iterator<SocketDownData.CloudRoadDataProto> iterator = mLastPositions.values().iterator();
Log.d("EmArrow", "removeUselessLastRecord size : " + mLastPositions.size());
while (iterator.hasNext()) {
SocketDownData.CloudRoadDataProto result = iterator.next();
long internal = Long.parseLong(adasControllerApi.getSatelliteTime()) - result.getSatelliteTime();
if (internal > 3000) {
iterator.remove();
}
}
}
/**
* 判断类型、uuid 等
*
* @param cloudRoadData {@link CloudRoadData}
* @param cloudRoadData {@link SocketDownData.CloudRoadDataProto}
* @return isUselessValue
*/
private boolean isUselessValue( CloudRoadData cloudRoadData ) {
if ( cloudRoadData == null ) {
private boolean isUselessValue(SocketDownData.CloudRoadDataProto cloudRoadData) {
if (cloudRoadData == null) {
return true;
}
if ( !isRenderType( cloudRoadData.getType() ) ) {
if (nonRenderType(cloudRoadData.getType())) {
return true;
}
String uniqueKey = cloudRoadData.getUniqueKey();
String uniqueKey = cloudRoadData.getUuid();
return TextUtils.isEmpty(uniqueKey);
}
/**
* 绘制某个物体的一个数据
*
* @param cloudRoadData {@link CloudRoadData}
* @param cloudRoadData {@link SocketDownData.CloudRoadDataProto}
* @param newSnapshotCaches 缓存数据
*/
private void renderSnapshotOneFrame( IMogoMarker marker, String uniqueKey, final CloudRoadData cloudRoadData, Map< String, IMogoMarker > newSnapshotCaches ) {
private void renderSnapshotOneFrame(IMogoMarker marker, String uniqueKey, SocketDownData.CloudRoadDataProto cloudRoadData, Map<String, IMogoMarker> newSnapshotCaches) {
final long start = System.nanoTime();
SocketDownData.CloudRoadDataProto lastPosition = mLastPositions.remove(uniqueKey);
// 道路吸附
// double lastLon = -1;
// double lastLat = -1;
// if (lastPosition != null) {
// lastLon = lastPosition.getWgslon();
// lastLat = lastPosition.getWgslat();
// }
// double[] matchLonLat = getMatchLonLat(cloudRoadData.getUuid(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading(), lastLon, lastLat);
// SocketDownData.CloudRoadDataProto.Builder builder = cloudRoadData.toBuilder();
// builder.setWgslon(matchLonLat[0]);
// builder.setWgslat(matchLonLat[1]);
// cloudRoadData = builder.build();
final long start = System.currentTimeMillis();
CloudRoadData lastPosition = mLastPositions.remove( uniqueKey );
double lastLon = -1;
double lastLat = -1;
if ( lastPosition != null ) {
lastLon = lastPosition.getWgslon();
lastLat = lastPosition.getWgslat();
}
double[] matchLonLat = getMatchLonLat( cloudRoadData.getUniqueKey(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading(), lastLon, lastLat );
cloudRoadData.setWgslon( matchLonLat[0] );
cloudRoadData.setWgslat( matchLonLat[1] );
mLastPositions.put( uniqueKey, cloudRoadData );
newSnapshotCaches.put( uniqueKey, marker );
if ( lastPosition != null ) {
long interval = computeAnimDuration( lastPosition.getSystemTime(), cloudRoadData.getSystemTime(), lastPosition.getSatelliteTime(), cloudRoadData.getSatelliteTime() );
final MogoLatLng point = new MogoLatLng( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() );
long cost = System.currentTimeMillis() - start;
final long intervalRef = interval - cost;
SimpleHandlerThreadPool.getInstance().postRender( () -> marker.addDynamicAnchorPosition( point, ( float ) cloudRoadData.getHeading(), intervalRef ));
} else {
marker.setRotateAngle( ( ( float ) cloudRoadData.getHeading() ) );
marker.setPosition( cloudRoadData.getWgslat(), cloudRoadData.getWgslon() );
}
marker.setAnchorColor( getModelRenderColor( cloudRoadData.getType(), cloudRoadData.getSpeed(), cloudRoadData.getWgslon(), cloudRoadData.getWgslat(), cloudRoadData.getHeading() ) );
if ( shouldShowSpeed( cloudRoadData.getType() ) ) {
Message msg = mRenderThreadHandler.obtainMessage();
SpeedData obj = new SpeedData();
obj.context = mContext;
obj.marker = marker;
obj.speed = cloudRoadData.getSpeed();
msg.obj = obj;
msg.what = MSG_DISPLAY_SPEED;
msg.sendToTarget();
mLastPositions.put(uniqueKey, cloudRoadData);
long interval = 45;
if (lastPosition != null) {
interval = computeAnimDuration(lastPosition.getSatelliteTime(), cloudRoadData.getSatelliteTime());
}
final MogoLatLng point = new MogoLatLng(cloudRoadData.getWgslat(), cloudRoadData.getWgslon());
long cost = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
final long intervalRef = interval - cost;
marker.addDynamicAnchorPosition(point, (float) cloudRoadData.getHeading(), intervalRef);
marker.setAnchorColor(getModelRenderColor(cloudRoadData.getType(), cloudRoadData.getFromType(), 1));
newSnapshotCaches.put(uniqueKey, marker);
// if (shouldShowSpeed(cloudRoadData.getType())) {
// Message msg = mRenderThreadHandler.obtainMessage();
// msg.obj = new SpeedData(marker
// , cloudRoadData.getSpeed()
// , cloudRoadData.getUuid()
// , cloudRoadData.getType()
// , cloudRoadData.getHeading()
// , MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode());
// msg.what = MSG_DISPLAY_SPEED;
// msg.sendToTarget();
// }
Log.d("云端数据延时", "render 刷新一台车 cost : " + TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - start)));
}
/**
* 过滤数据
* 过滤数据,对数据补点
*
* @param in 输入集合
* @param out 输出集合
*/
private void prepareData( List< CloudRoadData > in, List< CloudRoadData > out ) {
filterData( in );
out.addAll( in );
private void prepareData(List<SocketDownData.CloudRoadDataProto> in, List<SocketDownData.CloudRoadDataProto> out) {
// foreCastPoint(in, out);
out.addAll(in);
}
private final static String FORECAST = "snapshotForecast";
/**
* vr 模式下显示合并数据,否则只显示 mogo 车辆上报的数据
* 基于云平台下发的数据点速度预测当前位置和距离自车距离
*
* @param data 道路数据集合
* @param in 数据源
*/
private void filterData( List< CloudRoadData > data ) {
if ( data == null || data.isEmpty() ) {
return;
}
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
return;
}
List< CloudRoadData > newList = new ArrayList<>();
for ( CloudRoadData cloudRoadData : data ) {
if ( cloudRoadData.getFromType() != CloudRoadData.FROM_MY_LOCATION ) {
continue;
private void foreCastPoint(List<SocketDownData.CloudRoadDataProto> in, List<SocketDownData.CloudRoadDataProto> out) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
for (SocketDownData.CloudRoadDataProto proto : in) {
SocketDownData.CloudRoadDataProto.Builder builder = proto.toBuilder();
Log.d(FORECAST, "ready to foreCast current uuid : " + proto.getUuid());
long internal = getCurSatelliteTime() - builder.getSatelliteTime();
if (internal <= 0) {
Log.d(FORECAST, "time internal less than 0 , uuid : " + proto.getUuid());
out.add(proto);
continue;
}
long startTime = System.currentTimeMillis();
// 预测点
Log.d(FORECAST, "time internal : " + internal + " speed : " + proto.getSpeed());
double foreCastDistance = proto.getSpeed() * internal / 1000;
Log.d(FORECAST, "foreCastDistance : " + foreCastDistance);
MogoLatLng mogoLatLng = new MogoLatLng(proto.getWgslat(), proto.getWgslon());
MogoLatLng foreCastMogoLatLon = Trigonometric.getNewLocation(mogoLatLng, foreCastDistance, proto.getHeading());
// 计算与自车距离
float distanceFromSelf = CoordinateUtils.calculateLineDistance(getCurCoordinates()[0], getCurCoordinates()[1]
, foreCastMogoLatLon.getLon(), foreCastMogoLatLon.getLat());
long foreCastInternal = System.currentTimeMillis() - startTime;
Log.d(FORECAST, "foreCastInternal :" + foreCastInternal); //todo 耗时1~2毫秒 需要测试是否由于补点算法造成
builder.setWgslat(foreCastMogoLatLon.getLat());
builder.setWgslon(foreCastMogoLatLon.getLon());
builder.setSatelliteTime(getCurSatelliteTime() - foreCastInternal);
builder.setDistance(distanceFromSelf);
proto = builder.build();
out.add(proto);
}
newList.add( cloudRoadData );
}
data.clear();
data.addAll( newList );
}
/**
* 绑定点击事件
*/
public void bindClickListener( IMogoMarker marker ) {
if ( marker == null || marker.isDestroyed() ) {
public void bindClickListener(IMogoMarker marker) {
if (marker == null || marker.isDestroyed()) {
return;
}
marker.setOnMarkerClickListener( this );
marker.setOnMarkerClickListener(this);
}
/**
@@ -354,45 +391,46 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
* @param data 道路数据
* @return {@link IMogoMarker}
*/
public IMogoMarker drawSnapshotDataMarker( CloudRoadData data ) {
if ( data == null ) {
public IMogoMarker drawSnapshotDataMarker(SocketDownData.CloudRoadDataProto data) {
long start = System.nanoTime();
if (data == null) {
return null;
}
MogoMarkerOptions options = new MogoMarkerOptions()
.owner( DataTypes.TYPE_MARKER_CLOUD_DATA )
.anchor( 0.5f, 0.5f )
.rotate( ( float ) data.getHeading() )
.object( data )
.gps( true )
.controlAngle( true )
.position( new MogoLatLng( data.getWgslat(), data.getWgslon() ) );
.owner(TYPE_MARKER_CLOUD_DATA)
.anchor(0.5f, 0.5f)
.rotate((float) data.getHeading())
.object(data)
.gps(true)
.controlAngle(true)
.position(new MogoLatLng(data.getWgslat(), data.getWgslon()));
String resIdVal;
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
options.set3DMode( true );
options.anchorColor( getModelRenderColor( data.getType(), data.getSpeed(), data.getWgslon(), data.getWgslat(), data.getHeading() ) );
int resId = getModelRes( data.getType() );
if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
options.set3DMode(true);
options.anchorColor(getModelRenderColor(data.getType(), data.getFromType(), 1));
int resId = getModelRes(data.getType());
resIdVal = resId + "";
options.resName( mMarkerCachesResMd5Values.get( resIdVal ) );
options.icon3DRes( resId );
options.resName(mMarkerCachesResMd5Values.get(resIdVal));
options.icon3DRes(resId);
} else {
options.set3DMode( false );
View view = inflateView( data );
options.icon( view );
options.set3DMode(false);
View view = inflateView(data);
options.icon(view);
resIdVal = view.getId() + "";
}
IMogoMarker marker = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMarkerManager( mContext ).addMarker( DataTypes.TYPE_MARKER_CLOUD_DATA, options );
cacheMarkerIconResMd5Val( resIdVal, marker );
IMogoMarker marker = MogoApisHandler.getInstance().getApis().getMapServiceApi().getMarkerManager(mContext).addMarker(TYPE_MARKER_CLOUD_DATA, options);
cacheMarkerIconResMd5Val(resIdVal, marker);
if ( !TextUtils.isEmpty( data.getSn() ) ) {
bindClickListener( marker );
if (!TextUtils.isEmpty(data.getSn())) {
bindClickListener(marker);
}
Log.d("云端数据延时", "创建一个新 marker cost : " + TimeUnit.NANOSECONDS.toMillis((System.nanoTime() - start)));
return marker;
}
public String get3DCacheId( String resIdVal ) {
return mMarkerCachesResMd5Values.get( resIdVal );
public String get3DCacheId(String resIdVal) {
return mMarkerCachesResMd5Values.get(resIdVal);
}
/**
@@ -401,12 +439,12 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
* @param data 道路数据
* @return marker
*/
public View inflateView( CloudRoadData data ) {
View rootView = LayoutInflater.from( AbsMogoApplication.getApp() ).inflate( R.layout.module_commons_layout_car, null );
ImageView iv = rootView.findViewById( R.id.module_commons_marker_car_model );
int viewIdLike = get2DModel( data );
iv.setImageResource( viewIdLike );
rootView.setId( viewIdLike );
public View inflateView(SocketDownData.CloudRoadDataProto data) {
View rootView = LayoutInflater.from(AbsMogoApplication.getApp()).inflate(R.layout.module_commons_layout_car, null);
ImageView iv = rootView.findViewById(R.id.module_commons_marker_car_model);
int viewIdLike = get2DModel(data);
iv.setImageResource(viewIdLike);
rootView.setId(viewIdLike);
return rootView;
}
@@ -416,71 +454,71 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic
* @param data 道路数据
* @return 2D贴图id
*/
private int get2DModel( CloudRoadData data ) {
switch ( data.getFromType() ) {
case CloudRoadData.FROM_ADAS:
case CloudRoadData.FROM_ROAD_UNIT:
case CloudRoadData.FROM_MY_LOCATION:
private int get2DModel(SocketDownData.CloudRoadDataProto data) {
switch (data.getFromType()) {
case SocketDownDataHelper.FROM_ADAS:
case SocketDownDataHelper.FROM_ROAD_UNIT:
case SocketDownDataHelper.FROM_MY_LOCATION:
default:
return R.drawable.icon_map_marker_car_gray;
}
}
@Override
public boolean onMarkerClicked( IMogoMarker marker ) {
if ( marker != null && !marker.isDestroyed() ) {
if ( marker.getObject() instanceof CloudRoadData ) {
showCarCallPanel( ( ( CloudRoadData ) marker.getObject() ) );
public boolean onMarkerClicked(IMogoMarker marker) {
if (marker != null && !marker.isDestroyed()) {
if (marker.getObject() instanceof SocketDownData.CloudRoadDataProto) {
showCarCallPanel(((SocketDownData.CloudRoadDataProto) marker.getObject()));
}
}
return true;
}
/**
* 展示用户信息米娜
* 展示用户信息
*
* @param data 道路数据
*/
private void showCarCallPanel( CloudRoadData data ) {
private void showCarCallPanel(SocketDownData.CloudRoadDataProto data) {
MogoDriverInfo driverInfo = new MogoDriverInfo();
driverInfo.setLat( data.getLat() );
driverInfo.setLon( data.getLon() );
driverInfo.setSn( data.getSn() );
driverInfo.setLat(data.getLat());
driverInfo.setLon(data.getLon());
driverInfo.setSn(data.getSn());
ICarsChattingProvider carChatting = CallChatApi.getInstance().getApiProvider();
if ( carChatting != null ) {
if (carChatting != null) {
try {
carChatting.showUserWindow( TAG, driverInfo, mContext );
} catch ( Exception e ) {
Logger.e( TAG, e, "showCarCallPanel" );
carChatting.showUserWindow(TAG, driverInfo, mContext);
} catch (Exception e) {
Logger.e(TAG, e, "showCarCallPanel");
}
}
}
public void changeIconResourceIfNecessary( CloudRoadData cloudRoadData, IMogoMarker marker ) {
if ( isChangeCarModeStatus() ) {
setChangeCarModeStatus( false );
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
marker.getMogoMarkerOptions().set3DMode( true );
int resId = getModelRes( cloudRoadData.getType() );
String resName = get3DCacheId( resId + "" );
if ( TextUtils.isEmpty( resName ) ) {
marker.use3DResource( resId );
cacheMarkerIconResMd5Val( resId + "", marker );
public void changeIconResourceIfNecessary(SocketDownData.CloudRoadDataProto cloudRoadData, IMogoMarker marker) {
if (isChangeCarModeStatus()) {
setChangeCarModeStatus(false);
if (MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()) {
marker.getMogoMarkerOptions().set3DMode(true);
int resId = getModelRes(cloudRoadData.getType());
String resName = get3DCacheId(resId + "");
if (TextUtils.isEmpty(resName)) {
marker.use3DResource(resId);
cacheMarkerIconResMd5Val(resId + "", marker);
} else {
marker.use3DResource( resName );
marker.use3DResource(resName);
}
} else {
marker.getMogoMarkerOptions().set3DMode( false );
View view = inflateView( cloudRoadData );
marker.getMogoMarkerOptions().set3DMode(false);
View view = inflateView(cloudRoadData);
int resId = view.getId();
String resName = get3DCacheId( resId + "" );
if ( TextUtils.isEmpty( resName ) ) {
marker.setIcon( ViewUtils.fromView( view ) );
cacheMarkerIconResMd5Val( resId + "", marker );
String resName = get3DCacheId(resId + "");
if (TextUtils.isEmpty(resName)) {
marker.setIcon(ViewUtils.fromView(view));
cacheMarkerIconResMd5Val(resId + "", marker);
} else {
marker.use2DResource( resName );
marker.use2DResource(resName);
}
}
}

View File

@@ -0,0 +1,73 @@
package com.mogo.module.common.drawer.bean;
import com.mogo.map.marker.IMogoMarker;
/**
* 速度显示对象
*/
public class SpeedData {
public IMogoMarker marker;
public double speed;
public String uuid;
public int type;
public double heading;
public boolean isVrMode;
public SpeedData(IMogoMarker marker, double speed, String uuid, int type, double heading, boolean isVrMode) {
this.marker = marker;
this.speed = speed;
this.uuid = uuid;
this.type = type;
this.heading = heading;
this.isVrMode = isVrMode;
}
public IMogoMarker getMarker() {
return marker;
}
public void setMarker(IMogoMarker marker) {
this.marker = marker;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public double getHeading() {
return heading;
}
public void setHeading(double heading) {
this.heading = heading;
}
public boolean getIsVrMode() {
return isVrMode;
}
public void setIsVrMode(boolean isVrMode) {
this.isVrMode = isVrMode;
}
}

Binary file not shown.

Binary file not shown.