add time based vector and DRM support

This commit is contained in:
2026-08-06 13:05:32 +02:00
parent 45a4431b53
commit 19de2840c5
6 changed files with 239 additions and 60 deletions
+75
View File
@@ -55,6 +55,14 @@ config TIME_BASED_VECTOR_LENGHT
For example if set to 2 minutes the line will end where the plane be in 2 minutes, For example if set to 2 minutes the line will end where the plane be in 2 minutes,
if direction and speed does not change. if direction and speed does not change.
config VECTOR_FOLLOW_TRACK_RATE
bool "Time based vector follows change of track"
default 1
help
Make Time based vector follows change of track of aircraft.
This option will turn the vector from line into curve.
This is of course be more computationaly expensive.
comment "Receiver configuration" comment "Receiver configuration"
config FALLBACK_LAT config FALLBACK_LAT
@@ -76,3 +84,70 @@ config METRIC
default y default y
help help
Show altitudes in meters instead of feet. Show altitudes in meters instead of feet.
comment "Platform dependent options"
choice
prompt "Build target"
default BUILD_LINUX
help
Select platform you want p-rad to be compiled for.
config BUILD_LINUX
bool "Linux"
config BUILD_PICO
bool "PI pico W"
config BUILD_OTHER_UNIX
bool "Other Unix/Posix compatable system (NOT IMPLEMENTED)"
endchoice
if BUILD_LINUX
choice
prompt "SDL render target"
default SDL_TARGET_WINDOW
help
Select where you want SDL3 to render to.
config SDL_TARGET_WINDOW
bool "Full-Screen Window"
help
Render to Full-Screen Window using window system like X11 or wayland.
config SDL_TARGET_KMSDRM
bool "Direct to DRM"
help
Render directly to GPU using kmsdrm
endchoice
endif
if BUILD_LINUX || BUILD_OTHER_UNIX
config SDL_DRIVERS
string "Enabled SDL3 render drivers"
default "gpu,vulkan,opengl"
help
Comma-speparated list of drivers,
SDL will try each name, in the order listed, until one succeeds or all of them fail.
leave empty and SDL will attempt to choose the best option for you,
based on what is available on the your system.
(I dont recommend leaving this option empty.)
Available drivers can be listed by running this code:
#include <SDL3/SDL.h>
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Log("Available renderer drivers:");
for (int i = 0; i < SDL_GetNumRenderDrivers(); i++) {
SDL_Log("%d. %s", i + 1, SDL_GetRenderDriver(i));
}
}
endif
+4
View File
@@ -3,3 +3,7 @@ template<typename T>
static inline T feet_to_meters(T ft) { static inline T feet_to_meters(T ft) {
return static_cast<T>(ft * 0.3048); return static_cast<T>(ft * 0.3048);
} }
template<typename T>
static inline T knot_to_km(T kn) {
return static_cast<T>(kn * 0.5399568);
}
+1
View File
@@ -19,4 +19,5 @@ struct rect_t {
void filled_rect(const rect_t* rect, const color_t color); void filled_rect(const rect_t* rect, const color_t color);
void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color); void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color);
void rhombus(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color); void rhombus(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color);
void line(const uint16_t x1,const uint16_t y1,const uint16_t x2,const uint16_t y2, const color_t color);
} }
+89 -17
View File
@@ -1,6 +1,8 @@
#include "../core/const.hpp" #include "../core/const.hpp"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <SDL3/SDL_events.h> #include <SDL3/SDL_events.h>
#include <SDL3/SDL_hints.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_iostream.h> #include <SDL3/SDL_iostream.h>
#include <SDL3/SDL_mouse.h> #include <SDL3/SDL_mouse.h>
#include <SDL3/SDL_rect.h> #include <SDL3/SDL_rect.h>
@@ -14,6 +16,8 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include "../core/color.h"
#include "core/config.hpp"
#include "draw.hpp" #include "draw.hpp"
#include "hal/hal.hpp" #include "hal/hal.hpp"
#include <curl/curl.h> #include <curl/curl.h>
@@ -22,7 +26,7 @@
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp> #include <nlohmann/json_fwd.hpp>
#include <tuple> #include <tuple>
#include "../core/color.h"
struct sdl_session { struct sdl_session {
SDL_Window *window; SDL_Window *window;
SDL_Renderer *renderer; SDL_Renderer *renderer;
@@ -34,16 +38,53 @@ CURL *curl;
namespace hal { namespace hal {
int init() { int init() {
SDL_Init(SDL_INIT_VIDEO); #ifdef CONFIG_SDL_TARGET_KMSDRM
if (!SDL_SetHint(SDL_HINT_KMSDRM_DEVICE_INDEX, "-1")) {
SDL_Log("hint failed: %s", SDL_GetError());
}
if (!SDL_SetHint(SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER, "1")) {
SDL_Log("hint failed: %s", SDL_GetError());
}
if (!SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "kmsdrm")) {
SDL_Log("hint failed: %s", SDL_GetError());
}
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, CONFIG_SDL_DRIVERS)) {
SDL_Log("hint failed: %s", SDL_GetError());
}
#endif
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("init failed: %s", SDL_GetError());
return 1;
}
// DEBUG
std::clog << "active driver: " << SDL_GetCurrentVideoDriver() << "\n";
mode = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay()); mode = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay());
if (!mode) {
SDL_Log("failed to get display mode: %s", SDL_GetError());
return 1;
}
main_sdl_session.window = main_sdl_session.window =
SDL_CreateWindow(program_name, mode->w, mode->h, SDL_WINDOW_FULLSCREEN); SDL_CreateWindow(program_name, mode->w, mode->h, SDL_WINDOW_FULLSCREEN);
main_sdl_session.renderer = if (!main_sdl_session.window) {
SDL_CreateRenderer(main_sdl_session.window, "gpu,vulcan"); SDL_Log("window failed: %s", SDL_GetError());
return 1;
}
main_sdl_session.renderer = SDL_CreateRenderer(main_sdl_session.window,
#ifndef CONFIG_SDL_TARGET_KMSDRM
CONFIG_SDL_DRIVERS
#else
NULL
#endif
);
if (!main_sdl_session.renderer) {
SDL_Log("renderer failed: %s", SDL_GetError());
return 1;
}
curl = curl_easy_init(); curl = curl_easy_init();
return 0; return 0;
} }
std::tuple<uint16_t, uint16_t> get_screen_size() { return {mode->w, mode->h}; } std::tuple<uint16_t, uint16_t> get_screen_size() { return {mode->w, mode->h}; }
@@ -56,6 +97,26 @@ void start_frame() {
const Uint64 frame_delay_ns = 1000000000ULL / 1; const Uint64 frame_delay_ns = 1000000000ULL / 1;
void end_frame() { void end_frame() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
// Handles Window close (the 'X' button), Alt+F4, or SIGINT (Ctrl+C)
// Handles keyboard key presses
case SDL_EVENT_KEY_DOWN:
// Check if the pressed key is 'Q'
if (event.key.key != SDLK_Q) {
break;
}
case SDL_EVENT_QUIT:
SDL_Quit();
std::exit(0);
break;
default:
break;
}
}
SDL_RenderPresent(main_sdl_session.renderer); SDL_RenderPresent(main_sdl_session.renderer);
@@ -83,11 +144,13 @@ void filled_rect(const rect_t *rect, const color_t color) {
SDL_RenderFillRect(main_sdl_session.renderer, &frect); SDL_RenderFillRect(main_sdl_session.renderer, &frect);
} }
void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color) { void circle(const uint16_t x_center, const uint16_t y_center,
const uint16_t radius, const color_t color) {
SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b, SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b,
0xff); 0xff);
// based on https://www.geeksforgeeks.org/dsa/mid-point-circle-drawing-algorithm/ // based on
// https://www.geeksforgeeks.org/dsa/mid-point-circle-drawing-algorithm/
int x = radius, y = 0; int x = radius, y = 0;
// Printing the initial point on the axes // Printing the initial point on the axes
@@ -96,8 +159,7 @@ void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radi
// When radius is zero only a single // When radius is zero only a single
// point will be printed // point will be printed
if (radius > 0) if (radius > 0) {
{
SDL_RenderPoint(main_sdl_session.renderer, x + x_center, -y + y_center); SDL_RenderPoint(main_sdl_session.renderer, x + x_center, -y + y_center);
SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center); SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center);
SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center); SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center);
@@ -106,16 +168,14 @@ void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radi
// Initialising the value of P // Initialising the value of P
int P = 1 - radius; int P = 1 - radius;
while (x > y) while (x > y) {
{
y++; y++;
// Mid-point is inside or on the perimeter // Mid-point is inside or on the perimeter
if (P <= 0) if (P <= 0)
P = P + 2 * y + 1; P = P + 2 * y + 1;
// Mid-point is outside the perimeter // Mid-point is outside the perimeter
else else {
{
x--; x--;
P = P + 2 * y - 2 * x + 1; P = P + 2 * y - 2 * x + 1;
} }
@@ -133,8 +193,7 @@ void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radi
// If the generated point is on the line x = y then // If the generated point is on the line x = y then
// the perimeter points have already been printed // the perimeter points have already been printed
if (x != y) if (x != y) {
{
SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center); SDL_RenderPoint(main_sdl_session.renderer, y + x_center, x + y_center);
SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center); SDL_RenderPoint(main_sdl_session.renderer, -y + x_center, x + y_center);
SDL_RenderPoint(main_sdl_session.renderer, y + x_center, -x + y_center); SDL_RenderPoint(main_sdl_session.renderer, y + x_center, -x + y_center);
@@ -143,12 +202,25 @@ void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radi
} }
} }
void rhombus(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color) { void rhombus(const uint16_t x_center, const uint16_t y_center,
const uint16_t radius, const color_t color) {
SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b, SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b,
0xff); 0xff);
const SDL_FPoint points[] = {{static_cast<float>(x_center+radius),static_cast<float>(y_center)},{static_cast<float>(x_center),static_cast<float>(y_center+radius)},{static_cast<float>(x_center-radius),static_cast<float>(y_center)},{static_cast<float>(x_center),static_cast<float>(y_center-radius)},{static_cast<float>(x_center+radius),static_cast<float>(y_center)}}; const SDL_FPoint points[] = {
{static_cast<float>(x_center + radius), static_cast<float>(y_center)},
{static_cast<float>(x_center), static_cast<float>(y_center + radius)},
{static_cast<float>(x_center - radius), static_cast<float>(y_center)},
{static_cast<float>(x_center), static_cast<float>(y_center - radius)},
{static_cast<float>(x_center + radius), static_cast<float>(y_center)}};
SDL_RenderLines(main_sdl_session.renderer, points, ARRAY_LENGHT(points)); SDL_RenderLines(main_sdl_session.renderer, points, ARRAY_LENGHT(points));
} }
void line(const uint16_t x1, const uint16_t y1, const uint16_t x2,
const uint16_t y2, const color_t color) {
SDL_SetRenderDrawColor(main_sdl_session.renderer, color.r, color.g, color.b,
0xff);
SDL_RenderLine(main_sdl_session.renderer, x1, y1, x2, y2);
}
} // namespace draw } // namespace draw
namespace net { namespace net {
+2
View File
@@ -52,6 +52,8 @@ void filled_rect(const rect_t *rect, const color_t color) {}
void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color) { void circle(const uint16_t x_center, const uint16_t y_center,const uint16_t radius, const color_t color) {
} }
void rhombus(const uint16_t x_center, const uint16_t y_center, const uint16_t radius, const color_t color) {}
void line(const uint16_t x1, const uint16_t y1, const uint16_t x2, const uint16_t y2, const color_t color) {}
} // namespace draw } // namespace draw
namespace net { namespace net {
+26 -1
View File
@@ -8,8 +8,10 @@
#include "nlohmann/json_fwd.hpp" #include "nlohmann/json_fwd.hpp"
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cmath>
#include <format> #include <format>
#include <iostream> #include <iostream>
#include <numbers>
#include "core/global.hpp" #include "core/global.hpp"
#include "core/geo.hpp" #include "core/geo.hpp"
#include "core/gfx.hpp" #include "core/gfx.hpp"
@@ -106,6 +108,18 @@ int main() {
std::clog << YELLOW"[WARNING]" RESET " aircraft with no alt data detected!\n"; std::clog << YELLOW"[WARNING]" RESET " aircraft with no alt data detected!\n";
altitude = 0; altitude = 0;
} }
// aircraft gorund speed in km/h
float speed;
// aircraft track in degreees
float track;
try {
speed = knot_to_km(craft["gs"].get<float>());
track = craft["track"].get<float>();
} catch(...) {
std::clog << YELLOW"[WARNING]" RESET " aircraft with no ground speed or track data detected!\n";
speed = 0;
}
draw::color_t color= get_altitude_color(altitude); draw::color_t color= get_altitude_color(altitude);
try { try {
const auto [x_offset,y_offset] = get_offset_from_station(craft["lat"].get<double>(), craft["lon"].get<double>()); const auto [x_offset,y_offset] = get_offset_from_station(craft["lat"].get<double>(), craft["lon"].get<double>());
@@ -119,7 +133,18 @@ int main() {
#endif #endif
const uint16_t x_center = middle_x+((x_offset/1000)*pixels_per_km); const uint16_t x_center = middle_x+((x_offset/1000)*pixels_per_km);
const uint16_t y_center = middle_y+((y_offset/1000)*pixels_per_km); const uint16_t y_center = middle_y+((y_offset/1000)*pixels_per_km);
draw::pixel(x_center, y_center, color); // draw::pixel(x_center, y_center, color);
//speed in pixels per hour
const float speed_pph = speed* pixels_per_km;
// lenght of Time-Based Vector
const float vector_lenght = (speed_pph/60) * CONFIG_TIME_BASED_VECTOR_LENGHT;
// track in radians
const float track_rad = std::fmod((track-90),365.0f) * (static_cast<float>(std::numbers::pi)/180.0f);
draw::line(x_center, y_center,x_center + (vector_lenght*std::cos(track_rad)), y_center + (vector_lenght*std::sin(track_rad)), color);
draw::rhombus(x_center, y_center, 8/*TODO: remove magic*/,color); draw::rhombus(x_center, y_center, 8/*TODO: remove magic*/,color);
} catch(...) { } catch(...) {
std::clog << YELLOW"[WARNING]" RESET " aircraft with no lat/lon data detected!\n"; std::clog << YELLOW"[WARNING]" RESET " aircraft with no lat/lon data detected!\n";