--[[ adsb_send.lua: send a simulated ADSB vehicle flying a 500m radius circle This script demonstrates how to send ADSB_VEHICLE MAVLink messages using -- mavlink:send_chan() with manual struct packing (no MAVLink module required) --]] -- initialise mavlink (no rx needed, only tx) mavlink:init(1, 0) local ADSB_VEHICLE_MSGID = 246 -- ADSB flags bitmask values local ADSB_FLAGS_VALID_COORDS = 1 local ADSB_FLAGS_VALID_ALTITUDE = 2 local ADSB_FLAGS_VALID_HEADING = 4 local ADSB_FLAGS_VALID_VELOCITY = 8 local ADSB_FLAGS_VALID_CALLSIGN = 16 local ADSB_FLAGS_SIMULATED = 64 local ADSB_FLAGS_VERTICAL_VELOCITY_VALID = 128 -- -- Send an ADSB_VEHICLE message on all MAVLink channels -- -- lat_deg : latitude in degrees -- lng_deg : longitude in degrees -- alt_amsl_m : altitude AMSL in metres -- heading_deg : course over ground in degrees (0=north, clockwise) -- speed_mps : horizontal speed in m/s -- vspeed_mps : vertical speed in m/s (positive = up) -- icao_address : 24-bit ICAO address -- callsign : up to 8 character string -- squawk : squawk code in decimal (e.g. 1200 for VFR) -- emitter_type : ADSB_EMITTER_TYPE enum value -- flags : ADSB_FLAGS bitmask -- local function send_ADSB_VEHICLE(lat_deg, lng_deg, alt_amsl_m, heading_deg, speed_mps, vspeed_mps, icao_address, callsign, squawk, emitter_type, flags) -- pad or truncate callsign to exactly 9 bytes (8 chars + null) local cs = callsign .. string.rep("\0", 9) cs = string.sub(cs, 1, 9) -- MAVLink wire order: fields sorted by type size descending, then XML order -- uint32: ICAO_address, lat, lon, altitude (4 x I4/i4) -- uint16: heading, hor_velocity, ver_velocity, (5 x I2/i2) -- flags, squawk -- uint8: altitude_type (1 x B) -- char[9]: callsign (c9) -- uint8: emitter_type, tslc (2 x B) local payload = string.pack(" 2 * math.pi then angle_rad = angle_rad - 2 * math.pi end -- compute position on circle local pos = Location() pos:lat(center_lat) pos:lng(center_lng) pos:alt(math.floor(alt_m * 100)) pos:offset_bearing(math.deg(angle_rad), RADIUS_M) -- heading is tangent to circle (90 degrees ahead of radial) local heading_deg = math.deg(angle_rad) + 90 if heading_deg >= 360 then heading_deg = heading_deg - 360 end send_ADSB_VEHICLE( pos:lat() / 1e7, -- back to degrees pos:lng() / 1e7, -- back to degrees alt_m, heading_deg, SPEED_MS, 0, -- no vertical speed ICAO_ADDR, CALLSIGN, 1200, -- VFR squawk 1, -- ADSB_EMITTER_TYPE_LIGHT FLAGS ) return update, math.floor(1000 / UPDATE_HZ) end return update()