Skip to content

Commit 5689aa1

Browse files
Merge pull request #10927 from error414/adsb-better-look
ADSB - Use extended OSD glyphs for dot in numbers and improve aircraft warni…
2 parents a3286c1 + fc2f5db commit 5689aa1

File tree

10 files changed

+300
-115
lines changed

10 files changed

+300
-115
lines changed

docs/ADSB.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ is an air traffic surveillance technology that enables aircraft to be accurately
77

88
OSD can be configured to shows the closest aircraft.
99

10+
## OSD element
11+
OSD can be configured to simple view (one line) or to extended view (two lines) by \
12+
`set osd_adsb_warning_style=EXTENDED`
13+
14+
### Simple view
15+
`{distance to vehicle} {direction to vehicle} {altitude diff}`
16+
17+
### Extended view
18+
`{distance to vehicle} {direction to vehicle} {altitude diff}` \
19+
`{Emiter Type} {Vehicle direction} {Vehicle Speed}`
20+
21+
![ADSB OSD](assets/images/adsb-info.png)
22+
23+
1024
## Hardware
1125

1226
All ADSB receivers which can send Mavlink [ADSB_VEHICLE](https://mavlink.io/en/messages/common.html#ADSB_VEHICLE) message are supported

docs/Settings.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4492,6 +4492,16 @@ Ignore adsb planes above, limit, 0 disabled (meters)
44924492

44934493
---
44944494

4495+
### osd_adsb_warning_style
4496+
4497+
ADSB warning element style, how rich information on scree will be, Possible values are `COMPACT` and `EXTENDED`
4498+
4499+
| Default | Min | Max |
4500+
| --- | --- | --- |
4501+
| COMPACT | | |
4502+
4503+
---
4504+
44954505
### osd_ahi_bordered
44964506

44974507
Shows a border/corners around the AHI region (pixel OSD only)
@@ -5504,7 +5514,7 @@ Use custom pilot logo with/instead of the INAV logo. The pilot logo must be char
55045514

55055515
### osd_video_system
55065516

5507-
Video system used. Possible values are `AUTO`, `PAL`, `NTSC`, `HDZERO`, 'DJIWTF', 'AVATAR' and `BF43COMPAT`
5517+
Video system used. Possible values are `AUTO`, `PAL`, `NTSC`, `HDZERO`, 'DJIWTF', 'AVATAR', `BF43COMPAT`, `BFHDCOMPAT` and `DJI_NATIVE`
55085518

55095519
| Default | Min | Max |
55105520
| --- | --- | --- |

docs/assets/images/adsb-info.png

540 KB
Loading

src/main/fc/fc_msp.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -971,8 +971,8 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
971971
}
972972

973973
sbufWriteU32(dst, adsbVehicle->vehicleValues.icao);
974-
sbufWriteU32(dst, adsbVehicle->vehicleValues.lat);
975-
sbufWriteU32(dst, adsbVehicle->vehicleValues.lon);
974+
sbufWriteU32(dst, adsbVehicle->vehicleValues.gps.lat);
975+
sbufWriteU32(dst, adsbVehicle->vehicleValues.gps.lon);
976976
sbufWriteU32(dst, adsbVehicle->vehicleValues.alt);
977977
sbufWriteU16(dst, (uint16_t)CENTIDEGREES_TO_DEGREES(adsbVehicle->vehicleValues.heading));
978978
sbufWriteU8(dst, adsbVehicle->vehicleValues.tslc);
@@ -1584,6 +1584,11 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF
15841584
sbufWriteU8(dst, osdConfig()->sidebar_scroll_arrows);
15851585
sbufWriteU8(dst, osdConfig()->units);
15861586
sbufWriteU8(dst, osdConfig()->stats_energy_unit);
1587+
#ifdef USE_ADSB
1588+
sbufWriteU8(dst, osdConfig()->adsb_warning_style);
1589+
#else
1590+
sbufWriteU8(dst, 0);
1591+
#endif
15871592
break;
15881593

15891594
#endif
@@ -3291,7 +3296,12 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
32913296

32923297
case MSP2_INAV_OSD_SET_PREFERENCES:
32933298
{
3294-
if (dataSize == 9) {
3299+
if (
3300+
dataSize == 9
3301+
#ifdef USE_ADSB
3302+
|| dataSize == 10
3303+
#endif
3304+
) {
32953305
osdConfigMutable()->video_system = sbufReadU8(src);
32963306
osdConfigMutable()->main_voltage_decimals = sbufReadU8(src);
32973307
osdConfigMutable()->ahi_reverse_roll = sbufReadU8(src);
@@ -3301,6 +3311,11 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
33013311
osdConfigMutable()->sidebar_scroll_arrows = sbufReadU8(src);
33023312
osdConfigMutable()->units = sbufReadU8(src);
33033313
osdConfigMutable()->stats_energy_unit = sbufReadU8(src);
3314+
#ifdef USE_ADSB
3315+
if(dataSize == 10) {
3316+
osdConfigMutable()->adsb_warning_style = sbufReadU8(src);
3317+
}
3318+
#endif
33043319
osdStartFullRedraw();
33053320
} else
33063321
return MSP_RESULT_ERROR;

src/main/fc/settings.yaml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ tables:
209209
enum: fenceAction_e
210210
- name: geozone_rth_no_way_home
211211
values: [RTH, EMRG_LAND]
212+
- name: osd_adsb_warning_style
213+
values: [ "COMPACT", "EXTENDED" ]
214+
enum: osd_adsb_warning_style_e
212215

213216
constants:
214217
RPYL_PID_MIN: 0
@@ -3271,7 +3274,7 @@ groups:
32713274
type: uint8_t
32723275
default_value: "OFF"
32733276
- name: osd_video_system
3274-
description: "Video system used. Possible values are `AUTO`, `PAL`, `NTSC`, `HDZERO`, 'DJIWTF', 'AVATAR' and `BF43COMPAT`"
3277+
description: "Video system used. Possible values are `AUTO`, `PAL`, `NTSC`, `HDZERO`, 'DJIWTF', 'AVATAR', `BF43COMPAT`, `BFHDCOMPAT` and `DJI_NATIVE`"
32753278
default_value: "AUTO"
32763279
table: osd_video_system
32773280
field: video_system
@@ -3471,7 +3474,6 @@ groups:
34713474
field: ahi_max_pitch
34723475
min: 10
34733476
max: 90
3474-
default_value: 20
34753477
- name: osd_crosshairs_style
34763478
description: "To set the visual type for the crosshair"
34773479
default_value: "DEFAULT"
@@ -3644,6 +3646,13 @@ groups:
36443646
min: 0
36453647
max: 64000
36463648
type: uint16_t
3649+
- name: osd_adsb_warning_style
3650+
description: "ADSB warning element style, how rich information on scree will be, Possible values are `COMPACT` and `EXTENDED`"
3651+
default_value: "COMPACT"
3652+
table: osd_adsb_warning_style
3653+
field: adsb_warning_style
3654+
type: uint8_t
3655+
condition: USE_ADSB
36473656
- name: osd_estimations_wind_compensation
36483657
description: "Use wind estimation for remaining flight time/distance estimation"
36493658
default_value: ON

src/main/io/adsb.c

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
/*
2-
* This file is part of Cleanflight.
2+
* This file is part of INAV Project.
33
*
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.
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
6+
* You can obtain one at http://mozilla.org/MPL/2.0/.
87
*
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.
8+
* Alternatively, the contents of this file may be used under the terms
9+
* of the GNU General Public License Version 3, as described below:
10+
*
11+
* This file is free software: you may copy, redistribute and/or modify
12+
* it under the terms of the GNU General Public License as published by the
13+
* Free Software Foundation, either version 3 of the License, or (at your
14+
* option) any later version.
15+
*
16+
* This file is distributed in the hope that it will be useful, but
17+
* WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19+
* Public License for more details.
1320
*
1421
* You should have received a copy of the GNU General Public License
15-
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
22+
* along with this program. If not, see http://www.gnu.org/licenses/.
1623
*/
1724

1825

@@ -86,6 +93,26 @@ adsbVehicle_t *findVehicleClosest(void) {
8693
return adsbLocal;
8794
}
8895

96+
/**
97+
* find the closest vehicle, apply filter max verticalDistance
98+
* @return
99+
*/
100+
adsbVehicle_t *findVehicleClosestLimit(int32_t maxVerticalDistance) {
101+
adsbVehicle_t *adsbLocal = NULL;
102+
for (uint8_t i = 0; i < MAX_ADSB_VEHICLES; i++) {
103+
if(adsbVehiclesList[i].ttl > 0 && adsbVehiclesList[i].calculatedVehicleValues.valid){
104+
if(adsbVehiclesList[i].calculatedVehicleValues.verticalDistance > 0 && maxVerticalDistance > 0 && adsbVehiclesList[i].calculatedVehicleValues.verticalDistance > maxVerticalDistance){
105+
continue;
106+
}
107+
108+
if (adsbLocal == NULL || adsbLocal->calculatedVehicleValues.dist > adsbVehiclesList[i].calculatedVehicleValues.dist) {
109+
adsbLocal = &adsbVehiclesList[i];
110+
}
111+
}
112+
}
113+
return adsbLocal;
114+
}
115+
89116
adsbVehicle_t *findFreeSpaceInList(void) {
90117
//find expired first
91118
for (uint8_t i = 0; i < MAX_ADSB_VEHICLES; i++) {
@@ -121,23 +148,18 @@ adsbVehicleStatus_t* getAdsbStatus(void){
121148
return &adsbVehiclesStatus;
122149
}
123150

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;
128-
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);
132-
};
133-
134151
bool adsbHeartbeat(void){
135152
adsbVehiclesStatus.heartbeatMessagesTotal++;
136153
return true;
137154
}
138155

139156
void adsbNewVehicle(adsbVehicleValues_t* vehicleValuesLocal) {
140157

158+
if(vehicleValuesLocal->icao == 0)
159+
{
160+
return;
161+
}
162+
141163
// no valid lat lon or altitude
142164
if((vehicleValuesLocal->flags & (ADSB_FLAGS_VALID_ALTITUDE | ADSB_FLAGS_VALID_COORDS)) != (ADSB_FLAGS_VALID_ALTITUDE | ADSB_FLAGS_VALID_COORDS)){
143165
return;
@@ -148,28 +170,27 @@ void adsbNewVehicle(adsbVehicleValues_t* vehicleValuesLocal) {
148170
adsbVehicle_t *vehicle = NULL;
149171

150172
vehicle = findVehicleByIcao(vehicleValuesLocal->icao);
151-
if(vehicle != NULL && vehicleValuesLocal->tslc > ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST){
152-
vehicle->ttl = 0;
173+
if(vehicleValuesLocal->tslc > ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST){
174+
if(vehicle != NULL){
175+
vehicle->ttl = 0;
176+
}
153177
return;
154178
}
155179

156180
// non GPS mode, GPS is not fix, just find free space in list or by icao and save vehicle without calculated values
157181
if (!enviromentOkForCalculatingDistaceBearing()) {
158-
159182
if(vehicle == NULL){
160183
vehicle = findFreeSpaceInList();
161184
}
162185

163186
if (vehicle != NULL) {
164187
memcpy(&(vehicle->vehicleValues), vehicleValuesLocal, sizeof(vehicle->vehicleValues));
165-
vehicle->ttl = ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST;
188+
vehicle->ttl = MAX(0, ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST - vehicleValuesLocal->tslc);
166189
vehicle->calculatedVehicleValues.valid = false;
167190
return;
168191
}
169192
} else {
170193
// GPS mode, GPS is fixed and has enough sats
171-
172-
173194
if(vehicle == NULL){
174195
vehicle = findFreeSpaceInList();
175196
}
@@ -180,21 +201,39 @@ void adsbNewVehicle(adsbVehicleValues_t* vehicleValuesLocal) {
180201

181202
if(vehicle == NULL){
182203
vehicle = findVehicleFarthest();
204+
if(vehicle != NULL)
205+
{
206+
//calculate distance to new vehicle, we need to compare if new vehicle is closer than the farthest plane
207+
fpVector3_t vehicleVector;
208+
geoConvertGeodeticToLocal(&vehicleVector, &posControl.gpsOrigin, &vehicleValuesLocal->gps, GEO_ALT_RELATIVE);
209+
if(calculateDistanceToDestination(&vehicleVector) > vehicle->calculatedVehicleValues.dist){
210+
//saved vehicle in list is closer, no need to update vehicle in list
211+
vehicle = NULL;
212+
}
213+
}
183214
}
184215

185216
if (vehicle != NULL) {
186217
memcpy(&(vehicle->vehicleValues), vehicleValuesLocal, sizeof(vehicle->vehicleValues));
187218
recalculateVehicle(vehicle);
188-
vehicle->ttl = ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST;
219+
vehicle->ttl = MAX(0, ADSB_MAX_SECONDS_KEEP_INACTIVE_PLANE_IN_LIST - vehicleValuesLocal->tslc);
189220
return;
190221
}
191222
}
192223
};
193224

194225
void recalculateVehicle(adsbVehicle_t* vehicle){
195-
gpsDistanceCmBearing(gpsSol.llh.lat, gpsSol.llh.lon, vehicle->vehicleValues.lat, vehicle->vehicleValues.lon, &(vehicle->calculatedVehicleValues.dist), &(vehicle->calculatedVehicleValues.dir));
226+
if(vehicle->ttl == 0){
227+
return;
228+
}
229+
230+
fpVector3_t vehicleVector;
231+
geoConvertGeodeticToLocal(&vehicleVector, &posControl.gpsOrigin, &vehicle->vehicleValues.gps, GEO_ALT_RELATIVE);
196232

197-
if (vehicle != NULL && vehicle->calculatedVehicleValues.dist > ADSB_LIMIT_CM) {
233+
vehicle->calculatedVehicleValues.dist = calculateDistanceToDestination(&vehicleVector);
234+
vehicle->calculatedVehicleValues.dir = calculateBearingToDestination(&vehicleVector);
235+
236+
if (vehicle->calculatedVehicleValues.dist > ADSB_LIMIT_CM) {
198237
vehicle->ttl = 0;
199238
return;
200239
}
@@ -215,6 +254,10 @@ void adsbTtlClean(timeUs_t currentTimeUs) {
215254
if (adsbVehiclesList[i].ttl > 0) {
216255
adsbVehiclesList[i].ttl--;
217256
}
257+
258+
if (adsbVehiclesList[i].ttl > 0) {
259+
recalculateVehicle(&adsbVehiclesList[i]);
260+
}
218261
}
219262

220263
adsbTtlLastCleanServiced = currentTimeUs;

src/main/io/adsb.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <stdint.h>
2121
#include "common/time.h"
22+
#include "io/gps.h"
2223
#include "fc/runtime_config.h"
2324

2425
#define ADSB_CALL_SIGN_MAX_LENGTH 9
@@ -27,16 +28,16 @@
2728
typedef struct {
2829
bool valid;
2930
int32_t dir; // centidegrees direction to plane, pivot is inav FC
30-
uint32_t dist; // CM distance to plane, pivot is inav FC
31-
int32_t verticalDistance; // CM, vertical distance to plane, pivot is inav FC
31+
uint32_t dist; // horisontal distance to plane, cm, pivot is inav FC
32+
int32_t verticalDistance; // vertical distance to plane, cm, pivot is inav FC
3233
} adsbVehicleCalculatedValues_t;
3334

3435
typedef struct {
3536
uint32_t icao; // ICAO address
36-
int32_t lat; // Latitude, expressed as degrees * 1E7
37-
int32_t lon; // Longitude, expressed as degrees * 1E7
38-
int32_t alt; // Barometric/Geometric Altitude (ASL), in cm
39-
uint16_t heading; // Course over ground in centidegrees
37+
uint16_t horVelocity; // [cm/s]
38+
gpsLocation_t gps;
39+
int32_t alt; // [cm] Barometric/Geometric Altitude (MSL)
40+
uint16_t heading; // [centidegrees] Course over ground
4041
uint16_t flags; // Flags to indicate various statuses including valid data fields
4142
uint8_t altitudeType; // Type from ADSB_ALTITUDE_TYPE enum
4243
char callsign[ADSB_CALL_SIGN_MAX_LENGTH]; // The callsign, 8 chars + NULL
@@ -50,16 +51,14 @@ typedef struct {
5051
uint8_t ttl;
5152
} adsbVehicle_t;
5253

53-
54-
5554
typedef struct {
5655
uint32_t vehiclesMessagesTotal;
5756
uint32_t heartbeatMessagesTotal;
5857
} adsbVehicleStatus_t;
5958

6059
void adsbNewVehicle(adsbVehicleValues_t* vehicleValuesLocal);
6160
bool adsbHeartbeat(void);
62-
adsbVehicle_t * findVehicleClosest(void);
61+
adsbVehicle_t *findVehicleClosestLimit(int32_t maxVerticalDistance);
6362
adsbVehicle_t * findVehicle(uint8_t index);
6463
uint8_t getActiveVehiclesCount(void);
6564
void adsbTtlClean(timeUs_t currentTimeUs);

0 commit comments

Comments
 (0)