add new func of ezhou airport and upgrade the aiSdkVersion to fit demo server
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
BIN
modules/mogo-module-common/src/main/res/raw/daba.n3d
Normal file
BIN
modules/mogo-module-common/src/main/res/raw/daba.n3d
Normal file
Binary file not shown.
BIN
modules/mogo-module-common/src/main/res/raw/tache.n3d
Normal file
BIN
modules/mogo-module-common/src/main/res/raw/tache.n3d
Normal file
Binary file not shown.
BIN
modules/mogo-module-common/src/main/res/raw/tachexiaoche.n3d
Normal file
BIN
modules/mogo-module-common/src/main/res/raw/tachexiaoche.n3d
Normal file
Binary file not shown.
BIN
modules/mogo-module-common/src/main/res/raw/zixingche.n3d
Normal file
BIN
modules/mogo-module-common/src/main/res/raw/zixingche.n3d
Normal file
Binary file not shown.
Reference in New Issue
Block a user