1、针对遮挡严重的场景做了优化
2、增加模拟终端子模块,便于算法验证
This commit is contained in:
parent
c88d37c072
commit
40ae325fe6
1
pom.xml
1
pom.xml
@ -14,6 +14,7 @@
|
|||||||
<module>sec-beidou-rtcm</module>
|
<module>sec-beidou-rtcm</module>
|
||||||
<module>sec-api</module>
|
<module>sec-api</module>
|
||||||
<module>sec-beidou-fwd</module>
|
<module>sec-beidou-fwd</module>
|
||||||
|
<module>sec-test-device</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@ -12,6 +12,9 @@ public interface RtcmClient {
|
|||||||
@PostMapping("/device_param_changed")
|
@PostMapping("/device_param_changed")
|
||||||
HttpResp deviceParamChanged(@RequestParam(name = "deviceId") String deviceId);
|
HttpResp deviceParamChanged(@RequestParam(name = "deviceId") String deviceId);
|
||||||
|
|
||||||
|
@PostMapping("/group_param_changed")
|
||||||
|
HttpResp groupParamChanged();
|
||||||
|
|
||||||
@PostMapping("/warning_param_changed")
|
@PostMapping("/warning_param_changed")
|
||||||
HttpResp warningParamChanged();
|
HttpResp warningParamChanged();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,18 @@ package com.imdroid.sideslope.bd;
|
|||||||
public interface FocusCalculator {
|
public interface FocusCalculator {
|
||||||
void reset();
|
void reset();
|
||||||
void addXyz(double[] xyz);
|
void addXyz(double[] xyz);
|
||||||
|
void addTilt(Tilt tilt);
|
||||||
|
void addDelayMs(int ms);
|
||||||
int[] getB562Stat();
|
int[] getB562Stat();
|
||||||
double[] resultB562(double[] last);
|
double[] resultB562(double[] last);
|
||||||
|
double[] result9250();
|
||||||
|
double[] ekfResult(double[] b562Xyz, double[] tiltXyz);
|
||||||
|
Tilt avgTilt();
|
||||||
|
int getAvgDelayMs();
|
||||||
|
Tilt getTilt0();
|
||||||
|
|
||||||
|
double[] getPosition0();
|
||||||
|
|
||||||
|
double getR();
|
||||||
|
boolean isShocked();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package com.imdroid.sideslope.bd;
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,34 +14,38 @@ import java.util.*;
|
|||||||
* 6.。。。。。。
|
* 6.。。。。。。
|
||||||
*/
|
*/
|
||||||
public class FocusCalculator1 implements FocusCalculator{
|
public class FocusCalculator1 implements FocusCalculator{
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(FocusCalculator1.class);
|
||||||
|
|
||||||
private final List<double[]> list = Collections.synchronizedList(new ArrayList<>());
|
// b562算法相关:b562固定解的点、计算球心初始半径、迭代步长、最少点数
|
||||||
private final List<Tilt> tilts = Collections.synchronizedList(new ArrayList<>());
|
final List<double[]> pointList = Collections.synchronizedList(new ArrayList<>());
|
||||||
private Tilt tilt0;//初始状态
|
int gravityMinCount = 50;
|
||||||
private double[] position0;
|
int gravityMaxCount = 300;
|
||||||
private double r = 10;//杆的长度cm 20230718 测试改为10
|
double gravityInitR = 0.5;
|
||||||
//private boolean flag = false; // 是否是第一次计算
|
double pointSelectedRate = 0.5;
|
||||||
private final List<Point> pointList = new ArrayList<>();
|
double iterStep = 0.1;
|
||||||
//public static double[] lastFocus = null;//
|
// 惯导算法相关
|
||||||
private int delay_ms = 0;
|
final List<Tilt> tilts = Collections.synchronizedList(new ArrayList<>());
|
||||||
private int counter = 0;
|
Tilt tilt0;//初始状态
|
||||||
private boolean isShock = false;
|
double[] position0;
|
||||||
|
double height = 200;
|
||||||
private final double shockThreshold = 1.5;
|
boolean isShock = false;
|
||||||
|
final double shockThreshold = 1.5;
|
||||||
private int counterNoB562 = 0;
|
|
||||||
private int counterNoFixed = 0;
|
|
||||||
private int counterFixedResult = 0;
|
|
||||||
|
|
||||||
|
//其他
|
||||||
|
int delay_ms = 0;
|
||||||
|
int delay_counter = 0;
|
||||||
|
int counterNoB562 = 0;
|
||||||
|
int counterNoFixed = 0;
|
||||||
|
int counterFixedResult = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建计算器,如果tilt0和position0是null,那么计算过程将不考虑与tilts数据融合
|
* 构建计算器,如果tilt0和position0是null,那么计算过程将不考虑与tilts数据融合
|
||||||
* @param r 杆的长度,单位厘米
|
* @param height 杆的长度,单位厘米
|
||||||
* @param tilt0 一个小时前的tilt平均值,用一小时的avgTilt计算得到,如果第一次,用null
|
* @param tilt0 一个小时前的tilt平均值,用一小时的avgTilt计算得到,如果第一次,用null
|
||||||
* @param position0 一个小时前的xyz三维坐标值,用一小时前的ekf计算得到的那个,如果第一次,用null
|
* @param position0 一个小时前的xyz三维坐标值,用一小时前的ekf计算得到的那个,如果第一次,用null
|
||||||
*/
|
*/
|
||||||
public FocusCalculator1(double r, Tilt tilt0, double[] position0){
|
public FocusCalculator1(double height, Tilt tilt0, double[] position0){
|
||||||
this.r = r;
|
this.height = height;
|
||||||
this.tilt0 = tilt0;
|
this.tilt0 = tilt0;
|
||||||
this.position0 = position0;
|
this.position0 = position0;
|
||||||
this.isShock = false;
|
this.isShock = false;
|
||||||
@ -53,15 +60,15 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset(){
|
public void reset(){
|
||||||
list.clear();
|
|
||||||
pointList.clear();
|
pointList.clear();
|
||||||
|
tilts.clear();
|
||||||
counterNoB562 = 0;
|
counterNoB562 = 0;
|
||||||
counterNoFixed = 0;
|
counterNoFixed = 0;
|
||||||
counterFixedResult = 0;
|
counterFixedResult = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入list
|
* 加入pointList
|
||||||
* @param xyz
|
* @param xyz
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@ -71,10 +78,10 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
else {
|
else {
|
||||||
counterFixedResult ++;
|
counterFixedResult ++;
|
||||||
if (filter(xyz)) {
|
if (filter(xyz)) {
|
||||||
list.add(xyz);
|
pointList.add(xyz);
|
||||||
}
|
}
|
||||||
if (list.size() > 300) {
|
if (pointList.size() > gravityMaxCount) {
|
||||||
list.remove(0);
|
pointList.remove(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,70 +93,68 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算得到最终结果
|
* 计算本轮固定解的重心:
|
||||||
|
* 1、如果本轮固定解数少于50个,则直接计算均值
|
||||||
|
* 2、如果大于50个:
|
||||||
|
* a)找出离上次距离最近的50个点,计算初始重心
|
||||||
|
* b)以初始重心为球心,初始半径为0.5画球,找出所有在球内的点
|
||||||
|
* c)重新计算这个球的重心,半径增加0.1,再次找出所有在球内的点,直到筛选出不少于总数50%的点
|
||||||
|
* d)计算这些点的均值
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public double[] resultB562(double[] r9250Result){
|
public double[] resultB562(double[] lastResult){
|
||||||
int count = 50;
|
double r = gravityInitR;//初始球半径
|
||||||
double rate = 0.5;
|
|
||||||
try {
|
try {
|
||||||
double r = 0.5;//初始球半径
|
if(pointList.size() >= gravityMinCount){
|
||||||
if(list.size() >= count){
|
// 筛选出离上次解算结果最近的50个点计算初始球心
|
||||||
List<Point> results = new ArrayList<>();
|
// 如果没有上次位置,选最后50个点
|
||||||
if (r9250Result != null && r9250Result.length > 0){
|
// 为便于排序,使用Point对象
|
||||||
|
List<Point> selectPoints = new ArrayList<>();
|
||||||
|
if (lastResult != null && lastResult.length > 0){
|
||||||
// 计算所有点位与变量之间的距离,并存入集合
|
// 计算所有点位与变量之间的距离,并存入集合
|
||||||
pointList.clear();
|
for (double[] point : pointList) {
|
||||||
for (double[] point : list) {
|
Point pointObj = new Point(point[0],point[1],point[2]);
|
||||||
Point point1 = new Point(point[0],point[1],point[2]);
|
pointObj.setXDistance(disXY(point,lastResult)); // 设置该点到变量的水平距离
|
||||||
point1.setXDistance(disXY(point,r9250Result)); // 设置该点到变量的水平距离
|
pointObj.setZDistance(Math.abs(point[2] - lastResult[2])); // 设置该点到变量的垂直距离
|
||||||
point1.setZDistance(Math.abs(point[2] - r9250Result[2])); // 设置该点到变量的垂直距离
|
selectPoints.add(pointObj); // 将点位加入集合
|
||||||
results.add(point1); // 将点位加入集合
|
|
||||||
}
|
}
|
||||||
Collections.sort(results, Comparator.comparing(Point::getXDistance));//排序
|
Collections.sort(selectPoints, Comparator.comparing(Point::getXDistance));//排序
|
||||||
|
|
||||||
results = results.subList(0, Math.min(50, results.size()));
|
selectPoints = selectPoints.subList(0, Math.min(50, selectPoints.size()));
|
||||||
|
|
||||||
}else {
|
}else {
|
||||||
for (int i = list.size()-count; i < list.size(); i++) {
|
for (int i = pointList.size()-gravityMinCount; i < pointList.size(); i++) {
|
||||||
results.add(new Point(list.get(i)[0],list.get(i)[1],list.get(i)[2]));
|
selectPoints.add(new Point(pointList.get(i)[0],pointList.get(i)[1],pointList.get(i)[2]));
|
||||||
}
|
}
|
||||||
//flag = true;
|
//flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 求初始重心
|
// 求初始重心
|
||||||
double[] focus = focusPoint(results);
|
double[] focus = focusPointObj(selectPoints);
|
||||||
|
|
||||||
//重心
|
// 迭代计算重心,直到选出50%的点
|
||||||
int iterNum = 0;
|
int iterNum = 0;
|
||||||
if(globeProportion(focus,r) < rate){
|
List<double[]> pointList;
|
||||||
|
if(globeProportion(focus,r) < pointSelectedRate){
|
||||||
do{
|
do{
|
||||||
iterNum++;
|
iterNum++;
|
||||||
r += 0.1;
|
r += iterStep;
|
||||||
//球附近点集个数有可能为0,继续计算会导致focus结果出现NaN
|
//球附近点集个数有可能为0,继续计算会导致focus结果出现NaN
|
||||||
List<double[]> doubles1 = globeFilter(focus, r);
|
pointList = globeFilter(focus, r);
|
||||||
if(doubles1.size() == 0){
|
if(pointList.size() == 0) continue;
|
||||||
continue;
|
focus = focusPoint(pointList);
|
||||||
}
|
}while (globeProportion(focus,r) < pointSelectedRate);
|
||||||
focus = focus(doubles1);
|
logger.info("calc focus iter num:{}, point num:{}",iterNum,pointList.size());
|
||||||
}while (globeProportion(focus,r) < rate);
|
|
||||||
System.out.println("calc focus iter num:"+iterNum);
|
|
||||||
// if (flag){
|
|
||||||
// lastFocus = new double[3];
|
|
||||||
// lastFocus = focus;
|
|
||||||
// }
|
|
||||||
return focus;
|
return focus;
|
||||||
}else{
|
}else{
|
||||||
// if (flag){
|
logger.info("calc focus iter num:0, point num:{}",selectPoints.size());
|
||||||
// lastFocus = new double[3];
|
|
||||||
// lastFocus = focus;
|
|
||||||
// }
|
|
||||||
return focus;
|
return focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
//如果计算过程中修改list,可能引发异常
|
//如果计算过程中修改pointList,可能引发异常
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return resultB562Sub();
|
return resultB562Sub();
|
||||||
@ -159,10 +164,10 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* resultB562替补方法,尽量不返回空
|
* resultB562替补方法,尽量不返回空
|
||||||
* @return x,y,z,有效点数
|
* @return x,y,z,有效点数
|
||||||
*/
|
*/
|
||||||
private double[] resultB562Sub(){
|
double[] resultB562Sub(){
|
||||||
if(list.size() > 0){
|
if(pointList.size() > 0){
|
||||||
//重心
|
//重心
|
||||||
return focus(list);
|
return focusPoint(pointList);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -172,7 +177,7 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* @param xyz
|
* @param xyz
|
||||||
* @return true表示数据正常
|
* @return true表示数据正常
|
||||||
*/
|
*/
|
||||||
private boolean filter(double[] xyz){
|
boolean filter(double[] xyz){
|
||||||
double a = xyz[0]*xyz[1]*xyz[2];
|
double a = xyz[0]*xyz[1]*xyz[2];
|
||||||
if(a == 0 || Double.isInfinite(a) || Double.isNaN(a)){
|
if(a == 0 || Double.isInfinite(a) || Double.isNaN(a)){
|
||||||
return false;
|
return false;
|
||||||
@ -185,7 +190,7 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* @param list
|
* @param list
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private double[] focus(List<double[]> list){
|
double[] focusPoint(List<double[]> list){
|
||||||
double sumX = 0;
|
double sumX = 0;
|
||||||
double sumY = 0;
|
double sumY = 0;
|
||||||
double sumZ = 0;
|
double sumZ = 0;
|
||||||
@ -198,7 +203,7 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
return new double[]{sumX/count,sumY/count,sumZ/count};
|
return new double[]{sumX/count,sumY/count,sumZ/count};
|
||||||
}
|
}
|
||||||
|
|
||||||
private double[] focusPoint(List<Point> list){
|
double[] focusPointObj(List<Point> list){
|
||||||
double sumX = 0;
|
double sumX = 0;
|
||||||
double sumY = 0;
|
double sumY = 0;
|
||||||
double sumZ = 0;
|
double sumZ = 0;
|
||||||
@ -231,15 +236,15 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* @param r
|
* @param r
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private double globeProportion(double[] focus, double r){
|
double globeProportion(double[] focus, double r){
|
||||||
int in = 0;//在球内的个数
|
int in = 0;//在球内的个数
|
||||||
for (double[] doubles : list) {
|
for (double[] doubles : pointList) {
|
||||||
double dis = dis(doubles, focus);
|
double dis = dis(doubles, focus);
|
||||||
if(dis < r){
|
if(dis < r){
|
||||||
in += 1;
|
in += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double proportion = 1.00*in/list.size();
|
double proportion = 1.00*in/pointList.size();
|
||||||
return proportion;
|
return proportion;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,9 +254,9 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* @param r
|
* @param r
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private List<double[]> globeFilter(double[] focus, double r){
|
List<double[]> globeFilter(double[] focus, double r){
|
||||||
ArrayList<double[]> arrayList = new ArrayList<>();
|
ArrayList<double[]> arrayList = new ArrayList<>();
|
||||||
for (double[] doubles1 : list) {
|
for (double[] doubles1 : pointList) {
|
||||||
if(dis(doubles1,focus) < r){
|
if(dis(doubles1,focus) < r){
|
||||||
arrayList.add(doubles1);
|
arrayList.add(doubles1);
|
||||||
}
|
}
|
||||||
@ -266,6 +271,7 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* 3.可用点数无,用9250
|
* 3.可用点数无,用9250
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public double[] ekfResult(double[] b562Xyz, double[] tiltXyz){
|
public double[] ekfResult(double[] b562Xyz, double[] tiltXyz){
|
||||||
if(tiltXyz == null){
|
if(tiltXyz == null){
|
||||||
return b562Xyz;
|
return b562Xyz;
|
||||||
@ -275,15 +281,15 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
}
|
}
|
||||||
double b562Variance;
|
double b562Variance;
|
||||||
double tiltVariance = 5; //Sherlock 230802 2-》5, 减小惯导的长周期影响
|
double tiltVariance = 5; //Sherlock 230802 2-》5, 减小惯导的长周期影响
|
||||||
if(list.size() >= 50){
|
if(pointList.size() >= 50){
|
||||||
b562Variance = 1;
|
b562Variance = 1;
|
||||||
}else if(list.size() >= 40){
|
}else if(pointList.size() >= 40){
|
||||||
b562Variance = 3;
|
b562Variance = 3;
|
||||||
}else if(list.size() >= 30){
|
}else if(pointList.size() >= 30){
|
||||||
b562Variance = 9;
|
b562Variance = 9;
|
||||||
}else if(list.size() >= 20){
|
}else if(pointList.size() >= 20){
|
||||||
b562Variance = 30;
|
b562Variance = 30;
|
||||||
}else if(list.size() >= 10){
|
}else if(pointList.size() >= 10){
|
||||||
b562Variance = 60;
|
b562Variance = 60;
|
||||||
}else{
|
}else{
|
||||||
b562Variance = 90;
|
b562Variance = 90;
|
||||||
@ -303,77 +309,72 @@ public class FocusCalculator1 implements FocusCalculator{
|
|||||||
* 加入tilts
|
* 加入tilts
|
||||||
* @param tilt
|
* @param tilt
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public void addTilt(Tilt tilt){
|
public void addTilt(Tilt tilt){
|
||||||
tilts.add(tilt);
|
tilts.add(tilt);
|
||||||
if(tilt.getShock() > shockThreshold) isShock = true;
|
if(tilt.getShock() > shockThreshold) isShock = true;
|
||||||
|
|
||||||
if(tilts.size() > 300){
|
if(tilts.size() > gravityMaxCount){
|
||||||
tilts.remove(0);
|
tilts.remove(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean isShocked() {
|
public boolean isShocked() {
|
||||||
return isShock;
|
return isShock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* 取平均
|
public Tilt avgTilt() {
|
||||||
* @return
|
if (tilts.size() == 0) {
|
||||||
*/
|
|
||||||
public Tilt avgTilt(){
|
|
||||||
if(tilts.size() == 0){
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
Iterator<Tilt> iterator = tilts.iterator();
|
||||||
Iterator<Tilt> iterator = tilts.iterator();
|
double roll = 0;
|
||||||
int size = tilts.size();
|
double pitch = 0;
|
||||||
double sumP = 0;
|
double yaw = 0;
|
||||||
double sumR = 0;
|
while (iterator.hasNext()) {
|
||||||
double sumY = 0;
|
Tilt tilt = iterator.next();
|
||||||
while (iterator.hasNext()){
|
roll += tilt.getRoll();
|
||||||
Tilt tilt = iterator.next();
|
pitch += tilt.getPitch();
|
||||||
sumP += Math.sin(tilt.getPitch()*Math.PI/180);
|
yaw += tilt.getYaw();
|
||||||
sumR += Math.sin(tilt.getRoll()*Math.PI/180);
|
|
||||||
sumY += Math.sin(tilt.getYaw()*Math.PI/180);
|
|
||||||
}
|
|
||||||
double pitch = (Math.asin(sumP/size) * 180/Math.PI + 360)%360;
|
|
||||||
double roll = (Math.asin(sumR/size) * 180/Math.PI + 360)%360;
|
|
||||||
double yaw = (Math.asin(sumY/size) * 180/Math.PI + 360)%360;
|
|
||||||
|
|
||||||
return new Tilt(pitch,roll,yaw);
|
|
||||||
}catch (Exception e){
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
return null;
|
return new Tilt(pitch,roll,yaw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public double[] result9250(){
|
public double[] result9250(){
|
||||||
Tilt avg = avgTilt();
|
Tilt avg = avgTilt();
|
||||||
if(tilt0 == null || position0 == null || r == 0 || avg == null){
|
if(tilt0 == null || position0 == null || height == 0 || avg == null){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return TiltUtil.toPosition(avg,tilt0,position0,r);
|
return TiltUtil.toPosition(avg,tilt0,position0,height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Tilt getTilt0(){
|
public Tilt getTilt0(){
|
||||||
return tilt0;
|
return tilt0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public double[] getPosition0(){
|
public double[] getPosition0(){
|
||||||
return position0;
|
return position0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public double getR(){
|
public double getR(){
|
||||||
return r;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void addDelayMs(int ms){
|
public void addDelayMs(int ms){
|
||||||
delay_ms += ms;
|
delay_ms += ms;
|
||||||
counter ++;
|
delay_counter ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public int getAvgDelayMs(){
|
public int getAvgDelayMs(){
|
||||||
return delay_ms/counter;
|
return delay_ms/delay_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.imdroid.sideslope.bd;
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -10,243 +11,79 @@ import java.util.*;
|
|||||||
* 5.否则,扩大半径0.01再求重心,包容百分之68,此重心为所求
|
* 5.否则,扩大半径0.01再求重心,包容百分之68,此重心为所求
|
||||||
* 6.。。。。。。
|
* 6.。。。。。。
|
||||||
*/
|
*/
|
||||||
public class FocusCalculator2 implements FocusCalculator{
|
public class FocusCalculator2 extends FocusCalculator1{
|
||||||
|
final static int MAX_B562_NUM = 3600;
|
||||||
|
final static int B562_EXPIRED_HOUR = 2;
|
||||||
|
final List<LocalDateTime> pointTimeList = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
|
||||||
private final List<double[]> list = Collections.synchronizedList(new ArrayList<>());
|
/**
|
||||||
|
* 构建计算器,如果tilt0和position0是null,那么计算过程将不考虑与tilts数据融合
|
||||||
private final List<Point> pointList = new ArrayList<>();
|
* @param height 杆的长度,单位厘米
|
||||||
private int counterNoB562 = 0;
|
* @param tilt0 一个小时前的tilt平均值,用一小时的avgTilt计算得到,如果第一次,用null
|
||||||
private int counterNoFixed = 0;
|
* @param position0 一个小时前的xyz三维坐标值,用一小时前的ekf计算得到的那个,如果第一次,用null
|
||||||
private int counterFixedResult = 0;
|
*/
|
||||||
|
public FocusCalculator2(double height, Tilt tilt0, double[] position0){
|
||||||
|
super(height,tilt0,position0);
|
||||||
|
iterStep = 0.2;
|
||||||
|
gravityMaxCount = MAX_B562_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FocusCalculator2(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset(){
|
public void reset(){
|
||||||
list.clear();
|
//pointList.clear();
|
||||||
pointList.clear();
|
|
||||||
counterNoB562 = 0;
|
counterNoB562 = 0;
|
||||||
counterNoFixed = 0;
|
counterNoFixed = 0;
|
||||||
counterFixedResult = 0;
|
counterFixedResult = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加入list
|
* 加入pointList
|
||||||
* @param xyz
|
* @param xyz
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void addXyz(double[] xyz){
|
public void addXyz(double[] xyz){
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
Iterator<LocalDateTime> iterPointTime = pointTimeList.iterator();
|
||||||
|
Iterator<double[]> iterPoint = pointList.iterator();
|
||||||
|
while(iterPointTime.hasNext() && iterPoint.hasNext()){
|
||||||
|
LocalDateTime pointTime = iterPointTime.next();
|
||||||
|
if(now.isAfter(pointTime.plusHours(B562_EXPIRED_HOUR))){
|
||||||
|
iterPointTime.remove();
|
||||||
|
iterPoint.remove();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if((int)xyz[3] == UBXUtil.NO_B562) counterNoB562++;
|
if((int)xyz[3] == UBXUtil.NO_B562) counterNoB562++;
|
||||||
else if((int)xyz[3] == UBXUtil.NO_FIX_RESULT) counterNoFixed++;
|
else if((int)xyz[3] == UBXUtil.NO_FIX_RESULT) counterNoFixed++;
|
||||||
else {
|
else {
|
||||||
counterFixedResult ++;
|
counterFixedResult ++;
|
||||||
if (filter(xyz)) {
|
if (filter(xyz)) {
|
||||||
list.add(xyz);
|
pointList.add(xyz);
|
||||||
|
pointTimeList.add(now);
|
||||||
}
|
}
|
||||||
if (list.size() > 300) {
|
if (pointList.size() > gravityMaxCount) {
|
||||||
list.remove(0);
|
pointList.remove(0);
|
||||||
|
pointTimeList.remove(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean filter(double[] xyz){
|
public double[] resultB562(double[] lastResult){
|
||||||
double a = xyz[0]*xyz[1]*xyz[2];
|
if(counterFixedResult<30) return null;
|
||||||
if(a == 0 || Double.isInfinite(a) || Double.isNaN(a)){
|
else return super.resultB562(lastResult);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getB562Stat(){
|
public int[] getB562Stat(){
|
||||||
return new int[]{counterFixedResult,counterNoFixed,counterNoB562};
|
int[] b562Stat = new int[]{counterFixedResult,counterNoFixed,counterNoB562};
|
||||||
}
|
reset();
|
||||||
|
return b562Stat;
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算得到最终结果
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public double[] resultB562_2() {
|
|
||||||
// 求全体样本的重心
|
|
||||||
double e = 0;
|
|
||||||
double n = 0;
|
|
||||||
double d = 0;
|
|
||||||
for(double[] point: list){
|
|
||||||
e += point[0];
|
|
||||||
n += point[1];
|
|
||||||
d += point[2];
|
|
||||||
}
|
|
||||||
e /= list.size();
|
|
||||||
n /= list.size();
|
|
||||||
d /= list.size();
|
|
||||||
|
|
||||||
double g = 0;
|
|
||||||
int iterNum = 0;
|
|
||||||
while(Math.abs(g-e)>0.2){
|
|
||||||
g = e;
|
|
||||||
e = gravity(g, 0.3, 0);
|
|
||||||
iterNum ++;
|
|
||||||
if(iterNum>=10) break;
|
|
||||||
}
|
|
||||||
//System.out.println("e iter num: "+iterNum);
|
|
||||||
|
|
||||||
g = 0;
|
|
||||||
iterNum = 0;
|
|
||||||
while(Math.abs(g-n)>0.2){
|
|
||||||
g = n;
|
|
||||||
n = gravity(g, 0.26, 0);
|
|
||||||
iterNum ++;
|
|
||||||
if(iterNum>=10) break;
|
|
||||||
}
|
|
||||||
//System.out.println("n iter num: "+iterNum);
|
|
||||||
|
|
||||||
g = 0;
|
|
||||||
iterNum = 0;
|
|
||||||
while(Math.abs(g-d)>0.4){
|
|
||||||
g = d;
|
|
||||||
d = gravity(g, 0.87, 0);
|
|
||||||
iterNum ++;
|
|
||||||
if(iterNum>=10) break;
|
|
||||||
}
|
|
||||||
//System.out.println("e iter num: "+iterNum);
|
|
||||||
|
|
||||||
return new double[]{e,n,d};
|
|
||||||
}
|
|
||||||
|
|
||||||
double gravity(double g, double r, int index){
|
|
||||||
//筛选出半径为r=0.144的圆内的点
|
|
||||||
double newG = 0;
|
|
||||||
List<Double> list2 = new ArrayList<>();
|
|
||||||
for(double[] point: list){
|
|
||||||
if(Math.abs(point[index]-g)<=r){
|
|
||||||
list2.add(point[index]);
|
|
||||||
newG += point[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("sub set: " + list2.size());
|
|
||||||
if(list2.size()>0) newG /= list2.size();
|
|
||||||
return newG;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double[] resultB562(double[] last) {
|
|
||||||
double[] g = {0, 0, 0};
|
|
||||||
if(last != null) g=last;
|
|
||||||
else {
|
|
||||||
for (double[] xyz : list) {
|
|
||||||
g[0] += xyz[0];
|
|
||||||
g[1] += xyz[1];
|
|
||||||
g[2] += xyz[2];
|
|
||||||
}
|
|
||||||
g[0] /= list.size();
|
|
||||||
g[1] /= list.size();
|
|
||||||
g[2] /= list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] g2 = {0,0,0};
|
|
||||||
int iterNum = 0;
|
|
||||||
while(isLarge(g,g2,2, 4)){
|
|
||||||
g2 = g;
|
|
||||||
g = gravity3(g);
|
|
||||||
iterNum ++;
|
|
||||||
if(iterNum>=10) break;
|
|
||||||
}
|
|
||||||
System.out.println("e iter num: "+iterNum);
|
|
||||||
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isLarge(double[] p1, double[] p2, double xy, double z){
|
|
||||||
//return true;
|
|
||||||
return (Math.sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1]))>xy ||
|
|
||||||
Math.abs(p1[2]-p2[2])>z);
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] gravity2(double[] g){
|
|
||||||
//筛选出半径为r=0.144的圆内的点
|
|
||||||
List<Point> points = new ArrayList<>();
|
|
||||||
for(double[] xyz: list){
|
|
||||||
Point point = new Point(xyz[0], xyz[1], xyz[2]);
|
|
||||||
point.setXDistance(Math.sqrt((xyz[0]-g[0])*(xyz[0]-g[0])+(xyz[1]-g[1])*(xyz[1]-g[1])));
|
|
||||||
point.setZDistance(Math.abs(xyz[2]-g[2]));
|
|
||||||
points.add(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] newG = {0,0,0};
|
|
||||||
int i=0;
|
|
||||||
int calcNum = points.size()*5/10;
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getXDistance));//升序排序
|
|
||||||
for(Point point:points){
|
|
||||||
newG[0] += point.getX();
|
|
||||||
newG[1] += point.getY();
|
|
||||||
i++;
|
|
||||||
if(i>=calcNum) {
|
|
||||||
newG[0] /= calcNum;
|
|
||||||
newG[1] /= calcNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getZDistance));//升序排序
|
|
||||||
i=0;
|
|
||||||
for(Point point:points){
|
|
||||||
newG[2] += point.getZ();
|
|
||||||
i++;
|
|
||||||
if(i>=calcNum) {
|
|
||||||
newG[2] /= calcNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newG;
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] gravity3(double[] g){
|
|
||||||
//筛选出半径为r=0.144的圆内的点
|
|
||||||
List<Point> points = new ArrayList<>();
|
|
||||||
for(double[] xyz: list){
|
|
||||||
Point point = new Point(xyz[0], xyz[1], xyz[2]);
|
|
||||||
point.setXDistance(Math.abs(xyz[0]-g[0]));
|
|
||||||
point.setYDistance(Math.abs(xyz[1]-g[1]));
|
|
||||||
point.setZDistance(Math.abs(xyz[2]-g[2]));
|
|
||||||
points.add(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
double[] newG = {0,0,0};
|
|
||||||
int i=0;
|
|
||||||
int calcNum = points.size()*5/10;
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getXDistance));//升序排序
|
|
||||||
for(Point point:points){
|
|
||||||
newG[0] += point.getX();
|
|
||||||
i++;
|
|
||||||
if(i>=calcNum) {
|
|
||||||
newG[0] /= calcNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getYDistance));//升序排序
|
|
||||||
i=0;
|
|
||||||
for(Point point:points){
|
|
||||||
newG[1] += point.getY();
|
|
||||||
i++;
|
|
||||||
if(i>=calcNum) {
|
|
||||||
newG[1] /= calcNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getZDistance));//升序排序
|
|
||||||
i=0;
|
|
||||||
for(Point point:points){
|
|
||||||
newG[2] += point.getZ();
|
|
||||||
i++;
|
|
||||||
if(i>=calcNum) {
|
|
||||||
newG[2] /= calcNum;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newG;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,8 +20,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
public class GNSSCalcFilterService {
|
public class GNSSCalcFilterService {
|
||||||
private final Logger logger = LoggerFactory.getLogger(GNSSCalcFilterService.class);
|
private final Logger logger = LoggerFactory.getLogger(GNSSCalcFilterService.class);
|
||||||
|
|
||||||
@Resource(name = "local")
|
|
||||||
DeviceService gnssDeviceRepository;
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private GnssGroupCalcMapper groupCalcMapper;
|
private GnssGroupCalcMapper groupCalcMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -44,18 +42,13 @@ public class GNSSCalcFilterService {
|
|||||||
|
|
||||||
final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
public void calc(GnssCalcData locationRecord, boolean isExceed) {
|
public void calc(Device gnssDevice, GnssGroupCalc groupCalc, GnssCalcData locationRecord, boolean isExceed) {
|
||||||
String deviceId = locationRecord.getDeviceid();
|
String deviceId = locationRecord.getDeviceid();
|
||||||
Device gnssDevice = gnssDeviceRepository.findByDeviceId(deviceId);
|
|
||||||
if(gnssDevice == null) return;
|
|
||||||
|
|
||||||
//补充解算记录的设备信息
|
//补充解算记录的设备信息
|
||||||
locationRecord.setTenantid(gnssDevice.getTenantId());
|
locationRecord.setTenantid(gnssDevice.getTenantId());
|
||||||
locationRecord.setEnabled(true);
|
locationRecord.setEnabled(true);
|
||||||
|
|
||||||
// 获取平滑参数
|
|
||||||
GnssGroupCalc groupCalc = getCalcParams(gnssDevice.getCalcGroupId());
|
|
||||||
|
|
||||||
// 计算平滑周期
|
// 计算平滑周期
|
||||||
int filterCycle = groupCalc.getFilter_hour();
|
int filterCycle = groupCalc.getFilter_hour();
|
||||||
VaryFilterCycle varyCycle = autoCycleDevices.get(deviceId);
|
VaryFilterCycle varyCycle = autoCycleDevices.get(deviceId);
|
||||||
@ -76,20 +69,6 @@ public class GNSSCalcFilterService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GnssGroupCalc getCalcParams(int calcGroupId){
|
|
||||||
GnssGroupCalc calcParam = groupCalcMapper.selectById(calcGroupId);
|
|
||||||
if(calcParam == null){
|
|
||||||
calcParam = new GnssGroupCalc();
|
|
||||||
calcParam.setAuto_filter(false);
|
|
||||||
calcParam.setFilter_hour(FILTER_DEFAULT_CYCLE_HOUR);
|
|
||||||
calcParam.setFilter_min_hour(FILTER_MIN_CYCLE_HOUR);
|
|
||||||
calcParam.setXy_threshold(XY_THRESHOLD);
|
|
||||||
calcParam.setZ_threshold(Z_THRESHOLD);
|
|
||||||
calcParam.setAuto_threshold(AUTO_THRESHOLD);
|
|
||||||
}
|
|
||||||
return calcParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算东北天的最近融合数据的加权平均, 刘畅20230725 copy 自 avgEND; id>20, 滤波参数6h 或 25h
|
* 计算东北天的最近融合数据的加权平均, 刘畅20230725 copy 自 avgEND; id>20, 滤波参数6h 或 25h
|
||||||
*/
|
*/
|
||||||
@ -223,12 +202,8 @@ public class GNSSCalcFilterService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDateTime updateRpos(String deviceId, LocalDateTime afterTime){
|
public LocalDateTime updateRpos(Device gnssDevice, GnssGroupCalc groupCalc,LocalDateTime afterTime){
|
||||||
// 获取平滑参数
|
String deviceId=gnssDevice.getDeviceId();
|
||||||
Device gnssDevice = gnssDeviceRepository.findByDeviceId(deviceId);
|
|
||||||
if(gnssDevice == null) return afterTime;
|
|
||||||
GnssGroupCalc groupCalc = getCalcParams(gnssDevice.getCalcGroupId());
|
|
||||||
|
|
||||||
// 平滑处理
|
// 平滑处理
|
||||||
LocalDateTime beforTime = afterTime.plusHours(groupCalc.getFilter_hour());
|
LocalDateTime beforTime = afterTime.plusHours(groupCalc.getFilter_hour());
|
||||||
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
|
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
package com.imdroid.sideslope.calc;
|
package com.imdroid.sideslope.calc;
|
||||||
|
|
||||||
import com.imdroid.sideslope.bd.Tilt;
|
import com.imdroid.secapi.dto.GnssGroupCalc;
|
||||||
import com.imdroid.sideslope.message.D341LocationMessage;
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
|
import com.imdroid.sideslope.sal.Device;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@ -18,19 +19,6 @@ public interface GNSSDataCalcService {
|
|||||||
/**
|
/**
|
||||||
* 单轮解算结束,计算平滑值
|
* 单轮解算结束,计算平滑值
|
||||||
*/
|
*/
|
||||||
void calSingleDone(String deviceId, Integer tenantId, LocalDateTime resultTime);
|
void calSingleDone(Device device, GnssGroupCalc groupCalc, LocalDateTime resultTime);
|
||||||
/**
|
|
||||||
* 根据GNSS数据的中间结果,计算出最终结果
|
|
||||||
*
|
|
||||||
* @param deviceId 设备id
|
|
||||||
* @return x,y,z三轴数据
|
|
||||||
*/
|
|
||||||
//double[] calcResult(String deviceId,double[] b562Xyz, double[] tiltXyz);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据GNSS数据的中间结果,计算Tilt的平均值
|
|
||||||
* @param deviceid 设备id
|
|
||||||
* @return Tilt
|
|
||||||
*/
|
|
||||||
Tilt calcAvgTilt(String deviceid);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,13 +5,17 @@ import com.imdroid.secapi.dto.*;
|
|||||||
import com.imdroid.sideslope.message.BaseMessage;
|
import com.imdroid.sideslope.message.BaseMessage;
|
||||||
import com.imdroid.sideslope.message.D341LocationMessage;
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
import com.imdroid.sideslope.message.D342LocationMessage;
|
import com.imdroid.sideslope.message.D342LocationMessage;
|
||||||
|
import com.imdroid.sideslope.sal.Device;
|
||||||
|
import com.imdroid.sideslope.sal.DeviceService;
|
||||||
import com.imdroid.sideslope.service.DataPersistService;
|
import com.imdroid.sideslope.service.DataPersistService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@ -22,7 +26,7 @@ public class MultiLineGNSSCalcService {
|
|||||||
LocalDateTime createTime;
|
LocalDateTime createTime;
|
||||||
LocalDateTime uploadTime;
|
LocalDateTime uploadTime;
|
||||||
}
|
}
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SingleLineGNSSCalcService.class);
|
private static final Logger logger = LoggerFactory.getLogger(MultiLineGNSSCalcService.class);
|
||||||
private static final Map<String, D342Time> deviceMap = new ConcurrentHashMap<>();
|
private static final Map<String, D342Time> deviceMap = new ConcurrentHashMap<>();
|
||||||
private static final Map<String, ResendRecord> fwdRecordMap = new ConcurrentHashMap<>();
|
private static final Map<String, ResendRecord> fwdRecordMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@ -36,6 +40,24 @@ public class MultiLineGNSSCalcService {
|
|||||||
private BeidouClient beidouClient;
|
private BeidouClient beidouClient;
|
||||||
@Autowired
|
@Autowired
|
||||||
DataPersistService dataPersistService;
|
DataPersistService dataPersistService;
|
||||||
|
@Resource(name = "local")
|
||||||
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
GnssGroupCalcMapper groupCalcMapper;
|
||||||
|
List<GnssGroupCalc> groupCalcList;
|
||||||
|
|
||||||
|
GnssGroupCalc getGroupCalc(int groupId){
|
||||||
|
if(groupCalcList == null){
|
||||||
|
groupCalcList = groupCalcMapper.selectList(null);
|
||||||
|
}
|
||||||
|
if(groupCalcList != null){
|
||||||
|
for(GnssGroupCalc groupCalc:groupCalcList){
|
||||||
|
if(groupCalc.getId() == groupId) return groupCalc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void calc(D342LocationMessage d342Message){
|
public void calc(D342LocationMessage d342Message){
|
||||||
// 如果时间跨度大于1分钟,或者不含d341,则计算平滑值
|
// 如果时间跨度大于1分钟,或者不含d341,则计算平滑值
|
||||||
@ -56,7 +78,9 @@ public class MultiLineGNSSCalcService {
|
|||||||
if (msgTime.isAfter(lastD342Time.createTime.plusMinutes(4))) {
|
if (msgTime.isAfter(lastD342Time.createTime.plusMinutes(4))) {
|
||||||
logger.info(deviceId + " d341 cycle done!");
|
logger.info(deviceId + " d341 cycle done!");
|
||||||
// 计算上轮结果
|
// 计算上轮结果
|
||||||
calcService.calSingleDone(deviceId, d342Message.getTenantId(), lastD342Time.createTime);
|
Device device = deviceService.findByDeviceId(deviceId);
|
||||||
|
GnssGroupCalc groupCalc = getGroupCalc(device.getCalcGroupId());
|
||||||
|
calcService.calSingleDone(device, groupCalc, lastD342Time.createTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
@ -105,9 +129,11 @@ public class MultiLineGNSSCalcService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
// 计算上轮结果
|
// 计算上轮结果
|
||||||
calcService.calSingleDone(deviceId, tenantId, lastDate);
|
Device device = deviceService.findByDeviceId(deviceId);
|
||||||
|
GnssGroupCalc groupCalc = getGroupCalc(device.getCalcGroupId());
|
||||||
|
calcService.calSingleDone(device, groupCalc, lastDate);
|
||||||
// 重算最近的
|
// 重算最近的
|
||||||
lastDate = gnssCalcFilterService.updateRpos(deviceId,lastDate);
|
lastDate = gnssCalcFilterService.updateRpos(device,groupCalc,lastDate);
|
||||||
// 记录转发表更新为upload done
|
// 记录转发表更新为upload done
|
||||||
ResendRecord fwdRecord = fwdRecordMap.get(deviceId);
|
ResendRecord fwdRecord = fwdRecordMap.get(deviceId);
|
||||||
if(fwdRecord != null){
|
if(fwdRecord != null){
|
||||||
@ -159,4 +185,9 @@ public class MultiLineGNSSCalcService {
|
|||||||
}
|
}
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refreshGroupCalc(){
|
||||||
|
groupCalcList = groupCalcMapper.selectList(null);
|
||||||
|
logger.info("group paras changed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@ package com.imdroid.sideslope.calc;
|
|||||||
|
|
||||||
import com.imdroid.common.util.ThreadManager;
|
import com.imdroid.common.util.ThreadManager;
|
||||||
import com.imdroid.secapi.dto.GnssCalcData;
|
import com.imdroid.secapi.dto.GnssCalcData;
|
||||||
|
import com.imdroid.secapi.dto.GnssGroupCalc;
|
||||||
|
import com.imdroid.secapi.dto.GnssGroupCalcMapper;
|
||||||
import com.imdroid.sideslope.bd.*;
|
import com.imdroid.sideslope.bd.*;
|
||||||
import com.imdroid.sideslope.message.D341LocationMessage;
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
import com.imdroid.sideslope.sal.Device;
|
import com.imdroid.sideslope.sal.Device;
|
||||||
@ -15,6 +17,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
/**
|
/**
|
||||||
@ -26,7 +29,7 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(SingleLineGNSSCalcService.class);
|
private static final Logger logger = LoggerFactory.getLogger(SingleLineGNSSCalcService.class);
|
||||||
|
|
||||||
private static final Map<String, FocusCalculator1> calculatorMap = new ConcurrentHashMap<>();
|
private static final Map<String, FocusCalculator> calculatorMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final Map<String, ScheduledFuture<?>> timerMap = new ConcurrentHashMap<>();
|
private static final Map<String, ScheduledFuture<?>> timerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@ -36,8 +39,6 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
|
|
||||||
private static final Map<String, Boolean> cleanTiltStatusMap = new ConcurrentHashMap<>();
|
private static final Map<String, Boolean> cleanTiltStatusMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final Map<String, Boolean> cleanPositionStatusMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
WarningService warningService;
|
WarningService warningService;
|
||||||
|
|
||||||
@ -47,26 +48,53 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
@Resource(name = "local")
|
@Resource(name = "local")
|
||||||
private DeviceService deviceService;
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
GnssGroupCalcMapper groupCalcMapper;
|
||||||
|
List<GnssGroupCalc> groupCalcList;
|
||||||
|
|
||||||
|
GnssGroupCalc getGroupCalc(int groupId){
|
||||||
|
if(groupCalcList == null){
|
||||||
|
groupCalcList = groupCalcMapper.selectList(null);
|
||||||
|
}
|
||||||
|
if(groupCalcList != null){
|
||||||
|
for(GnssGroupCalc groupCalc:groupCalcList){
|
||||||
|
if(groupCalc.getId() == groupId) return groupCalc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double[] calcSingle(D341LocationMessage message, boolean completeWhenIdle) {
|
public double[] calcSingle(D341LocationMessage message, boolean completeWhenIdle) {
|
||||||
String deviceId = message.getId();
|
String deviceId = message.getId();
|
||||||
if(completeWhenIdle) resultOutputTimer(deviceId, message.getTenantId(), message.getCreateTime());
|
Device device = deviceService.findByDeviceId(deviceId);
|
||||||
|
if(device == null) return null;
|
||||||
|
GnssGroupCalc groupCalc = getGroupCalc(device.getCalcGroupId());
|
||||||
|
|
||||||
|
if(completeWhenIdle) resultOutputTimer(device, groupCalc, message.getCreateTime());
|
||||||
|
|
||||||
//todo 创建FocusCalculator对象需获取该测站的杆长度,上一小时的Tilt平均值,上一小时的测站相对坐标融合值ekfResult
|
//todo 创建FocusCalculator对象需获取该测站的杆长度,上一小时的Tilt平均值,上一小时的测站相对坐标融合值ekfResult
|
||||||
FocusCalculator1 focusCalculator = calculatorMap.computeIfAbsent(deviceId, s -> new FocusCalculator1(150,tiltMap.get(deviceId),
|
FocusCalculator focusCalculator;
|
||||||
positionMap.get(deviceId)));
|
/*if(groupCalc!=null && groupCalc.getVer() == 2){
|
||||||
|
focusCalculator = calculatorMap.computeIfAbsent(deviceId,
|
||||||
|
s -> new FocusCalculator2(200,tiltMap.get(deviceId),positionMap.get(deviceId)));
|
||||||
|
}
|
||||||
|
else {*/
|
||||||
|
focusCalculator = calculatorMap.computeIfAbsent(deviceId,
|
||||||
|
s -> new FocusCalculator1(200, tiltMap.get(deviceId),positionMap.get(deviceId)));
|
||||||
|
//}
|
||||||
|
|
||||||
// 读取惯导
|
// 读取惯导
|
||||||
Tilt tilt = message.getTilt();
|
Tilt tilt = message.getTilt();
|
||||||
|
|
||||||
focusCalculator.addTilt(tilt);
|
focusCalculator.addTilt(tilt);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("测站" + deviceId + "的9250单次解析结果:{}", tilt + "," + Arrays.toString(TiltUtil.toPosition(tilt, focusCalculator.getTilt0(), focusCalculator.getPosition0(), focusCalculator.getR())));
|
logger.debug("测站" + deviceId + "惯导单次解析结果:{}", tilt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算延迟
|
// 延迟
|
||||||
focusCalculator.addDelayMs(message.getPps());
|
focusCalculator.addDelayMs(message.getPps());
|
||||||
|
|
||||||
//计算到单次相对位置xyz并记录
|
// 单次b562
|
||||||
double[] doubles = message.getB562_loc();
|
double[] doubles = message.getB562_loc();
|
||||||
focusCalculator.addXyz(doubles);
|
focusCalculator.addXyz(doubles);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
@ -76,10 +104,10 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void calSingleDone(String deviceId, Integer tenantId, LocalDateTime resultTime) {
|
public void calSingleDone(Device device, GnssGroupCalc groupCalc, LocalDateTime resultTime) {
|
||||||
ThreadManager.getScheduledThreadPool().schedule(() -> {
|
ThreadManager.getScheduledThreadPool().schedule(() -> {
|
||||||
try {
|
try {
|
||||||
calCycleResult(deviceId, tenantId, resultTime);
|
calCycleResult(device, groupCalc, resultTime);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e.toString());
|
logger.error(e.toString());
|
||||||
}
|
}
|
||||||
@ -87,9 +115,9 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resultOutputTimer(String deviceId, Integer tenantId, LocalDateTime date){
|
private void resultOutputTimer(Device device, GnssGroupCalc groupCalc,LocalDateTime date){
|
||||||
//40秒没数据后输出结果
|
//40秒没数据后输出结果
|
||||||
ScheduledFuture<?> future = timerMap.get(deviceId);
|
ScheduledFuture<?> future = timerMap.get(device.getDeviceId());
|
||||||
if (future != null && !future.isDone()) {
|
if (future != null && !future.isDone()) {
|
||||||
future.cancel(true);
|
future.cancel(true);
|
||||||
future = null;
|
future = null;
|
||||||
@ -97,41 +125,37 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
|
|
||||||
future = ThreadManager.getScheduledThreadPool().schedule(() -> {
|
future = ThreadManager.getScheduledThreadPool().schedule(() -> {
|
||||||
try {
|
try {
|
||||||
calCycleResult(deviceId, tenantId, date);
|
calCycleResult(device, groupCalc,date);
|
||||||
// 清除统计
|
// 清除统计
|
||||||
Device device = deviceService.findByDeviceId(deviceId);
|
device.clearStat();
|
||||||
if(device != null) device.clearStat();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e.toString());
|
logger.error(e.toString());
|
||||||
}
|
}
|
||||||
},40, TimeUnit.SECONDS);
|
},20, TimeUnit.SECONDS);
|
||||||
timerMap.put(deviceId, future);
|
timerMap.put(device.getDeviceId(), future);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calCycleResult(String deviceId, Integer tenantId, LocalDateTime resultTime) {
|
private void calCycleResult(Device device, GnssGroupCalc groupCalc, LocalDateTime resultTime) {
|
||||||
FocusCalculator1 focusCalculator = calculatorMap.get(deviceId);
|
String deviceId = device.getDeviceId();
|
||||||
|
Integer tenantId = device.getTenantId();
|
||||||
|
FocusCalculator focusCalculator = calculatorMap.get(deviceId);
|
||||||
if(focusCalculator == null) return;
|
if(focusCalculator == null) return;
|
||||||
// 1.检查b562有效数,如果过少,产生告警
|
|
||||||
warningService.checkB562Num(deviceId, tenantId,
|
|
||||||
focusCalculator.getB562Stat());
|
|
||||||
|
|
||||||
// 2.数据处理:参考上次的位置,计算b562重心
|
// 数据处理:参考上次的位置,计算b562重心
|
||||||
double[] lastEfk = null;
|
double[] lastEfk = positionMap.get(deviceId);
|
||||||
if(positionMap.containsKey(deviceId)){
|
|
||||||
lastEfk = positionMap.get(deviceId);
|
|
||||||
}
|
|
||||||
double[] b562Result = focusCalculator.resultB562(lastEfk);
|
double[] b562Result = focusCalculator.resultB562(lastEfk);
|
||||||
double[] r9250Result = null;
|
double[] r9250Result = null; // 倾角转换成杆顶到杆底的位移
|
||||||
//判断 取到的b562 和上次融合坐标做判断,如果距离>100mm 不计算9250
|
double[] mergeResult = null;
|
||||||
if (lastEfk != null && b562Result!=null && FocusCalculator1.disXY(b562Result,lastEfk)<100){
|
//判断 取到的b562 和上次融合坐标做判断,如果距离>200mm 不计算融合值
|
||||||
|
if (lastEfk != null && b562Result!=null && FocusCalculator1.disXY(b562Result,lastEfk)<200){
|
||||||
r9250Result = focusCalculator.result9250();
|
r9250Result = focusCalculator.result9250();
|
||||||
|
mergeResult = focusCalculator.ekfResult(b562Result,r9250Result);//融合位置
|
||||||
}
|
}
|
||||||
double[] result = focusCalculator.ekfResult(b562Result,r9250Result);
|
Tilt tilt = focusCalculator.avgTilt();
|
||||||
Tilt tilt = calcAvgTilt(deviceId);
|
|
||||||
|
|
||||||
logger.info("测站 {} 的b562相对坐标重心:{}", deviceId, Arrays.toString(b562Result));
|
logger.info("测站 {} 的b562相对坐标重心:{}", deviceId, Arrays.toString(b562Result));
|
||||||
logger.info("测站 {} 的9250相对坐标:{}", deviceId, Arrays.toString(r9250Result));
|
logger.info("测站 {} 的惯导相对坐标:{}", deviceId, Arrays.toString(r9250Result));
|
||||||
logger.info("测站 {} 的相对坐标融合值:{}", deviceId, Arrays.toString(result));
|
logger.info("测站 {} 的相对坐标融合值:{}", deviceId, Arrays.toString(mergeResult));
|
||||||
logger.info("测站 {} 的Tilt平均值:{}", deviceId, tilt);
|
logger.info("测站 {} 的Tilt平均值:{}", deviceId, tilt);
|
||||||
logger.info("测站 {} 的平均延迟:{}ms", deviceId, focusCalculator.getAvgDelayMs());
|
logger.info("测站 {} 的平均延迟:{}ms", deviceId, focusCalculator.getAvgDelayMs());
|
||||||
|
|
||||||
@ -143,68 +167,62 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
|
|||||||
} else {
|
} else {
|
||||||
tiltMap.put(deviceId, tilt);
|
tiltMap.put(deviceId, tilt);
|
||||||
}
|
}
|
||||||
}
|
}/*
|
||||||
if (result != null && b562Result != null) {
|
if (mergeResult != null && b562Result != null) {
|
||||||
//这里检查一下result,过滤1千米外非正常数据
|
//这里检查一下result,过滤1千米外非正常数据
|
||||||
if(focusCalculator.dis(result,b562Result) < 1000_00) {
|
if(focusCalculator.dis(mergeResult,b562Result) < 1000_00) {
|
||||||
if (Boolean.TRUE.equals(cleanPositionStatusMap.get(deviceId))) {
|
if (Boolean.TRUE.equals(cleanPositionStatusMap.get(deviceId))) {
|
||||||
// 置为false,下一次计算时就可以正常设置值到positionMap了
|
// 置为false,下一次计算时就可以正常设置值到positionMap了
|
||||||
cleanPositionStatusMap.put(deviceId, Boolean.FALSE);
|
cleanPositionStatusMap.put(deviceId, Boolean.FALSE);
|
||||||
logger.info("置为false,下一次计算时就可以正常设置值到positionMap了");
|
logger.info("置为false,下一次计算时就可以正常设置值到positionMap了");
|
||||||
} else {
|
} else {
|
||||||
positionMap.put(deviceId, result);
|
positionMap.put(deviceId, mergeResult);
|
||||||
}
|
}
|
||||||
postLocationRecord(deviceId, b562Result, r9250Result, result, resultTime,
|
postLocationRecord(deviceId, b562Result, r9250Result, mergeResult, resultTime,
|
||||||
focusCalculator.getAvgDelayMs(), focusCalculator.isShocked());
|
focusCalculator.getAvgDelayMs(), focusCalculator.isShocked());
|
||||||
}else{
|
}else{
|
||||||
logger.error("融合值异常");
|
logger.error("融合值异常");
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
if (b562Result != null) {
|
||||||
|
positionMap.put(deviceId, b562Result);
|
||||||
|
GnssCalcData locationRecord = new GnssCalcData();
|
||||||
|
locationRecord.setCreatetime(resultTime);
|
||||||
|
locationRecord.setUpdatetime(LocalDateTime.now()); //通过这里可以区分补传记录
|
||||||
|
locationRecord.setDeviceid(deviceId);
|
||||||
|
|
||||||
|
// 调用这个函数之前已判断是否为null
|
||||||
|
locationRecord.setB562e(b562Result[0] * 10); //cm->mm
|
||||||
|
locationRecord.setB562n(b562Result[1] * 10);
|
||||||
|
locationRecord.setB562d(b562Result[2] * 10);
|
||||||
|
|
||||||
|
if(r9250Result!=null) {
|
||||||
|
locationRecord.setR9250e(r9250Result[0]);
|
||||||
|
locationRecord.setR9250n(r9250Result[1]);
|
||||||
|
locationRecord.setR9250d(r9250Result[2]);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if(mergeResult!=null){
|
||||||
|
locationRecord.setMpose(mergeResult[0]);
|
||||||
|
locationRecord.setMposn(mergeResult[1]);
|
||||||
|
locationRecord.setMposd(mergeResult[2]);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
locationRecord.setPps(focusCalculator.getAvgDelayMs());
|
||||||
|
gnssCalcFilterService.calc(device, groupCalc, locationRecord, focusCalculator.isShocked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查b562有效数,如果过少,产生告警
|
||||||
|
warningService.checkB562Num(deviceId, tenantId,
|
||||||
|
focusCalculator.getB562Stat());
|
||||||
|
|
||||||
focusCalculator.reset();
|
focusCalculator.reset();
|
||||||
calculatorMap.remove(deviceId);
|
//calculatorMap.remove(deviceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postLocationRecord(String deviceId, double[] b562Result, double[] r9250Result, double[] result,
|
public void refreshGroupCalc(){
|
||||||
LocalDateTime resultTime, int delay, boolean isShocked) {
|
groupCalcList = groupCalcMapper.selectList(null);
|
||||||
GnssCalcData locationRecord = new GnssCalcData();
|
logger.info("group paras changed");
|
||||||
locationRecord.setCreatetime(resultTime);
|
|
||||||
locationRecord.setUpdatetime(LocalDateTime.now()); //通过这里可以区分补传记录
|
|
||||||
locationRecord.setDeviceid(deviceId);
|
|
||||||
|
|
||||||
// 调用这个函数之前已判断是否为null
|
|
||||||
locationRecord.setB562e(b562Result[0] * 10); //cm->mm
|
|
||||||
locationRecord.setB562n(b562Result[1] * 10);
|
|
||||||
locationRecord.setB562d(b562Result[2] * 10);
|
|
||||||
|
|
||||||
if(r9250Result!=null) {
|
|
||||||
locationRecord.setR9250e(r9250Result[0]);
|
|
||||||
locationRecord.setR9250n(r9250Result[1]);
|
|
||||||
locationRecord.setR9250d(r9250Result[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
locationRecord.setPps(delay);
|
|
||||||
gnssCalcFilterService.calc(locationRecord, isShocked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Tilt calcAvgTilt(String deviceId) {
|
|
||||||
FocusCalculator1 focusCalculator = calculatorMap.get(deviceId);
|
|
||||||
if (focusCalculator != null) {
|
|
||||||
return focusCalculator.avgTilt();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 清零:不需要,滤波窗口是按时间来选取历史数据的,只要超过4小时或一天,即使中间没有数据,也不会用
|
|
||||||
* 超过filterCycle的数据
|
|
||||||
|
|
||||||
public void cleanTiltByDeviceId(String deviceId) {
|
|
||||||
logger.info("清零[{}]", deviceId);
|
|
||||||
tiltMap.remove(deviceId);
|
|
||||||
positionMap.remove(deviceId);
|
|
||||||
cleanTiltStatusMap.put(deviceId, Boolean.TRUE);
|
|
||||||
cleanPositionStatusMap.put(deviceId, Boolean.TRUE);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package com.imdroid.sideslope.web;
|
package com.imdroid.sideslope.web;
|
||||||
|
|
||||||
import com.imdroid.secapi.client.HttpResp;
|
import com.imdroid.secapi.client.HttpResp;
|
||||||
|
import com.imdroid.sideslope.calc.MultiLineGNSSCalcService;
|
||||||
|
import com.imdroid.sideslope.calc.SingleLineGNSSCalcService;
|
||||||
import com.imdroid.sideslope.sal.LocalDeviceServiceImpl;
|
import com.imdroid.sideslope.sal.LocalDeviceServiceImpl;
|
||||||
import com.imdroid.sideslope.server.DeviceChannel;
|
import com.imdroid.sideslope.server.DeviceChannel;
|
||||||
import com.imdroid.sideslope.server.OnlineChannels;
|
import com.imdroid.sideslope.server.OnlineChannels;
|
||||||
@ -33,6 +35,10 @@ public class ApiController {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
WarningService warningService;
|
WarningService warningService;
|
||||||
|
@Autowired
|
||||||
|
SingleLineGNSSCalcService calcService;
|
||||||
|
@Autowired
|
||||||
|
MultiLineGNSSCalcService multiCalcService;
|
||||||
|
|
||||||
@PostMapping(value = "/config")
|
@PostMapping(value = "/config")
|
||||||
public HttpResp config(String deviceId, String configuration) {
|
public HttpResp config(String deviceId, String configuration) {
|
||||||
@ -74,6 +80,16 @@ public class ApiController {
|
|||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/group_param_changed")
|
||||||
|
public HttpResp groupParamChanged(){
|
||||||
|
calcService.refreshGroupCalc();
|
||||||
|
multiCalcService.refreshGroupCalc();
|
||||||
|
HttpResp resp = new HttpResp();
|
||||||
|
resp.setResponseMessage("succeed");
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@PostMapping("/warning_param_changed")
|
@PostMapping("/warning_param_changed")
|
||||||
public HttpResp warningParamChanged(){
|
public HttpResp warningParamChanged(){
|
||||||
warningService.refreshCfg();
|
warningService.refreshCfg();
|
||||||
|
|||||||
@ -1,188 +0,0 @@
|
|||||||
import com.imdroid.sideslope.bd.FocusCalculator;
|
|
||||||
import com.imdroid.sideslope.bd.Point;
|
|
||||||
import org.ejml.simple.SimpleMatrix;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class FocusCalculator3 implements FocusCalculator {
|
|
||||||
|
|
||||||
private final List<double[]> list = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
|
|
||||||
private final List<Double> listE = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
|
|
||||||
private final List<Double> listN = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
|
|
||||||
private final List<Double> listD = Collections.synchronizedList(new ArrayList<>());
|
|
||||||
|
|
||||||
private final List<Point> pointList = new ArrayList<>();
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reset(){
|
|
||||||
list.removeAll(list);
|
|
||||||
pointList.removeAll(pointList);
|
|
||||||
listE.removeAll(listE);
|
|
||||||
listD.removeAll(listD);
|
|
||||||
listN.removeAll(listN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 加入list
|
|
||||||
* @param xyz
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void addXyz(double[] xyz){
|
|
||||||
if(filter(xyz)){
|
|
||||||
list.add(xyz);
|
|
||||||
}
|
|
||||||
if(list.size() > 300){
|
|
||||||
list.remove(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean filter(double[] xyz){
|
|
||||||
double a = xyz[0]*xyz[1]*xyz[2];
|
|
||||||
if(a == 0 || Double.isInfinite(a) || Double.isNaN(a)){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] getB562Stat(){
|
|
||||||
return new int[]{0,0,0};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public double[] resultB562(double[] last) {
|
|
||||||
double[] g = {0, 0, 0};
|
|
||||||
if(last != null) g=last;
|
|
||||||
else {
|
|
||||||
for (double[] xyz : list) {
|
|
||||||
g[0] += xyz[0];
|
|
||||||
g[1] += xyz[1];
|
|
||||||
g[2] += xyz[2];
|
|
||||||
}
|
|
||||||
g[0] /= list.size();
|
|
||||||
g[1] /= list.size();
|
|
||||||
g[2] /= list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
makeMatrixList(g);
|
|
||||||
|
|
||||||
double[] l = listE.stream().mapToDouble(Double::doubleValue).toArray();
|
|
||||||
double e = igg3(l);
|
|
||||||
l = listN.stream().mapToDouble(Double::doubleValue).toArray();
|
|
||||||
double n = igg3(l);
|
|
||||||
l = listD.stream().mapToDouble(Double::doubleValue).toArray();
|
|
||||||
double d = igg3(l);
|
|
||||||
|
|
||||||
return new double[]{e,n,d};
|
|
||||||
}
|
|
||||||
|
|
||||||
void makeMatrixList(double[] g){
|
|
||||||
//筛选出半径为r=0.144的圆内的点
|
|
||||||
List<Point> points = new ArrayList<>();
|
|
||||||
for(double[] xyz: list){
|
|
||||||
Point point = new Point(xyz[0], xyz[1], xyz[2]);
|
|
||||||
point.setXDistance(Math.abs(xyz[0]-g[0]));
|
|
||||||
point.setYDistance(Math.abs(xyz[1]-g[1]));
|
|
||||||
point.setZDistance(Math.abs(xyz[2]-g[2]));
|
|
||||||
points.add(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
int calcNum = points.size()*5/10;
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getXDistance));//升序排序
|
|
||||||
for(Point point:points){
|
|
||||||
listE.add(point.getX());
|
|
||||||
if(listE.size()>=calcNum) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getYDistance));//升序排序
|
|
||||||
for(Point point:points){
|
|
||||||
listN.add(point.getY());
|
|
||||||
if(listN.size()>=calcNum) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(points, Comparator.comparing(Point::getZDistance));//升序排序
|
|
||||||
for(Point point:points){
|
|
||||||
listD.add(point.getZ());
|
|
||||||
if(listD.size()>=calcNum) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double igg3(double[] l) {
|
|
||||||
SimpleMatrix L = new SimpleMatrix(l.length,1,false,l);
|
|
||||||
SimpleMatrix B = new SimpleMatrix(l.length,1);
|
|
||||||
B.fill(1);
|
|
||||||
SimpleMatrix P = new SimpleMatrix(l.length, l.length);
|
|
||||||
for(int i=0; i<l.length;i++){
|
|
||||||
//P.set(i,i,1/l[i]);
|
|
||||||
P.set(i,i,1);
|
|
||||||
}
|
|
||||||
double x_prev=0;
|
|
||||||
double x0=0;
|
|
||||||
for(int i=0;i<l.length;i++){
|
|
||||||
x0 += l[i];
|
|
||||||
}
|
|
||||||
x0 /= l.length;
|
|
||||||
|
|
||||||
L = L.minus(x0);
|
|
||||||
SimpleMatrix W,N,X,V,Q,Qvv;
|
|
||||||
SimpleMatrix sigma0;
|
|
||||||
double s0;
|
|
||||||
double k0=1.0, k1=5, k=1.0;
|
|
||||||
int iterNum = 0;
|
|
||||||
|
|
||||||
while(iterNum<10){
|
|
||||||
W = B.transpose().mult(P).mult(L); //W=B'*P*l;
|
|
||||||
N = B.transpose().mult(P).mult(B); //N=B'*P*B;
|
|
||||||
X = N.invert().mult(W); //x=inv(N)*W;% 待估参数向量
|
|
||||||
V = B.mult(X).minus(L); //v=B*x-l;% 残差向量
|
|
||||||
|
|
||||||
sigma0 = V.transpose().mult(P).mult(V).divide((l.length-1));
|
|
||||||
s0 = Math.sqrt(sigma0.get(0,0));//sigma0=sqrt(v'*P*v/(10-1));% 单位权中误差
|
|
||||||
//System.out.println(X);
|
|
||||||
//System.out.println(s0);
|
|
||||||
Q = P.invert();//Q=inv(P);
|
|
||||||
Qvv = Q.minus(B.mult(N.invert().mult(B.transpose())));//Qvv=Q-B*inv(N)*B';
|
|
||||||
|
|
||||||
for(int i=0; i<l.length; i++){
|
|
||||||
double v = V.get(i)/(s0*Math.sqrt(Qvv.get(i,i))); //v_=v(i)/(sigma0*sqrt(Qvv(i,i)));
|
|
||||||
if(Math.abs(v) < k0){
|
|
||||||
k = 1.0;
|
|
||||||
}
|
|
||||||
else if(Math.abs(v) > k1){
|
|
||||||
k = 1e-8;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
k=(k1-Math.abs(v))/(k1-k0);
|
|
||||||
k=k*k*(k0/Math.abs(v));
|
|
||||||
}
|
|
||||||
P.set(i,i,P.get(i,i)*k); //P(i,i)=P(i,i)*k;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(x_prev==0) {
|
|
||||||
x_prev = X.get(0);
|
|
||||||
}
|
|
||||||
else if(Math.abs(x_prev-X.get(0))<0.1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
x_prev = X.get(0);
|
|
||||||
iterNum++;
|
|
||||||
}
|
|
||||||
|
|
||||||
//x=x0+x_prev;%求出的最后长度 初值+改正数
|
|
||||||
return (x0+x_prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -22,8 +22,7 @@ import java.util.ListIterator;
|
|||||||
classes = {
|
classes = {
|
||||||
FocusCalculatorTest.class,
|
FocusCalculatorTest.class,
|
||||||
FocusCalculator1.class,
|
FocusCalculator1.class,
|
||||||
FocusCalculator2.class,
|
FocusCalculator2.class
|
||||||
FocusCalculator3.class
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
|
|||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.imdroid.beidou.common.HttpResult;
|
import com.imdroid.beidou.common.HttpResult;
|
||||||
|
import com.imdroid.secapi.client.RtcmClient;
|
||||||
import com.imdroid.secapi.dto.*;
|
import com.imdroid.secapi.dto.*;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
@ -18,9 +19,10 @@ public class GnssGroupController extends BasicController {
|
|||||||
GnssGroupMapper gnssGroupMapper;
|
GnssGroupMapper gnssGroupMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
GnssGroupCalcMapper gnssGroupCalcMapper;
|
GnssGroupCalcMapper gnssGroupCalcMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
GnssDeviceMapper deviceMapper;
|
GnssDeviceMapper deviceMapper;
|
||||||
|
@Autowired
|
||||||
|
RtcmClient rtcmClient;
|
||||||
|
|
||||||
/********* 推送页面 *********/
|
/********* 推送页面 *********/
|
||||||
@RequestMapping("/page/table/gnss_add_group")
|
@RequestMapping("/page/table/gnss_add_group")
|
||||||
@ -125,7 +127,10 @@ public class GnssGroupController extends BasicController {
|
|||||||
}
|
}
|
||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
return HttpResult.failed();
|
return HttpResult.failed();
|
||||||
} else return HttpResult.ok();
|
} else{
|
||||||
|
rtcmClient.groupParamChanged();
|
||||||
|
return HttpResult.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/gnss/group/delete_calc")
|
@PostMapping("/gnss/group/delete_calc")
|
||||||
@ -141,7 +146,10 @@ public class GnssGroupController extends BasicController {
|
|||||||
int num = gnssGroupCalcMapper.deleteById(del_id);
|
int num = gnssGroupCalcMapper.deleteById(del_id);
|
||||||
if (num == 0) {
|
if (num == 0) {
|
||||||
return HttpResult.failed();
|
return HttpResult.failed();
|
||||||
} else return HttpResult.ok();
|
} else{
|
||||||
|
rtcmClient.groupParamChanged();
|
||||||
|
return HttpResult.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,7 +76,7 @@ public class DatasetCleaner {
|
|||||||
|
|
||||||
void checkFwdDataset(){
|
void checkFwdDataset(){
|
||||||
long before = System.currentTimeMillis() -
|
long before = System.currentTimeMillis() -
|
||||||
(long)365 * 24 * 3600 * 1000;
|
(long)180 * 24 * 3600 * 1000;
|
||||||
Timestamp t = new Timestamp(before);
|
Timestamp t = new Timestamp(before);
|
||||||
int count = fwdRecordMapper.deleteTimeBefore(t);
|
int count = fwdRecordMapper.deleteTimeBefore(t);
|
||||||
log.info("clean fwd dataset num: "+count);
|
log.info("clean fwd dataset num: "+count);
|
||||||
|
|||||||
@ -92,9 +92,9 @@
|
|||||||
{field: 'rpose', title: '相对东', templet: "<div>{{d.rpose==null?'':d.rpose.toFixed(2)}}</div>"},
|
{field: 'rpose', title: '相对东', templet: "<div>{{d.rpose==null?'':d.rpose.toFixed(2)}}</div>"},
|
||||||
{field: 'rposn', title: '相对北', templet: "<div>{{d.rposn==null?'':d.rposn.toFixed(2)}}</div>"},
|
{field: 'rposn', title: '相对北', templet: "<div>{{d.rposn==null?'':d.rposn.toFixed(2)}}</div>"},
|
||||||
{field: 'rposd', title: '相对天', templet: "<div>{{d.rposd==null?'':d.rposd.toFixed(2)}}</div>"},
|
{field: 'rposd', title: '相对天', templet: "<div>{{d.rposd==null?'':d.rposd.toFixed(2)}}</div>"},
|
||||||
{field: 'auxe', title: '辅助东', templet: "<div>{{d.auxe==null?'':d.auxe.toFixed(2)}}</div>"},
|
//{field: 'auxe', title: '辅助东', templet: "<div>{{d.auxe==null?'':d.auxe.toFixed(2)}}</div>"},
|
||||||
{field: 'auxn', title: '辅助北', templet: "<div>{{d.auxn==null?'':d.auxn.toFixed(2)}}</div>"},
|
//{field: 'auxn', title: '辅助北', templet: "<div>{{d.auxn==null?'':d.auxn.toFixed(2)}}</div>"},
|
||||||
{field: 'auxd', title: '辅助天', templet: "<div>{{d.auxd==null?'':d.auxd.toFixed(2)}}</div>"},
|
//{field: 'auxd', title: '辅助天', templet: "<div>{{d.auxd==null?'':d.auxd.toFixed(2)}}</div>"},
|
||||||
{field: 'enabled', title: '有效',templet: '#enabledTrans'},
|
{field: 'enabled', title: '有效',templet: '#enabledTrans'},
|
||||||
{field: 'pps', title: '平均延迟'}
|
{field: 'pps', title: '平均延迟'}
|
||||||
];
|
];
|
||||||
|
|||||||
128
sec-test-device/pom.xml
Normal file
128
sec-test-device/pom.xml
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>security-monitor</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>sec-test-device</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.1.78.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5.13</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>sec-api</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>sec-common</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.76</version>
|
||||||
|
</dependency>
|
||||||
|
<!--mqtt相关依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
<version>1.2.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>11</source>
|
||||||
|
<target>11</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>ali-mirror</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/central</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.imdroid.beidou.test_device;
|
||||||
|
|
||||||
|
import com.imdroid.beidou.test_device.task.BeidouDevice;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/1/31 20:33
|
||||||
|
*/
|
||||||
|
@SpringBootApplication(scanBasePackages = {"com.imdroid"})
|
||||||
|
@ComponentScan({"com.imdroid.*"})
|
||||||
|
public class BeidouTestApp {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
SpringApplication.run(BeidouTestApp.class, args);
|
||||||
|
BeidouDevice beidouDevice = new BeidouDevice();
|
||||||
|
beidouDevice.connectServer();
|
||||||
|
beidouDevice.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package com.imdroid.beidou.test_device.service;
|
||||||
|
|
||||||
|
import com.imdroid.common.util.ThreadManager;
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.channel.*;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class TCPClient {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
private Bootstrap bootstrap;
|
||||||
|
private EventLoopGroup group;
|
||||||
|
private Channel channel;
|
||||||
|
LocalDateTime connectTime = LocalDateTime.now();
|
||||||
|
TCPListener listener;
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
new Thread(this::connect, "forwarder tcp-client").start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(String dest_addr, int dest_port, TCPListener listener) {
|
||||||
|
this.host = dest_addr;
|
||||||
|
this.port = dest_port;
|
||||||
|
this.listener = listener;
|
||||||
|
|
||||||
|
//客户端需要一个事件循环组
|
||||||
|
group = new NioEventLoopGroup();
|
||||||
|
//创建客户端启动对象
|
||||||
|
// bootstrap 可重用, 只需在NettyClient实例化的时候初始化即可.
|
||||||
|
bootstrap = new Bootstrap();
|
||||||
|
bootstrap.group(group)
|
||||||
|
.channel(NioSocketChannel.class)
|
||||||
|
.handler(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
protected void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
//加入处理器
|
||||||
|
ch.pipeline().addLast(new TcpMessageHandler(TCPClient.this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
logger.info("netty client starting");
|
||||||
|
//启动客户端去连接服务器端
|
||||||
|
try {
|
||||||
|
ChannelFuture cf = bootstrap.connect(host, port);
|
||||||
|
cf.addListener(new ChannelFutureListener() {
|
||||||
|
@Override
|
||||||
|
public void operationComplete(ChannelFuture future) throws Exception {
|
||||||
|
if (!future.isSuccess()) {
|
||||||
|
//重连交给后端线程执行
|
||||||
|
future.channel().eventLoop().schedule(() -> {
|
||||||
|
logger.info("tcp client reconnect");
|
||||||
|
try {
|
||||||
|
connect();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, 5000, TimeUnit.MILLISECONDS);
|
||||||
|
} else {
|
||||||
|
logger.info("tcp client start success!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//对通道关闭进行监听
|
||||||
|
this.channel = cf.channel();
|
||||||
|
this.channel.closeFuture().sync();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("netty client error:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeAndFlush(String json) {
|
||||||
|
ByteBuf sendBuffer = Unpooled.buffer();
|
||||||
|
sendBuffer.writeBytes(json.getBytes(StandardCharsets.UTF_8));
|
||||||
|
channel.writeAndFlush(sendBuffer).addListener(future -> {
|
||||||
|
if (future.isSuccess()) {
|
||||||
|
logger.info("send to tcp:"+host+" succeed.");
|
||||||
|
} else {
|
||||||
|
logger.info("send to tcp:"+host+" failed.");
|
||||||
|
if(listener!=null){
|
||||||
|
listener.onMessage("failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onConnected(){
|
||||||
|
connectTime = LocalDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisconnect(){
|
||||||
|
if(connectTime.isBefore(LocalDateTime.now().minusMinutes(1))) {
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
ThreadManager.getScheduledThreadPool().schedule(() -> {
|
||||||
|
try {
|
||||||
|
connect();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.toString());
|
||||||
|
}
|
||||||
|
},60, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onMessage(String msg){
|
||||||
|
if(listener!=null){
|
||||||
|
listener.onMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
package com.imdroid.beidou.test_device.service;
|
||||||
|
|
||||||
|
public interface TCPListener {
|
||||||
|
void onConnected();
|
||||||
|
void onDisconnect();
|
||||||
|
void onMessage(String msg);
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package com.imdroid.beidou.test_device.service;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/18 20:36
|
||||||
|
*/
|
||||||
|
public class TcpMessageHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private final TCPClient tcpClient;
|
||||||
|
|
||||||
|
public TcpMessageHandler(TCPClient tcpClient) {
|
||||||
|
this.tcpClient = tcpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf buf) throws Exception {
|
||||||
|
String msg = buf.toString(Charset.defaultCharset());
|
||||||
|
tcpClient.onMessage(msg);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("receive server message:" + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
logger.info("tcp channel active");
|
||||||
|
tcpClient.onConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
logger.info("tcp channel inactive");
|
||||||
|
tcpClient.onDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
|
logger.error("TcpMessageHandler error: {}", cause.toString());
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package com.imdroid.beidou.test_device.service;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.net.DatagramPacket;
|
||||||
|
import java.net.DatagramSocket;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
|
||||||
|
public class UDPClient {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
private DatagramSocket socket;
|
||||||
|
|
||||||
|
private InetAddress inetAddress;
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
public void init(String host, int port) {
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
try {
|
||||||
|
logger.info("UDP client init "+host + ":" + port);
|
||||||
|
this.socket = new DatagramSocket();
|
||||||
|
this.inetAddress = InetAddress.getByName(host);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("初始化udp客户端失败:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendData(byte[] data) {
|
||||||
|
try {
|
||||||
|
DatagramPacket packet = new DatagramPacket(data, data.length, inetAddress, port);
|
||||||
|
socket.send(packet);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("udp推送gnss数据异常:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package com.imdroid.beidou.test_device.task;
|
||||||
|
|
||||||
|
import com.imdroid.beidou.test_device.service.UDPClient;
|
||||||
|
import com.imdroid.common.util.ByteUtil;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class BeidouDevice {
|
||||||
|
private String host="127.0.0.1";
|
||||||
|
|
||||||
|
private int port=9903;
|
||||||
|
|
||||||
|
UDPClient udpClient;
|
||||||
|
public void connectServer(){
|
||||||
|
udpClient = new UDPClient();
|
||||||
|
udpClient.init(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run(){
|
||||||
|
try{
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412270_1xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412270_2xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_1xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_2xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_3xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_4xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_5xx.log");
|
||||||
|
//execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_6xx.log");
|
||||||
|
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_1.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_2.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_1xx.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_2xx.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_3xx.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_4xx.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_5xx.log");
|
||||||
|
execute("C:\\Users\\wd\\Desktop\\log\\b562_2412254_0416_6xx.log");
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
|
||||||
|
}
|
||||||
|
System.out.println("finish!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(String dataFileName) throws IOException {
|
||||||
|
FileReader fr=null;
|
||||||
|
BufferedReader br=null;
|
||||||
|
try {
|
||||||
|
fr = new FileReader(dataFileName);
|
||||||
|
br = new BufferedReader(fr);
|
||||||
|
String line = "";
|
||||||
|
String[] arrs = null;
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
|
||||||
|
long lastTime = 0;
|
||||||
|
int b562Count = 0;
|
||||||
|
int cycleCount = 0;
|
||||||
|
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
arrs = line.split(" ");
|
||||||
|
if(arrs.length != 3) continue;
|
||||||
|
Date time = sdf.parse(arrs[0] + " " + arrs[1]);
|
||||||
|
|
||||||
|
if (lastTime!=0 && Math.abs(time.getTime() - lastTime) > 60 * 1000) {//超过1分钟为一个周期
|
||||||
|
Thread.sleep(30 * 1000);
|
||||||
|
cycleCount++;
|
||||||
|
System.out.println(time+" cycle "+cycleCount+", b562 num "+b562Count);
|
||||||
|
}
|
||||||
|
udpClient.sendData(ByteUtil.hexStringTobyte(arrs[2]));
|
||||||
|
b562Count++;
|
||||||
|
lastTime = time.getTime();
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
fr.close();
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
if(br!=null) br.close();
|
||||||
|
if(fr!=null) fr.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
sec-test-device/src/main/resources/application.properties
Normal file
22
sec-test-device/src/main/resources/application.properties
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
server.port=9916
|
||||||
|
server.servlet.context-path=/gnss
|
||||||
|
|
||||||
|
spring.application.name=test-gnss
|
||||||
|
spring.application.build=20240106
|
||||||
|
|
||||||
|
spring.jpa.show-sql = true
|
||||||
|
spring.jpa.hibernate.ddl-auto = none
|
||||||
|
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
|
||||||
|
spring.datasource.url = jdbc:mysql://localhost:3306/beidou?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.username = admin
|
||||||
|
spring.datasource.password = DBMgr_2022
|
||||||
|
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
spring.jackson.dateFormat = yyyy-MM-dd HH:mm:ss
|
||||||
|
spring.jackson.time-zone = GMT+8
|
||||||
|
|
||||||
|
app.format.date = yyyy-MM-dd
|
||||||
|
app.format.time = HH:mm:ss
|
||||||
|
app.format.datetime = yyyy-MM-dd HH:mm:ss
|
||||||
|
|
||||||
|
mybatis-plus.configuration.map-underscore-to-camel-case=false
|
||||||
Loading…
x
Reference in New Issue
Block a user