import 'dart:async'; import 'dart:math'; import 'package:get/get.dart'; import 'package:trackoffical_app/logger.dart'; import 'package:trackoffical_app/model.dart'; import 'package:trackoffical_app/service/app.dart'; import 'package:trackoffical_app/service/game/compass_updater.dart'; import 'package:trackoffical_app/service/game/map_status.dart'; import 'package:sensors_plus/sensors_plus.dart'; import 'package:vector_math/vector_math.dart'; import 'game_model.dart'; import 'plug.dart'; import 'package:sensor/sensor.dart'; import 'package:simple_kalman/simple_kalman.dart'; class PlugOrientation extends Plug { PlugOrientation({required this.mapStatus}); StreamSubscription? compassListener; StreamSubscription? accelerometer; final GameModel _model = Get.find(); final MapStatus mapStatus; final _angleFusedUpdater = CompassUpdater(); final _angleSrcUpdater = CompassUpdater(); var _lastAccelerometer = AccelerometerEvent(0, 0, 0); var _lastAccelerometerTime = DateTime.now(); @override Future init() async { _model.isMoving =false; compassListener = Sensor.orientationStream.listen((event) { _model.orientation.value = event; var direction = event.z; if (_model.isUseRealNorth) { direction += _model.compassRealNorthOffset; } final src = _angleSrcUpdater.updateRadians(direction); if(src!=null){ _model.compassRadiansSrc.value = -src; } // GPS 方向 final gpsD = gpsDirection(); _model.isMoving = gpsD != null; if (gpsD != null) { direction = gpsD; } final fused = _angleFusedUpdater.updateRadians(direction); if(fused!=null){ _model.compassRadiansFused.value = -fused; } }); accelerometer = accelerometerEvents.listen((AccelerometerEvent event) { final now = DateTime.now(); if(now.difference(_lastAccelerometerTime) >= 1.seconds){ var sum = (event.x - _lastAccelerometer.x).abs() + (event.y - _lastAccelerometer.y).abs() + (event.z - _lastAccelerometer.z).abs(); final d = now.difference(_lastAccelerometerTime); _model.deviceSpeed = sum / (d.inMilliseconds.toDouble() / 1000); _lastAccelerometerTime = now; _lastAccelerometer = event; } }); } /// GPS 方向 double? gpsDirection() { if(_model.deviceSpeed < 1){ return null; } final locations = []; var disKm = 0.0; final t = 4.seconds; final bt = App.to.now.add(-t); for (var i = _model.myPositionHistoryTmp.length - 1; i >= 0; i--) { final one = _model.myPositionHistoryTmp[i]; if (one.timestamp.isBefore(bt)) { break; } locations.add(one); } if (locations.length > 1) { for (var i = 0; i < locations.length; i++) { if (i > 0) { final p1 = locations[i]; final p2 = locations[i - 1]; disKm += p1.distance(p2).km; } } final d = locations.last.timestamp.difference(locations[0].timestamp); final speedMPerS = disKm * 1000 / (d.inMilliseconds.toDouble().abs() / 1000); _model.speedMPreS.value = speedMPerS; if (speedMPerS > 1.1) { // ---- 均值 ----- // var dSum = 0.0; // var count = 0; // for(var i=locations.length-1; i >=0 && i >= locations.length-3; i--){ // final l1 = locations[i]; // final l2 = locations[i-1]; // dSum += l1.directionTo(l2); // count++; // } // // return dSum/count; // --------------- final l1 = locations[locations.length-1]; var i = locations.length-4; if(i< 0){ i=0; } final l2 = locations[i]; return l1.directionTo(l2); } } return null; } @override Future close() async { super.close(); compassListener?.cancel(); accelerometer?.cancel(); } }