From def4004885e3e150ff6bf06c8824e17c23795ecc Mon Sep 17 00:00:00 2001 From: tongchenfei Date: Thu, 4 Mar 2021 15:25:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Esnapshot=E5=A4=9A=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mogo/map/impl/custom/AMapViewWrapper.java | 35 ++-- .../mogo/module/common/drawer/BaseDrawer.java | 10 +- .../common/drawer/SnapshotSetDataDrawer.java | 46 ++--- .../common/utils/SimpleHandlerThreadPool.java | 186 ++++++++++++++++++ .../service/intent/MockIntentHandler.java | 44 ++++- 5 files changed, 280 insertions(+), 41 deletions(-) create mode 100644 modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/SimpleHandlerThreadPool.java diff --git a/libraries/map-custom/src/main/java/com/mogo/map/impl/custom/AMapViewWrapper.java b/libraries/map-custom/src/main/java/com/mogo/map/impl/custom/AMapViewWrapper.java index 85c7509ef5..8abeebce04 100644 --- a/libraries/map-custom/src/main/java/com/mogo/map/impl/custom/AMapViewWrapper.java +++ b/libraries/map-custom/src/main/java/com/mogo/map/impl/custom/AMapViewWrapper.java @@ -57,6 +57,7 @@ import com.zhidaoauto.map.sdk.open.marker.MarkerOptions; import com.zhidaoauto.map.sdk.open.marker.MultiPointOverlayOptions; import com.zhidaoauto.map.sdk.open.marker.OnInfoWindowClickListener; import com.zhidaoauto.map.sdk.open.marker.OnMarkClickListener; +import com.zhidaoauto.map.sdk.open.poyline.PolylineOptions; import com.zhidaoauto.map.sdk.open.query.LonLatPoint; import com.zhidaoauto.map.sdk.open.tools.MapTools; import com.zhidaoauto.map.sdk.open.view.MapAutoView; @@ -1020,7 +1021,7 @@ public class AMapViewWrapper implements IMogoMapView, e.printStackTrace(); } } - + private float lastRoadId; @Override public double[] matchRoad( double lon, double lat, double angle, boolean isGpsLocation, boolean isRTK ) { double wgs[] = CoordinateUtils.transformGcj02toWgs84( lat, lon ); @@ -1032,19 +1033,29 @@ public class AMapViewWrapper implements IMogoMapView, // return CoordinateUtils.transformWgsToGcj( matchedPoint[1], matchedPoint[0] ); matchedPoint = CoordinateUtils.transformWgsToGcj( matchedPoint[1], matchedPoint[0] ); - MarkerOptions options - = new MarkerOptions(); - options.markerIcon( R.drawable.red ) - .position( new LonLatPoint( matchedPoint[0], matchedPoint[1] ) ) - .setGps( false ); - mMapView.getMapAutoViewHelper().addMarker( options ); - MarkerOptions options2 = new MarkerOptions(); - options2.markerIcon( R.drawable.blue ) - .position( new LonLatPoint( lon, lat ) ) - .setGps( true ); - mMapView.getMapAutoViewHelper().addMarker( options2 ); +// MarkerOptions options +// = new MarkerOptions(); +// options.markerIcon( R.drawable.red ) +// .position( new LonLatPoint( matchedPoint[0], matchedPoint[1] ) ) +// .setGps( false ); +// mMapView.getMapAutoViewHelper().addMarker( options ); +// +// MarkerOptions options2 = new MarkerOptions(); +// options2.markerIcon( R.drawable.blue ) +// .position( new LonLatPoint( lon, lat ) ) +// .setGps( true ); +// mMapView.getMapAutoViewHelper().addMarker( options2 ); +// if(lastRoadId != singlePointRoadInfo.getRoadId()) { +// lastRoadId = singlePointRoadInfo.getRoadId(); +// PolylineOptions lineOptions = new PolylineOptions(); +// lineOptions.setGps(true) +// .lonLatPoints(singlePointRoadInfo.getCoords()) +// .color(Color.RED) +// .lineWidth(10); +// mMapView.getMapAutoViewHelper().drawLine(lineOptions); +// } return matchedPoint; } return null; diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/BaseDrawer.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/BaseDrawer.java index 20dc2362f8..599b5f9b0d 100644 --- a/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/BaseDrawer.java +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/BaseDrawer.java @@ -78,7 +78,7 @@ class BaseDrawer { * @param msg * @param data */ - protected void sendMessage( int msg, Object data ) { + public void sendMessage( int msg, Object data ) { if ( mWorkThreadHandler == null ) { initWorkThreadHandler(); } @@ -94,7 +94,7 @@ class BaseDrawer { * @param type * @return */ - protected boolean isCarType( int type ) { + public boolean isCarType( int type ) { AdasRecognizedType recognizedType = AdasRecognizedType.valueFrom( type ); if ( recognizedType == AdasRecognizedType.classIdCar || recognizedType == AdasRecognizedType.classIdTrafficBus @@ -115,7 +115,7 @@ class BaseDrawer { * @param speed * @param isVrMode */ - protected void showSelfSpeed( Context context, IMogoMarker mogoMarker, double speed, boolean isVrMode ) { + public void showSelfSpeed( Context context, IMogoMarker mogoMarker, double speed, boolean isVrMode ) { if ( mogoMarker == null || mogoMarker.isDestroyed() ) { return; } @@ -189,7 +189,7 @@ class BaseDrawer { * @param isRtk * @return */ - protected double[] matchRoad( double lon, double lat, double angle, boolean isRtk ) { + public double[] matchRoad( double lon, double lat, double angle, boolean isRtk ) { return MogoApisHandler.getInstance() .getApis() .getMapServiceApi() @@ -206,7 +206,7 @@ class BaseDrawer { * @param curSatelliteTime * @return */ - protected long computeAnimDuration( long lastSystemTime, long curSystemTime, long lastSatelliteTime, long curSatelliteTime ) { + public long computeAnimDuration( long lastSystemTime, long curSystemTime, long lastSatelliteTime, long curSatelliteTime ) { long systemTimeInterval = curSystemTime - lastSystemTime - 25; long satelliteTimeInterval = curSatelliteTime - lastSatelliteTime - 25; long interval = systemTimeInterval < satelliteTimeInterval || satelliteTimeInterval == 0 ? systemTimeInterval : satelliteTimeInterval; diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/SnapshotSetDataDrawer.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/SnapshotSetDataDrawer.java index 13c39060ef..b5833502f6 100644 --- a/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/SnapshotSetDataDrawer.java +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/drawer/SnapshotSetDataDrawer.java @@ -2,6 +2,7 @@ package com.mogo.module.common.drawer; import android.content.Context; import android.text.TextUtils; +import android.util.ArrayMap; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; @@ -16,6 +17,7 @@ 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.kt.ScopeManager; +import com.mogo.module.common.utils.SimpleHandlerThreadPool; import com.mogo.realtime.entity.CloudRoadData; import com.mogo.realtime.entity.MogoSnapshotSetData; import com.mogo.service.statusmanager.IMogoStatusChangedListener; @@ -129,6 +131,8 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic return false; } + Map cloudKeyCache = new ArrayMap<>(); + /** * mogo 他车、mogo 他车识别的社会车辆、路边单元识别的车辆 * @@ -142,29 +146,24 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic List< CloudRoadData > allDatumsList = new ArrayList<>(); prepareData( data.getAllList(), allDatumsList ); - Map< String, IMogoMarker > newAdasRecognizedMarkersCaches = new ConcurrentHashMap<>(); + Map< String, String > newAdasRecognizedMarkersCaches = new ArrayMap<>(allDatumsList.size()); for ( CloudRoadData cloudRoadData : allDatumsList ) { - -// double[] matchedPoint = matchRoad( cloudRoadData.getLon(), -// cloudRoadData.getLat(), -// cloudRoadData.getHeading(), -// true -// ); -// if ( matchedPoint != null ) { -// cloudRoadData.setLon( matchedPoint[0] ); -// cloudRoadData.setLat( matchedPoint[1] ); -// } - ScopeManager.INSTANCE.mainScope( () -> { - rendCarOneFrame( cloudRoadData, newAdasRecognizedMarkersCaches ); - } ); + cloudKeyCache.remove(cloudRoadData.getUniqueKey()); +// newAdasRecognizedMarkersCaches.put(cloudRoadData.getUniqueKey(), cloudRoadData.getUniqueKey()); + SimpleHandlerThreadPool.getInstance().post(cloudRoadData); +// ScopeManager.INSTANCE.mainScope( () -> { +// rendCarOneFrame( cloudRoadData, newAdasRecognizedMarkersCaches ); +// } ); } - ScopeManager.INSTANCE.mainScope( () -> { - sendMessage( MSG_REMOVE_DIRTY_MARKERS, mCloudSnapshotMarkersCaches ); - mCloudSnapshotMarkersCaches = newAdasRecognizedMarkersCaches; - } ); + SimpleHandlerThreadPool.getInstance().removeDirtyMarker(cloudKeyCache.values()); + cloudKeyCache = newAdasRecognizedMarkersCaches; +// ScopeManager.INSTANCE.mainScope( () -> { +// sendMessage( MSG_REMOVE_DIRTY_MARKERS, mCloudSnapshotMarkersCaches ); +// mCloudSnapshotMarkersCaches = newAdasRecognizedMarkersCaches; +// } ); } - private void rendCarOneFrame( CloudRoadData cloudRoadData, Map< String, IMogoMarker > newAdasRecognizedMarkersCaches ) { + public void rendCarOneFrame( CloudRoadData cloudRoadData, Map< String, IMogoMarker > newAdasRecognizedMarkersCaches ) { if ( cloudRoadData == null ) { return; @@ -196,8 +195,9 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic bindClickListener( marker ); } } - - newAdasRecognizedMarkersCaches.put( uniqueKey, marker ); + if(newAdasRecognizedMarkersCaches != null) { + newAdasRecognizedMarkersCaches.put(uniqueKey, marker); + } // // if ( mChangeCarModeStatus ) { // mIsVrMode = MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode(); @@ -263,7 +263,7 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic /** * 绑定点击事件 */ - private void bindClickListener( IMogoMarker marker ) { + public void bindClickListener( IMogoMarker marker ) { if ( marker == null || marker.isDestroyed() ) { return; } @@ -276,7 +276,7 @@ public class SnapshotSetDataDrawer extends BaseDrawer implements IMogoMarkerClic * @param data * @return */ - private IMogoMarker drawSnapshotDataMarker( CloudRoadData data ) { + public IMogoMarker drawSnapshotDataMarker( CloudRoadData data ) { if ( data == null ) { return null; } diff --git a/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/SimpleHandlerThreadPool.java b/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/SimpleHandlerThreadPool.java new file mode 100644 index 0000000000..1052712b76 --- /dev/null +++ b/modules/mogo-module-common/src/main/java/com/mogo/module/common/utils/SimpleHandlerThreadPool.java @@ -0,0 +1,186 @@ +package com.mogo.module.common.utils; + +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; +import android.text.TextUtils; +import android.util.ArrayMap; + +import com.mogo.commons.AbsMogoApplication; +import com.mogo.map.MogoLatLng; +import com.mogo.map.marker.IMogoMarker; +import com.mogo.module.common.MogoApisHandler; +import com.mogo.module.common.drawer.AdasRecognizedResultDrawer; +import com.mogo.module.common.drawer.SnapshotSetDataDrawer; +import com.mogo.realtime.entity.CloudRoadData; +import com.mogo.utils.logger.Logger; + +import java.util.Collection; +import java.util.Map; + +import static com.mogo.module.common.drawer.BaseDrawer.MSG_REMOVE_DIRTY_MARKERS; + +/** + * 简单HandlerThread线程池实现 + * + * @author tongchenfei + */ +public class SimpleHandlerThreadPool { + private static final String TAG = "SimpleHandlerThreadPool"; + private HandlerThread renderThread = new HandlerThread("one-frame-render-thread"); + private Handler renderHandler; + private SimpleHandlerThreadPool() { + renderThread.start(); + renderHandler = new Handler(renderThread.getLooper()); + } + + private static final SimpleHandlerThreadPool INSTANCE = new SimpleHandlerThreadPool(); + + public static SimpleHandlerThreadPool getInstance() { + return INSTANCE; + } + + /** + * 默认线程数量 + */ + private static final int DEFAULT_THREAD_COUNT = 3; + + private int threadCount = DEFAULT_THREAD_COUNT; + + public void setThreadCount(int threadCount) { + this.threadCount = threadCount; + } + + Map dataHandlerMap = new ArrayMap<>(); + Map handlerPool = new ArrayMap<>(); + private int lastUseThreadId = -1; + + public void post(CloudRoadData cloudRoadData) { + String uuid = cloudRoadData.getUniqueKey(); + Message msg; + if (dataHandlerMap.containsKey(uuid)) { + msg = dataHandlerMap.get(uuid).obtainMessage(); + } else { + if (handlerPool.size() < threadCount) { + // 新开线程 + lastUseThreadId = handlerPool.size(); + HandlerThread thread = new HandlerThread("one-frame-work-thread-" + handlerPool.size()); + thread.start(); + WorkHandler handler = new WorkHandler(thread.getLooper()); + handlerPool.put(handlerPool.size(), handler); + dataHandlerMap.put(uuid, handler); + msg = handler.obtainMessage(); + } else { + // 复用线程 + if (lastUseThreadId == threadCount - 1) { + lastUseThreadId = 0; + } else { + lastUseThreadId++; + } + WorkHandler handler = handlerPool.get(lastUseThreadId); + dataHandlerMap.put(uuid, handler); + msg = handler.obtainMessage(); + } + } + msg.obj = cloudRoadData; + msg.sendToTarget(); + } + + public void removeDirtyMarker(Collection keys) { + for (WorkHandler handler : handlerPool.values()) { + handler.removeDirtyMarker(keys); + } + } + + class WorkHandler extends Handler { + public WorkHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + CloudRoadData cloudRoadData = (CloudRoadData) msg.obj; + rendCarOneFrame(cloudRoadData); + } + + private final Map markerCache = new ArrayMap<>(); + private final Map roadDataCache = new ArrayMap<>(); + private final Map lastExecutionTimeCache = new ArrayMap<>(); + + private void rendCarOneFrame(CloudRoadData cloudRoadData) { + if (cloudRoadData == null) { + return; + } + + // 暂时只显示车辆 + if (TextUtils.isEmpty(cloudRoadData.getSn())) { + if (!SnapshotSetDataDrawer.getInstance().isCarType(cloudRoadData.getType())) { + return; + } + } + + String uniqueKey = cloudRoadData.getUniqueKey(); + if (TextUtils.isEmpty(uniqueKey) + // 本地过滤重复下发的adas识别车辆 + || AdasRecognizedResultDrawer.getInstance().hasCached(uniqueKey)) { + return; + } + IMogoMarker marker = markerCache.get(uniqueKey); + CloudRoadData lastPosition = roadDataCache.put(uniqueKey, cloudRoadData); + if (marker == null || marker.isDestroyed()) { + marker = SnapshotSetDataDrawer.getInstance().drawSnapshotDataMarker(cloudRoadData); + if (marker == null) { + return; + } + markerCache.put(uniqueKey, marker); + if (!TextUtils.isEmpty(cloudRoadData.getSn())) { + SnapshotSetDataDrawer.getInstance().bindClickListener(marker); + } + } + + if(cloudRoadData.getFromType() == CloudRoadData.FROM_MY_LOCATION) { + + double[] matchedPoint = SnapshotSetDataDrawer.getInstance().matchRoad(cloudRoadData.getLon(), + cloudRoadData.getLat(), + cloudRoadData.getHeading(), + true + ); + if (matchedPoint != null) { + cloudRoadData.setLon(matchedPoint[0]); + cloudRoadData.setLat(matchedPoint[1]); + } + } + + final IMogoMarker finalMarker = marker; + Logger.d(TAG, "work in " + Thread.currentThread().getName()); + renderHandler.post(()->{ + // 由于地图现在不支持addDynamicAnchorPosition并发,所以工作线程仅做相关计算,真正绘制发送到另外一条绘制线程中做 + if (lastPosition != null && !lastPosition.equals(cloudRoadData)) { + long interval = SnapshotSetDataDrawer.getInstance().computeAnimDuration(lastPosition.getSystemTime(), cloudRoadData.getSystemTime(), lastPosition.getSatelliteTime(), cloudRoadData.getSatelliteTime()); + interval = SystemClock.uptimeMillis() - lastExecutionTimeCache.get(uniqueKey); + finalMarker.addDynamicAnchorPosition(new MogoLatLng(cloudRoadData.getLat(), cloudRoadData.getLon()), interval); + Logger.d(TAG, "anim duration: %s in thread: %s", interval, Thread.currentThread().getName()); + } else { + finalMarker.setRotateAngle((float) cloudRoadData.getHeading()); + finalMarker.setPosition(cloudRoadData.getLat(), cloudRoadData.getLon()); + Logger.d(TAG, "设置点位置 in thread: %s", Thread.currentThread().getName()); + } + lastExecutionTimeCache.put(uniqueKey, SystemClock.uptimeMillis()); + SnapshotSetDataDrawer.getInstance().showSelfSpeed(AbsMogoApplication.getApp(), finalMarker, cloudRoadData.getSpeed(), MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode()); + }); + + } + + public void removeDirtyMarker(Collection keys) { + Map result = new ArrayMap<>(keys.size()); + for (String key : keys) { + if(markerCache.containsKey(key)) { + result.put(key, markerCache.remove(key)); + } + } + SnapshotSetDataDrawer.getInstance().sendMessage( MSG_REMOVE_DIRTY_MARKERS, result ); + } + } +} diff --git a/modules/mogo-module-service/src/main/java/com/mogo/module/service/intent/MockIntentHandler.java b/modules/mogo-module-service/src/main/java/com/mogo/module/service/intent/MockIntentHandler.java index 05d2271b41..464c46f44c 100644 --- a/modules/mogo-module-service/src/main/java/com/mogo/module/service/intent/MockIntentHandler.java +++ b/modules/mogo-module-service/src/main/java/com/mogo/module/service/intent/MockIntentHandler.java @@ -556,8 +556,9 @@ public class MockIntentHandler implements IntentHandler { SnapshotSetDataDrawer.getInstance().renderSnapshotData( GsonUtil.objectFromJson( json, MogoSnapshotSetData.class ) ); break; case 47: - mLocationMockHandler.sendEmptyMessageDelayed( 1, 200L ); + mLocationMockHandler.sendEmptyMessageDelayed( 1, 400L ); mLocationMockHandler.sendEmptyMessageDelayed( 2, 0 ); + mLocationMockHandler.sendEmptyMessageDelayed( 21, 200 ); // mLocationMockHandler.sendEmptyMessageDelayed( 3, 300L ); break; } @@ -612,6 +613,17 @@ public class MockIntentHandler implements IntentHandler { } br2 = null; } + } else if( msg.what == 21 ) { + try { + handleMockSnapshotIntent2(); + } catch (Exception e) { + try { + br4.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + + } } } }; @@ -693,6 +705,36 @@ public class MockIntentHandler implements IntentHandler { return true; } + private BufferedReader br4; + + private boolean handleMockSnapshotIntent2() throws Exception { + if ( br4 == null ) { + br4 = new BufferedReader( new InputStreamReader( AbsMogoApplication.getApp().getAssets().open( "snapshot.txt" ) ) ); + } + String line = br4.readLine(); + if ( line == null ) { + throw new Exception( "end of file 2." ); + } + MogoSnapshotSetData data = new MogoSnapshotSetData(); + List< CloudRoadData > allList = new ArrayList<>(); + CloudRoadData cloudRoadData = GsonUtil.objectFromJson( line, CloudRoadData.class ); + if ( cloudRoadData == null ) { + return false; + } + double[] coor = CoordinateUtils.transformWgsToGcj( cloudRoadData.getLat(), cloudRoadData.getLon() ); + cloudRoadData.setUuid("1_21"); + cloudRoadData.setLon( coor[0] ); + cloudRoadData.setLat( coor[1] ); + allList.add( cloudRoadData ); + data.setAllList( allList ); + + final long start = System.currentTimeMillis(); + SnapshotSetDataDrawer.getInstance().renderSnapshotData( data ); + Log.i( "mock-timer-snapshot", "cost " + ( System.currentTimeMillis() - start ) + "ms" ); + mLocationMockHandler.sendEmptyMessageDelayed( 21, 100L ); + return true; + } + private BufferedReader br3; private boolean handleMockAdasIntent() throws Exception {