Add Heading to ADSB and Map Updating

This commit is contained in:
Joel Wetzell 2020-07-24 16:09:21 -05:00
parent f21e26eaa3
commit f08949acd7
8 changed files with 87 additions and 18 deletions

View File

@ -240,7 +240,7 @@ AISRecentEntryDetailView::AISRecentEntryDetailView(NavigationView& nav) {
void AISRecentEntryDetailView::update_position() {
if (send_updates)
geomap_view->update_position(ais::format::latlon_float(entry_.last_position.latitude.normalized()), ais::format::latlon_float(entry_.last_position.longitude.normalized()));
geomap_view->update_position(ais::format::latlon_float(entry_.last_position.latitude.normalized()), ais::format::latlon_float(entry_.last_position.longitude.normalized()), (float)entry_.last_position.true_heading);
}
void AISRecentEntryDetailView::focus() {

View File

@ -97,7 +97,7 @@ void ADSBRxDetailsView::update(const AircraftRecentEntry& entry) {
text_frame_pos_odd.set(to_string_hex_array(entry_copy.frame_pos_odd.get_raw_data(), 14));
if (send_updates)
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude);
geomap_view->update_position(entry_copy.pos.latitude, entry_copy.pos.longitude, entry_copy.velo.heading);
}
ADSBRxDetailsView::~ADSBRxDetailsView() {
@ -172,7 +172,7 @@ ADSBRxDetailsView::ADSBRxDetailsView(
GeoPos::alt_unit::FEET,
entry_copy.pos.latitude,
entry_copy.pos.longitude,
0,
entry_copy.velo.heading,
[this]() {
send_updates = false;
});
@ -214,6 +214,7 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
if (frame.get_DF() == DF_ADSB) {
uint8_t msg_type = frame.get_msg_type();
uint8_t msg_sub = frame.get_msg_sub();
uint8_t * raw_data = frame.get_raw_data();
if ((msg_type >= 1) && (msg_type <= 4)) {
@ -236,6 +237,8 @@ void ADSBRxView::on_frame(const ADSBFrameMessage * message) {
if (send_updates)
details_view->update(entry);
}
} else if(msg_type == 19 && (msg_sub >= 1 && msg_sub <= 4)){
entry.set_frame_velo(frame);
}
}
recent_entries_view.set_dirty();

View File

@ -49,7 +49,7 @@ struct AircraftRecentEntry {
uint16_t hits { 0 };
uint32_t age { 0 };
adsb_pos pos { false, 0, 0, 0 };
adsb_vel velo { false, 0, 0 };
ADSBFrame frame_pos_even { };
ADSBFrame frame_pos_odd { };
@ -86,6 +86,10 @@ struct AircraftRecentEntry {
pos = decode_frame_pos(frame_pos_even, frame_pos_odd);
}
}
void set_frame_velo(ADSBFrame& frame){
velo = decode_frame_velo(frame);
}
void set_info_string(std::string& new_info_string) {
info_string = new_info_string;

View File

@ -168,10 +168,15 @@ void GeoMap::paint(Painter& painter) {
// Cross
display.fill_rectangle({ r.center() - Point(16, 1), { 32, 2 } }, Color::red());
display.fill_rectangle({ r.center() - Point(1, 16), { 2, 32 } }, Color::red());
} else {
draw_bearing(r.center(), angle_, 10, Color::red());
//center tag above bearing
painter.draw_string(r.center() - Point(((int)tag_.length() * 8 / 2), 2 * 16), style(), tag_);
} else if (angle_ < 360){
//if we have a valid angle just draw bearing
draw_bearing({ 120, 32 + 144 }, angle_, 10, Color::red());
painter.draw_string({ 120 - ((int)tag_.length() * 8 / 2), 32 + 144 - 32 }, style(), tag_);
}
else {
//draw a small cross
display.fill_rectangle({ r.center() - Point(8, 1), { 16, 2 } }, Color::red());
display.fill_rectangle({ r.center() - Point(1, 8), { 2, 16 } }, Color::red());
}
}
@ -231,7 +236,7 @@ void GeoMap::set_mode(GeoMapMode mode) {
mode_ = mode;
}
void GeoMap::draw_bearing(const Point origin, const uint32_t angle, uint32_t size, const Color color) {
void GeoMap::draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color) {
Point arrow_a, arrow_b, arrow_c;
for (size_t thickness = 0; thickness < 3; thickness++) {
@ -254,9 +259,10 @@ void GeoMapView::focus() {
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT, nullptr);
}
void GeoMapView::update_position(float lat, float lon) {
void GeoMapView::update_position(float lat, float lon, uint16_t angle) {
lat_ = lat;
lon_ = lon;
angle_ = angle;
geopos.set_lat(lat_);
geopos.set_lon(lon_);
geomap.move(lon_, lat_);
@ -307,7 +313,7 @@ GeoMapView::GeoMapView(
GeoPos::alt_unit altitude_unit,
float lat,
float lon,
float angle,
uint16_t angle,
const std::function<void(void)> on_close
) : nav_ (nav),
altitude_ (altitude),

View File

@ -130,7 +130,7 @@ public:
}
private:
void draw_bearing(const Point origin, const uint32_t angle, uint32_t size, const Color color);
void draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color);
GeoMapMode mode_ { };
File map_file { };
@ -141,7 +141,7 @@ private:
int32_t prev_x_pos { 0xFFFF }, prev_y_pos { 0xFFFF };
float lat_ { };
float lon_ { };
float angle_ { };
uint16_t angle_ { };
std::string tag_ { };
};
@ -154,7 +154,7 @@ public:
GeoPos::alt_unit altitude_unit,
float lat,
float lon,
float angle,
uint16_t angle,
const std::function<void(void)> on_close = nullptr
);
GeoMapView(NavigationView& nav,
@ -173,7 +173,7 @@ public:
void focus() override;
void update_position(float lat, float lon);
void update_position(float lat, float lon, uint16_t angle);
std::string title() const override { return "Map view"; };
@ -190,7 +190,7 @@ private:
GeoPos::alt_unit altitude_unit_ { };
float lat_ { };
float lon_ { };
float angle_ { };
uint16_t angle_ { };
std::function<void(void)> on_close_ { nullptr };
bool map_opened { };

View File

@ -300,8 +300,8 @@ void encode_frame_velo(ADSBFrame& frame, const uint32_t ICAO_address, const uint
v_rate_coded = (v_rate / 64) + 1;
velo_ew_abs = abs(velo_ew);
velo_ns_abs = abs(velo_ns);
velo_ew_abs = abs(velo_ew) + 1;
velo_ns_abs = abs(velo_ns) + 1;
v_rate_coded_abs = abs(v_rate_coded);
make_frame_adsb(frame, ICAO_address);
@ -317,4 +317,47 @@ void encode_frame_velo(ADSBFrame& frame, const uint32_t ICAO_address, const uint
frame.make_CRC();
}
// Decoding method from dump1090
adsb_vel decode_frame_velo(ADSBFrame& frame){
adsb_vel velo {false, 0, 0};
uint8_t * frame_data = frame.get_raw_data();
uint8_t velo_type = frame.get_msg_sub();
if(velo_type >= 1 && velo_type <= 4){ //vertical rate is always present
velo.v_rate = (((frame_data[8] & 0x07 ) << 6) | ((frame_data[9]) >> 2) - 1) * 64;
if((frame_data[8] & 0x8) >> 3) velo.v_rate *= -1; //check v_rate sign
}
if(velo_type == 1 || velo_type == 2){ //Ground Speed
int32_t velo_ew = (((frame_data[5] & 0x03) << 8) | frame_data[6]) - 1;
int32_t velo_ns = ((frame_data[7] & 0x7f) << 3) | ((frame_data[8]) >> 5) - 1;
if (velo_type == 2){ // supersonic indicator so multiply by 4
velo_ew = velo_ew << 2;
velo_ns = velo_ns << 2;
}
if((frame_data[5]&4) >> 2) velo_ew *= -1; //check ew direction sign
if((frame_data[7]&0x80) >> 7) velo_ns *= -1; //check ns direction sign
velo.speed = sqrt(velo_ns*velo_ns + velo_ew*velo_ew);
if(velo.speed){
//calculate heading in degrees from ew/ns velocities
velo.heading = (uint16_t)(atan2(velo_ew,velo_ns) * 180.0 / pi);
// We don't want negative values but a 0-360 scale.
if (velo.heading < 0) velo.heading += 360.0;
}
}else if(velo_type == 3 || velo_type == 4){ //Airspeed
velo.valid = frame_data[5] & (1<<2);
velo.heading = ((((frame_data[5] & 0x03)<<8) | frame_data[6]) * 45) << 7;
}
return velo;
}
} /* namespace adsb */

View File

@ -56,6 +56,13 @@ struct adsb_pos {
int32_t altitude;
};
struct adsb_vel {
bool valid;
int32_t speed; //knot
uint16_t heading; //degree
int32_t v_rate; //ft/min
};
const float CPR_MAX_VALUE = 131072.0;
const float adsb_lat_lut[58] = {
@ -89,6 +96,8 @@ adsb_pos decode_frame_pos(ADSBFrame& frame_even, ADSBFrame& frame_odd);
void encode_frame_velo(ADSBFrame& frame, const uint32_t ICAO_address, const uint32_t speed,
const float angle, const int32_t v_rate);
adsb_vel decode_frame_velo(ADSBFrame& frame);
//void encode_frame_emergency(ADSBFrame& frame, const uint32_t ICAO_address, const uint8_t code);
void encode_frame_squawk(ADSBFrame& frame, const uint32_t squawk);

View File

@ -41,6 +41,10 @@ public:
return (raw_data[4] >> 3);
}
uint8_t get_msg_sub() {
return (raw_data[4] & 7);
}
uint32_t get_ICAO_address() {
return (raw_data[1] << 16) + (raw_data[2] << 8) + raw_data[3];
}