284 lines
8.8 KiB
Dart
284 lines
8.8 KiB
Dart
import 'dart:async';
|
|
import 'dart:math';
|
|
import 'dart:developer' as dev;
|
|
import 'package:cpnav/pages/setting/setting_controller.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:gnss/gnss.dart';
|
|
import 'package:scence_map/controllers/controller.dart';
|
|
import 'package:scence_map/record_entity.dart';
|
|
|
|
import '../main.dart';
|
|
import '../models/pilePoint/coord_trans.dart';
|
|
import '../pages/aim_point/aimpoint_controller.dart';
|
|
|
|
SettingController settingController = Get.find<SettingController>();
|
|
|
|
class GnssController extends GetxController {
|
|
late final Gnss gnss;
|
|
late ScenceMapController mapController;
|
|
late AimPointerController aimcontroller;
|
|
|
|
LocationData? locationData;
|
|
late Pos3D pilerCenter;
|
|
late DeviceItem device;
|
|
var locationUpdate = 0.obs;
|
|
// late final PilerPointCalculate pilerCenterPoint;
|
|
//三个定义
|
|
var maindrilldistance = 2.0.obs; //主天线与车心距离
|
|
var auxdrilldistance = 2.0.obs; //副天线与车心距离
|
|
var offsetangle = 0.0.obs; //主副连线与车身夹角
|
|
late final CoordTrans coordTrans;
|
|
RecordEntity? lastPilePoint;
|
|
var _dx = 0.0;
|
|
var _dy = 0.0;
|
|
Timer? timer;
|
|
checkDistance() {
|
|
if (DateTime.now().millisecondsSinceEpoch -
|
|
aimcontroller.lastManualTapTime <
|
|
30000 ||
|
|
DateTime.now().millisecondsSinceEpoch - aimcontroller.lastCloseTapTime <
|
|
30000) {
|
|
return;
|
|
}
|
|
|
|
Offset pilerCenterPoint = Offset(device.x.value, device.y.value);
|
|
if (aimcontroller.selectedPilePoint == null) {
|
|
return;
|
|
}
|
|
var offset = Offset(
|
|
aimcontroller.selectedPilePoint!.x, aimcontroller.selectedPilePoint!.y);
|
|
if (mapController.calculateDistance(pilerCenterPoint, offset) < 1.9) {
|
|
if (!aimcontroller.isCardVisible.value) {
|
|
dev.log("距离小于1m");
|
|
aimcontroller.isCardVisible.value = true;
|
|
} else {
|
|
return null;
|
|
}
|
|
} else {
|
|
if (!aimcontroller.isCardVisible.value) {
|
|
dev.log("距离大于1m");
|
|
return null;
|
|
} else {
|
|
aimcontroller.isCardVisible.value = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
void onInit() async {
|
|
super.onInit();
|
|
|
|
mapController = Get.find<ScenceMapController>();
|
|
|
|
aimcontroller = Get.find<AimPointerController>();
|
|
if (settingController.currentDevice.value != null) {
|
|
device = settingController.currentDevice.value!;
|
|
} else {
|
|
device = DeviceItem(
|
|
name: "",
|
|
tid: 0,
|
|
type: "",
|
|
height: 0.0,
|
|
width: 0.0,
|
|
image: "",
|
|
);
|
|
}
|
|
if (device.x.value == 0 && device.y.value == 0) {
|
|
device.x.value = 3790621.123;
|
|
device.y.value = 577052.547;
|
|
}
|
|
// device = DeviceItem(
|
|
// name: 'GNSS',
|
|
// tid: 1001,
|
|
// // type: 2,
|
|
// height: 3.0,
|
|
// width: 3.0,
|
|
// lat: 3790621.123,
|
|
// lon: 577052.547,
|
|
// image: 'assets/images/pilerCar.png');
|
|
// mapController.addDevice(device);
|
|
// pilerCenterPoint = PilerPointCalculate(
|
|
// maindrilldistance.value,
|
|
// auxdrilldistance.value,
|
|
// offsetangle.value,
|
|
// );
|
|
// 调用 pilerPos3D 方法
|
|
|
|
// pilerCenter = Pos3D(4196544.959, 517639.709, 0.0);
|
|
|
|
// 插入定时器测试代码
|
|
timer = Timer.periodic(const Duration(seconds: 1), (Timer timer) {
|
|
if (lastPilePoint != aimcontroller.selectedPilePoint) {
|
|
lastPilePoint = aimcontroller.selectedPilePoint;
|
|
if (aimcontroller.selectedPilePoint != null) {
|
|
var dx = device.x.value - aimcontroller.selectedPilePoint!.x;
|
|
var dy = device.y.value - aimcontroller.selectedPilePoint!.y;
|
|
var distance = sqrt(dx * dx + dy * dy);
|
|
if (distance > 2) {
|
|
dx = (aimcontroller.selectedPilePoint!.x - device.x.value) /
|
|
(distance / 2);
|
|
dy = (aimcontroller.selectedPilePoint!.y - device.y.value) /
|
|
(distance / 2);
|
|
device.x.value = aimcontroller.selectedPilePoint!.x + dx;
|
|
device.y.value = aimcontroller.selectedPilePoint!.y + dy;
|
|
}
|
|
_dx = -dx / 10;
|
|
_dy = -dy / 10;
|
|
}
|
|
}
|
|
|
|
// if ((aimcontroller.selectedPilePoint!.x - device.x).abs() > _dx.abs()) {
|
|
device.x.value += _dx;
|
|
device.y.value += _dy;
|
|
// } else {
|
|
// device.x = aimcontroller.selectedPilePoint!.x;
|
|
// device.y = aimcontroller.selectedPilePoint!.y;
|
|
// }
|
|
|
|
// device.x += 0.05;
|
|
// device.y += 0.05;
|
|
device.rotation.value += pi / 180; // 确保旋转角度在0-360度之间
|
|
device.update.value++;
|
|
checkDistance();
|
|
});
|
|
|
|
gnss = Gnss(port: "/dev/ttysWK2", baudrate: 115200);
|
|
// gnss = Gnss(port: "COM1", baudrate: 115200);
|
|
try {
|
|
gnss.start();
|
|
} catch (e) {
|
|
scaffoldMessengerKey.currentState?.showSnackBar(
|
|
SnackBar(
|
|
content: Text('发生错误: ${e.toString()}'),
|
|
duration: const Duration(seconds: 25),
|
|
backgroundColor: Colors.red,
|
|
),
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
gnss.locationStream.listen((location) {
|
|
locationData = location;
|
|
// log(locationData);
|
|
// var xyh = coordTrans.d2p(CoordBLH(
|
|
// B: location.latitude, L: location.longitude, H: location.altitude));
|
|
// pilerCenter = pilerCenterPoint.pilerPos3D(xyh, location.heading,
|
|
// location.pitch, location.baseLength, offsetangle.value);
|
|
// log(
|
|
// 'X: ${pilerCenter.X}, Y: ${pilerCenter.Y}, Rotation: ${pilerCenter.rotation}');
|
|
// CheckDistance();
|
|
locationUpdate.value++;
|
|
});
|
|
|
|
coordTrans = CoordTrans(TransOptions(L0: 108.5, elevation: 0));
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
gnss.dispose();
|
|
super.dispose();
|
|
timer?.cancel();
|
|
}
|
|
}
|
|
|
|
class Pos3D {
|
|
double X;
|
|
double Y;
|
|
double rotation;
|
|
|
|
Pos3D(this.X, this.Y, this.rotation);
|
|
}
|
|
|
|
// class PilerPointCalculate {
|
|
// final double mainDrillDistance; //主天线与钻头距离
|
|
|
|
// final double auxDrillDistance; //副天线与钻头距离
|
|
// final double offsetangle;
|
|
// PilerPointCalculate(
|
|
// this.mainDrillDistance,
|
|
// this.auxDrillDistance,
|
|
// this.offsetangle,
|
|
// );
|
|
// // 计算副天线的坐标
|
|
// Offset auxPointCalculate(
|
|
// CoordXYH mainPoint, double baseLength, double pitch, double heading) {
|
|
// // 将角度转换为弧度
|
|
// double pitchRad = pitch * pi / 180;
|
|
// double headingRad = (270 - heading) * pi / 180; //(270-)
|
|
|
|
// // 计算水平投影距离
|
|
// double dXY = baseLength * cos(pitchRad);
|
|
|
|
// // 计算副天线的坐标
|
|
// double x2 = mainPoint.X + dXY * cos(headingRad);
|
|
// double y2 = mainPoint.Y + dXY * sin(headingRad);
|
|
// return Offset(x2, y2);
|
|
// }
|
|
|
|
// // 计算交点
|
|
// List findIntersections(CoordXYH mainPoint, Offset auxPoint) {
|
|
// // 计算第二个点 b 的坐标
|
|
// // Offset auxPoint = _auxPointCalculate(mainPoint, baseLength, pitch, heading);
|
|
|
|
// double dx = auxPoint.dx - mainPoint.X;
|
|
// double dy = auxPoint.dy - mainPoint.Y;
|
|
// double d = sqrt(dx * dx + dy * dy);
|
|
|
|
// if (d > mainDrillDistance + auxDrillDistance ||
|
|
// d < (mainDrillDistance - auxDrillDistance).abs()) {
|
|
// // 圆不相交
|
|
// return [];
|
|
// }
|
|
|
|
// double a_ = (mainDrillDistance * mainDrillDistance -
|
|
// auxDrillDistance * auxDrillDistance +
|
|
// d * d) /
|
|
// (2 * d);
|
|
// double h = sqrt(mainDrillDistance * mainDrillDistance - a_ * a_);
|
|
|
|
// double x2 = mainPoint.X + a_ * (dx / d);
|
|
// double y2 = mainPoint.Y + a_ * (dy / d);
|
|
|
|
// double rx = -dy * (h / d);
|
|
// double ry = dx * (h / d);
|
|
|
|
// Offset intersection1 = Offset(x2 + rx, y2 + ry);
|
|
// Offset intersection2 = Offset(x2 - rx, y2 - ry);
|
|
|
|
// return [intersection1, intersection2];
|
|
// }
|
|
|
|
// // 计算车心
|
|
// Pos3D pilerPos3D(CoordXYH mainPoint, double heading, double pitch,
|
|
// double baseLength, double offsetangle) {
|
|
// // 找到两个可能的车心点
|
|
// Offset auxPoint = auxPointCalculate(mainPoint, baseLength, pitch, heading);
|
|
// List intersections = findIntersections(mainPoint, auxPoint);
|
|
|
|
// if (intersections.isEmpty) {
|
|
// throw Exception('无法找到车心点,圆不相交');
|
|
// }
|
|
|
|
// // 以主点为起点连线到副点作为横轴
|
|
// double dx = auxPoint.dx - mainPoint.X;
|
|
// double dy = auxPoint.dy - mainPoint.Y;
|
|
|
|
// // 横轴逆时针旋转90度为纵轴
|
|
// double verticalX = -dy;
|
|
// double verticalY = dx;
|
|
|
|
// // 选择位于纵轴正半轴的点作为最终的车心坐标
|
|
// Offset intersection = (intersections[1].dx - mainPoint.X) * verticalX +
|
|
// (intersections[1].dy - mainPoint.Y) * verticalY >
|
|
// 0
|
|
// ? intersections[1]
|
|
// : intersections[0];
|
|
|
|
// double rotation = (atan2(dy, dx) * 180 / pi) + 90 + offsetangle;
|
|
|
|
// return Pos3D(intersection.dx, intersection.dy, rotation);
|
|
// }
|
|
// }
|