2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
24 #include "navigation/navigation.h"
25 #include "navigation/navigation_private.h"
27 #include "common/maths.h"
28 #pragma GCC diagnostic push
29 #pragma GCC diagnostic ignored "-Wunused-function"
30 #include "common/mavlink.h"
31 #pragma GCC diagnostic pop
39 adsbVehicle_t adsbVehiclesList
[MAX_ADSB_VEHICLES
];
40 adsbVehicleStatus_t adsbVehiclesStatus
;
42 adsbVehicleValues_t vehicleValues
;
45 adsbVehicleValues_t
* getVehicleForFill(void){
46 return &vehicleValues
;
49 // use bsearch function
50 adsbVehicle_t
*findVehicleByIcao(uint32_t avicao
) {
51 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
52 if (avicao
== adsbVehiclesList
[i
].vehicleValues
.icao
) {
53 return &adsbVehiclesList
[i
];
59 adsbVehicle_t
*findVehicleFarthest(void) {
60 adsbVehicle_t
*adsbLocal
= NULL
;
61 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
62 if (adsbVehiclesList
[i
].ttl
> 0 && adsbVehiclesList
[i
].calculatedVehicleValues
.valid
&& (adsbLocal
== NULL
|| adsbLocal
->calculatedVehicleValues
.dist
< adsbVehiclesList
[i
].calculatedVehicleValues
.dist
)) {
63 adsbLocal
= &adsbVehiclesList
[i
];
69 uint8_t getActiveVehiclesCount(void) {
71 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
72 if (adsbVehiclesList
[i
].ttl
> 0) {
79 adsbVehicle_t
*findVehicleClosest(void) {
80 adsbVehicle_t
*adsbLocal
= NULL
;
81 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
82 if (adsbVehiclesList
[i
].ttl
> 0 && adsbVehiclesList
[i
].calculatedVehicleValues
.valid
&& (adsbLocal
== NULL
|| adsbLocal
->calculatedVehicleValues
.dist
> adsbVehiclesList
[i
].calculatedVehicleValues
.dist
)) {
83 adsbLocal
= &adsbVehiclesList
[i
];
89 adsbVehicle_t
*findFreeSpaceInList(void) {
91 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
92 if (adsbVehiclesList
[i
].ttl
== 0) {
93 return &adsbVehiclesList
[i
];
100 adsbVehicle_t
*findVehicleNotCalculated(void) {
102 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
103 if (adsbVehiclesList
[i
].calculatedVehicleValues
.valid
== false) {
104 return &adsbVehiclesList
[i
];
111 adsbVehicle_t
* findVehicle(uint8_t index
)
113 if (index
< MAX_ADSB_VEHICLES
){
114 return &adsbVehiclesList
[index
];
120 adsbVehicleStatus_t
* getAdsbStatus(void){
121 return &adsbVehiclesStatus
;
124 void gpsDistanceCmBearing(int32_t currentLat1
, int32_t currentLon1
, int32_t destinationLat2
, int32_t destinationLon2
, uint32_t *dist
, int32_t *bearing
) {
125 float GPS_scaleLonDown
= cos_approx((fabsf((float) gpsSol
.llh
.lat
) / 10000000.0f
) * 0.0174532925f
);
126 const float dLat
= destinationLat2
- currentLat1
; // difference of latitude in 1/10 000 000 degrees
127 const float dLon
= (float) (destinationLon2
- currentLon1
) * GPS_scaleLonDown
;
129 *dist
= sqrtf(sq(dLat
) + sq(dLon
)) * DISTANCE_BETWEEN_TWO_LONGITUDE_POINTS_AT_EQUATOR
;
130 *bearing
= 9000.0f
+ RADIANS_TO_CENTIDEGREES(atan2_approx(-dLat
, dLon
)); // Convert the output radians to 100xdeg
131 *bearing
= wrap_36000(*bearing
);
134 void adsbNewVehicle(adsbVehicleValues_t
* vehicleValuesLocal
) {
136 // no valid lat lon or altitude
137 if((vehicleValuesLocal
->flags
& (ADSB_FLAGS_VALID_ALTITUDE
| ADSB_FLAGS_VALID_COORDS
)) != (ADSB_FLAGS_VALID_ALTITUDE
| ADSB_FLAGS_VALID_COORDS
)){
141 adsbVehiclesStatus
.vehiclesMessagesTotal
++;
142 adsbVehicle_t
*vehicle
= NULL
;
144 vehicle
= findVehicleByIcao(vehicleValuesLocal
->icao
);
145 if(vehicle
!= NULL
&& vehicleValuesLocal
->tslc
> ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST
){
150 // non GPS mode, GPS is not fix, just find free space in list or by icao and save vehicle without calculated values
151 if (!enviromentOkForCalculatingDistaceBearing()) {
154 vehicle
= findFreeSpaceInList();
157 if (vehicle
!= NULL
) {
158 memcpy(&(vehicle
->vehicleValues
), vehicleValuesLocal
, sizeof(vehicle
->vehicleValues
));
159 vehicle
->ttl
= ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST
;
160 vehicle
->calculatedVehicleValues
.valid
= false;
164 // GPS mode, GPS is fixed and has enough sats
168 vehicle
= findFreeSpaceInList();
172 vehicle
= findVehicleNotCalculated();
176 vehicle
= findVehicleFarthest();
179 if (vehicle
!= NULL
) {
180 memcpy(&(vehicle
->vehicleValues
), vehicleValuesLocal
, sizeof(vehicle
->vehicleValues
));
181 recalculateVehicle(vehicle
);
182 vehicle
->ttl
= ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST
;
188 void recalculateVehicle(adsbVehicle_t
* vehicle
){
189 gpsDistanceCmBearing(gpsSol
.llh
.lat
, gpsSol
.llh
.lon
, vehicle
->vehicleValues
.lat
, vehicle
->vehicleValues
.lon
, &(vehicle
->calculatedVehicleValues
.dist
), &(vehicle
->calculatedVehicleValues
.dir
));
191 if (vehicle
!= NULL
&& vehicle
->calculatedVehicleValues
.dist
> ADSB_LIMIT_CM
) {
196 vehicle
->calculatedVehicleValues
.verticalDistance
= vehicle
->vehicleValues
.alt
- (int32_t)getEstimatedActualPosition(Z
) - GPS_home
.alt
;
197 vehicle
->calculatedVehicleValues
.valid
= true;
200 void adsbTtlClean(timeUs_t currentTimeUs
) {
202 static timeUs_t adsbTtlLastCleanServiced
= 0;
203 timeDelta_t adsbTtlSinceLastCleanServiced
= cmpTimeUs(currentTimeUs
, adsbTtlLastCleanServiced
);
206 if (adsbTtlSinceLastCleanServiced
> 1000000) // 1s
208 for (uint8_t i
= 0; i
< MAX_ADSB_VEHICLES
; i
++) {
209 if (adsbVehiclesList
[i
].ttl
> 0) {
210 adsbVehiclesList
[i
].ttl
--;
214 adsbTtlLastCleanServiced
= currentTimeUs
;
218 bool enviromentOkForCalculatingDistaceBearing(void){
219 return (STATE(GPS_FIX
) && gpsSol
.numSat
> 4);