2 * This file is part of u360gts, aka amv-open360tracker 32bits:
3 * https://github.com/raul-ortega/amv-open360tracker-32bits
5 * u360gts is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * u360gts is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with u360gts. If not, see <http://www.gnu.org/licenses/>.
20 #include "gps_estimation.h"
25 #include "telemetry.h"
26 #include "interpolation.h"
28 #define earthRadius 6378137.0f
32 uint32_t estimatedTime
;
33 float estimatedDistance
;
34 float estimatedAccDistance
;
35 float estimatedHeading
;
37 uint16_t positionIndex
=0;
41 #define PVQ_ELEMENTS 20
42 pvQElement_t epsVectors
[PVQ_ELEMENTS
];
49 PVQ_SIZE
= PVQ_ELEMENTS
;
55 return (pvQIn
== (( pvQOut
- 1 + PVQ_SIZE
) % PVQ_SIZE
));
58 return (pvQIn
== pvQOut
);
60 bool pvPut(epsVector_t
*pvector
, uint8_t vectorType
){
66 epsVectors
[pvQIn
].heading
= pvector
->heading
;
67 epsVectors
[pvQIn
].distance
= pvector
->distance
;
68 epsVectors
[pvQIn
].speed
= pvector
->speed
;
69 epsVectors
[pvQIn
].lat_a
= pvector
->lat_a
;
70 epsVectors
[pvQIn
].lat_b
= pvector
->lat_b
;
71 epsVectors
[pvQIn
].lon_a
= pvector
->lon_a
;
72 epsVectors
[pvQIn
].lon_b
= pvector
->lon_b
;
73 epsVectors
[pvQIn
].lat_sgn
= pvector
->lat_sgn
;
74 epsVectors
[pvQIn
].lon_sgn
= pvector
->lon_sgn
;
75 epsVectors
[pvQIn
].time
= pvector
->time
;
76 epsVectors
[pvQIn
].index
= pvector
->index
;
77 epsVectors
[pvQIn
].type
= vectorType
;
79 pvQIn
= (pvQIn
+ 1) % PVQ_SIZE
;
84 pvQElement_t
pvGet(void){
86 pvQElement_t pvector
= {0,0,0,0,0,0,0,0};
93 pvector
= epsVectors
[pvQOut
];
95 pvQOut
= (pvQOut
+ 1) % PVQ_SIZE
;
100 float epsVectorSpeed(uint32_t last_time
,uint32_t currentTime
, float distance
){
101 if(last_time
== currentTime
|| distance
== 0)
105 vartime
= currentTime
- last_time
;
106 speed
= distance
/ (vartime
/ 1000.0f
);
110 void epsVectorAddPoint(epsVector_t
*last
, epsVector_t
*current
){
115 delta
.speed
= current
->speed
- last
->speed
;
116 delta
.heading
= current
->heading
- last
->heading
;
118 if(current
->heading
< last
->heading
)
119 delta
.heading
= delta
.heading
+ 360;
121 if (delta
.heading
> 180)
122 delta
.heading
-= 360.0f
;
123 else if (delta
.heading
< -180)
124 delta
.heading
+= 360.0f
;
126 iPutPoint(current
->time
,delta
.heading
,delta
.speed
);
129 void epsVectorEstimate(epsVector_t
*last
, epsVector_t
*current
, epsVector_t
*estimated
,epsVectorGain_t gain
, uint32_t eps_frequency
,uint8_t eps_mode
){
130 float angularDistance
;
131 float headingRadians
;
138 estimatedHeading
= current
->heading
;
139 estimatedSpeed
= current
->speed
;
140 estimatedTime
= millis();
143 vartime
= estimatedTime
- current
->time
;
144 estimatedDistance
= current
->speed
* (vartime
/ 1000.0f
) *(gain
.distance
/ 100.0f
);
145 if(interpolationOn
) {
149 delta
= iEval(estimatedTime
);
150 estimatedHeading
= current
->heading
+ delta
.heading
* (gain
.heading
/ 100.0f
);
151 if(estimatedHeading
< 0)
152 estimatedHeading
+= 360;
153 if(estimatedHeading
> 360)
154 estimatedHeading
-= 360;
155 //estimatedHeading = fmod(estimatedHeading,360.0f);
156 estimatedSpeed
= current
->speed
+ delta
.speed
* (gain
.speed
/ 100.0f
);
157 estimatedDistance
= estimatedSpeed
* (vartime
/ 1000.0f
);
160 } else if(eps_mode
== 1) {
161 estimatedDistance
= (current
->distance
* gain
.distance
/ 100.0);
164 estimatedAccDistance
+= estimatedDistance
;
166 angularDistance
= estimatedDistance
/ earthRadius
;
168 headingRadians
= radians(estimatedHeading
);
170 lat2
= asin(sin(radians(current
->lat
/TELEMETRY_LATLON_DIVIDER_F
))*cos(angularDistance
) + cos(radians(current
->lat
/TELEMETRY_LATLON_DIVIDER_F
))*sin(angularDistance
)*cos(headingRadians
));
171 x
= cos(angularDistance
) - sin(radians(current
->lat
/TELEMETRY_LATLON_DIVIDER_F
)) * sin(lat2
);
172 y
= sin(headingRadians
) * sin(angularDistance
) * cos(radians(current
->lat
/TELEMETRY_LATLON_DIVIDER_F
));
173 lon2
= radians(current
->lon
/TELEMETRY_LATLON_DIVIDER_F
) + atan2(y
, x
);
174 lat2
= degrees(lat2
);
175 lon2
= fmod(degrees(lon2
) + 540,360)-180;
177 estimated
->lat
= lat2
* TELEMETRY_LATLON_DIVIDER_I
;
178 estimated
->lon
= lon2
* TELEMETRY_LATLON_DIVIDER_I
;
179 estimated
->lat_a
= abs(estimated
->lat
/ TELEMETRY_LATLON_DIVIDER_I
);
180 estimated
->lat_b
= abs(estimated
->lat
% TELEMETRY_LATLON_DIVIDER_I
);
181 estimated
->lat_sgn
= (estimated
->lat
< 0) ? -1 : 1;
182 estimated
->lon_a
= abs(estimated
->lon
/ TELEMETRY_LATLON_DIVIDER_I
);
183 estimated
->lon_b
= abs(estimated
->lon
% TELEMETRY_LATLON_DIVIDER_I
);
184 estimated
->lon_sgn
= (estimated
->lon
< 0) ? -1 : 1;
185 estimated
->time
= estimatedTime
;
186 estimated
->heading
= estimatedHeading
;
187 estimated
->speed
= estimatedSpeed
;
188 estimated
->distance
= estimatedDistance
;
190 estimated
->index
= positionIndex
;
196 void epsVectorsInit(epsVector_t
*last
, epsVector_t
*current
, epsVector_t
*estimated
, uint8_t interpolation
,uint8_t points
){
209 current
->heading
= 0;
211 current
->distance
= 0;
218 estimated
->heading
= 0;
219 estimated
->speed
= 0;
220 estimated
->distance
= 0;
221 estimated
->speed
= 0;
225 estimated
->index
= 0;
229 if(interpolation
== 1) {
231 interpolationOn
= true;
235 void epsVectorCurrentToLast(epsVector_t
*current
,epsVector_t
*last
){
236 last
->heading
= current
->heading
;
237 last
->speed
= current
->speed
;
238 last
->distance
= current
->distance
;
239 last
->speed
= current
->speed
;
240 last
->lat
= current
->lat
;
241 last
->lon
= current
->lon
;
242 last
->time
= current
->time
;
243 last
->lat_a
= current
->lat_a
;
244 last
->lat_b
= current
->lat_b
;
245 last
->lat_sgn
= current
->lat_sgn
;
246 last
->lon_a
= current
->lon_a
;
247 last
->lon_b
= current
->lon_b
;
248 last
->lon_sgn
= current
->lon_sgn
;
251 void epsVectorLoad(epsVector_t
*current
,int32_t lat
,int32_t lon
,float distance
, uint32_t last_time
, uint32_t currentTime
){
255 current
->time
= currentTime
;
256 current
->distance
= distance
;
257 current
->speed
= epsVectorSpeed(last_time
,currentTime
,distance
);
258 current
->lat_a
= abs(current
->lat
/ TELEMETRY_LATLON_DIVIDER_I
);
259 current
->lat_b
= abs(current
->lat
% TELEMETRY_LATLON_DIVIDER_I
);
260 current
->lat_sgn
= (current
->lat
< 0) ? -1 : 1;
261 current
->lon_a
= abs(current
->lon
/ TELEMETRY_LATLON_DIVIDER_I
);
262 current
->lon_b
= abs(current
->lon
% TELEMETRY_LATLON_DIVIDER_I
);
263 current
->lon_sgn
= (current
->lon
< 0) ? -1 : 1;
265 current
->index
= positionIndex
;
269 uint16_t getPositionVectorIndex(void){
270 return positionIndex
++;