Skip to content

Commit

Permalink
Add emitter category support & change ADS-B sprites to use tar1090 sp…
Browse files Browse the repository at this point in the history
…rites
  • Loading branch information
MUSTARDTIGERFPV committed Oct 14, 2024
1 parent 081a697 commit 6a2bc84
Show file tree
Hide file tree
Showing 20 changed files with 479 additions and 24 deletions.
23 changes: 12 additions & 11 deletions ExtLibs/ArduPilot/Mavlink/MAVLinkInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5126,25 +5126,26 @@ public async Task<MAVLinkMessage> readPacketAsync()
// adsb packets are forwarded and can be from any sysid/compid
if (msgid == (byte)MAVLINK_MSG_ID.ADSB_VEHICLE)
{
var adsb = message.ToStructure<mavlink_adsb_vehicle_t>();
var adsbMessage = message.ToStructure<mavlink_adsb_vehicle_t>();

var id = adsb.ICAO_address.ToString("X5");
var id = adsbMessage.ICAO_address.ToString("X5");

if (_UpdateADSBPlanePosition != null)
_UpdateADSBPlanePosition(this, new adsb.PointLatLngAltHdg(
adsb.lat / 1e7,
adsb.lon / 1e7,
adsb.altitude / 1000,
adsb.heading * 0.01f,
adsb.hor_velocity,
adsbMessage.lat / 1e7,
adsbMessage.lon / 1e7,
adsbMessage.altitude / 1000,
adsbMessage.heading * 0.01f,
adsbMessage.hor_velocity,
id,
DateTime.Now
)
{
CallSign = Encoding.UTF8.GetString(adsb.callsign),
Squawk = adsb.squawk,
Raw = adsb,
VerticalSpeed = adsb.ver_velocity,
CallSign = Encoding.UTF8.GetString(adsbMessage.callsign),
Squawk = adsbMessage.squawk,
Raw = adsbMessage,
VerticalSpeed = adsbMessage.ver_velocity,
Category = adsb.GetEmitterCategoryShort((ADSB_EMITTER_TYPE)adsbMessage.emitter_type),
}
);
}
Expand Down
142 changes: 132 additions & 10 deletions ExtLibs/Maps/GMapMarkerADSBPlane.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,46 @@
using System;
using System.Drawing;
using GMap.NET;
using GMap.NET.Drawing.Properties;
using GMap.NET.WindowsForms;

namespace MissionPlanner.Maps
{
[Serializable]
public class GMapMarkerADSBPlane : GMapMarker
{
private static readonly Bitmap icong = new Bitmap(global::MissionPlanner.Maps.Resources.FW_icons_2013_logos_01,
new Size(40, 40));
// The images we're using are 72x72, so we'll use that as the size
private static readonly Size size = new Size(72, 72);

private static readonly Bitmap iconr = new Bitmap(global::MissionPlanner.Maps.Resources.FW_icons_2013_logos_011,
new Size(40, 40));
// Images retrieved from tar1090 sprites: https://github.com/wiedehopf/tar1090/blob/master/html/images/sprites.png
private static readonly Bitmap adsb_unknown = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_unknown, size);
private static readonly Bitmap adsb_light = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_light, size);
private static readonly Bitmap adsb_small = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_small, size);
private static readonly Bitmap adsb_large = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_large, size);
private static readonly Bitmap adsb_heavy = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_heavy, size);
private static readonly Bitmap adsb_highly_manuv = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_highly_manuv, size);
private static readonly Bitmap adsb_rotocraft = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_rotocraft, size);
//private static readonly Bitmap adsb_glider = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_glider, size);
private static readonly Bitmap adsb_lighter_air = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_balloon, size);
private static readonly Bitmap adsb_parachute = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_parachute, size);
//private static readonly Bitmap adsb_ultralight = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_ultralight, size);
private static readonly Bitmap adsb_uav = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_uav, size);
private static readonly Bitmap adsb_emergency_surface = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_emergency_surface, size);
private static readonly Bitmap adsb_service_surface = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_service_surface, size);
private static readonly Bitmap adsb_point_obstacle = new Bitmap(global::MissionPlanner.Maps.Resources.adsb_balloon, size); // point obstacles are used for balloons

private static readonly Bitmap icono = new Bitmap(global::MissionPlanner.Maps.Resources.FW_icons_2013_logos_012,
new Size(40, 40));

public float heading = 0;
public AlertLevelOptions AlertLevel = AlertLevelOptions.Green;
public float DrawScale = 1;

// Cache the last drawn data to avoid re-coloring every frame
private Bitmap lastDrawn = null;
// Store the last alert level to decide whether to redraw
private AlertLevelOptions lastAlertLevel = AlertLevelOptions.Green;
private MAVLink.ADSB_EMITTER_TYPE lastEmitterCategory = MAVLink.ADSB_EMITTER_TYPE.NO_INFO;

public MAVLink.ADSB_EMITTER_TYPE EmitterCategory { get; set; }

public enum AlertLevelOptions
{
Expand All @@ -32,10 +54,33 @@ public GMapMarkerADSBPlane(PointLatLng p, float heading, AlertLevelOptions alert
{
this.AlertLevel = alert;
this.heading = heading;
Size = icong.Size;
Size = size;
Offset = new Point(Size.Width / -2, Size.Height / -2);
}

private static void ColorSprite(Bitmap bitmap, Color fillColor)
{
int width = bitmap.Width;
int height = bitmap.Height;

bool IsWhite(Color pixel) => pixel.R == 255 && pixel.G == 255 && pixel.B == 255 && pixel.A != 0;

// Iterate through every pixel in the image
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
Color pixel = bitmap.GetPixel(x, y);

// If the pixel is white, color it with the fill color
if (IsWhite(pixel))
{
bitmap.SetPixel(x, y, fillColor);
}
}
}
}

public override void OnRender(IGraphics g)
{
var temp = g.Transform;
Expand All @@ -51,19 +96,96 @@ public override void OnRender(IGraphics g)
{
}

bool needsRedraw = lastDrawn == null || lastAlertLevel != AlertLevel || lastEmitterCategory != EmitterCategory;

if (!needsRedraw)
{
g.ScaleTransform(DrawScale, DrawScale);
g.DrawImageUnscaled(lastDrawn, lastDrawn.Width / -2, lastDrawn.Height / -2);
return;
}

// Set the icon based on emitter category
Bitmap bitmap = adsb_unknown;
DrawScale = 0.5f;

switch (this.EmitterCategory)
{
case MAVLink.ADSB_EMITTER_TYPE.NO_INFO:
bitmap = adsb_unknown;
break;
case MAVLink.ADSB_EMITTER_TYPE.LIGHT:
bitmap = adsb_light;
break;
case MAVLink.ADSB_EMITTER_TYPE.SMALL:
bitmap = adsb_small;
break;
case MAVLink.ADSB_EMITTER_TYPE.LARGE:
bitmap = adsb_large;
DrawScale *= 1.25f;
break;
case MAVLink.ADSB_EMITTER_TYPE.HEAVY:
bitmap = adsb_heavy;
DrawScale *= 1.5f;
break;
case MAVLink.ADSB_EMITTER_TYPE.HIGH_VORTEX_LARGE:
bitmap = adsb_heavy;
DrawScale *= 1.5f;
break;
case MAVLink.ADSB_EMITTER_TYPE.HIGHLY_MANUV:
bitmap = adsb_highly_manuv;
break;
case MAVLink.ADSB_EMITTER_TYPE.ROTOCRAFT:
bitmap = adsb_rotocraft;
break;
case MAVLink.ADSB_EMITTER_TYPE.GLIDER:
bitmap = adsb_lighter_air;
break;
case MAVLink.ADSB_EMITTER_TYPE.PARACHUTE:
bitmap = adsb_parachute;
break;
case MAVLink.ADSB_EMITTER_TYPE.ULTRA_LIGHT:
bitmap = adsb_lighter_air;
break;
case MAVLink.ADSB_EMITTER_TYPE.UAV:
bitmap = adsb_uav;
break;
case MAVLink.ADSB_EMITTER_TYPE.SPACE:
//???
break;
case MAVLink.ADSB_EMITTER_TYPE.EMERGENCY_SURFACE:
bitmap = adsb_emergency_surface;
break;
case MAVLink.ADSB_EMITTER_TYPE.SERVICE_SURFACE:
bitmap = adsb_service_surface;
break;
case MAVLink.ADSB_EMITTER_TYPE.POINT_OBSTACLE:
bitmap = adsb_point_obstacle;
break;
}

// Set the color based on alert level
var fillColor = Color.Green;
switch (AlertLevel)
{
case AlertLevelOptions.Green:
g.DrawImageUnscaled(icong, icong.Width / -2, icong.Height / -2);
fillColor = Color.Green;
break;
case AlertLevelOptions.Orange:
g.DrawImageUnscaled(icono, icono.Width / -2, icono.Height / -2);
fillColor = Color.Orange;
break;
case AlertLevelOptions.Red:
g.DrawImageUnscaled(iconr, iconr.Width / -2, iconr.Height / -2);
fillColor = Color.Red;
break;
}

ColorSprite(bitmap, fillColor);

g.ScaleTransform(DrawScale, DrawScale);
g.DrawImageUnscaled(bitmap, bitmap.Width / -2, bitmap.Height / -2);

lastDrawn = bitmap;

g.Transform = temp;
}
}
Expand Down
132 changes: 131 additions & 1 deletion ExtLibs/Maps/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6a2bc84

Please sign in to comment.