mirror of
https://github.com/valmojr/armatak.git
synced 2026-06-13 13:53:28 +00:00
Refacted UDP Socket config and created UAS addon
This commit is contained in:
@@ -12,7 +12,7 @@ class armatak_udp_socket_start_dialog {
|
||||
x = "0.386562 * safezoneW + safezoneX";
|
||||
y = "0.357 * safezoneH + safezoneY";
|
||||
w = "0.216563 * safezoneW";
|
||||
h = "0.319 * safezoneH";
|
||||
h = "0.418 * safezoneH";
|
||||
colorBackground[]={0,0,0,0.45};
|
||||
};
|
||||
};
|
||||
@@ -44,6 +44,16 @@ class armatak_udp_socket_start_dialog {
|
||||
h = "0.044 * safezoneH";
|
||||
colorBackground[]={0,0,0,0.5};
|
||||
};
|
||||
class armatak_gui_module_udp_socket_dialog_video_feed_url_edit: RscEdit {
|
||||
idc = 16969;
|
||||
text = "";
|
||||
x = "0.391719 * safezoneW + safezoneX";
|
||||
y = "0.632 * safezoneH + safezoneY";
|
||||
w = "0.20625 * safezoneW";
|
||||
h = "0.044 * safezoneH";
|
||||
colorBackground[]={0,0,0,0.5};
|
||||
tooltip = "Optional shared feed URL. If empty, the UAV 3DEN URL is used first, then a local RTP fallback.";
|
||||
};
|
||||
class armatak_gui_module_udp_socket_dialog_address_text: RscText {
|
||||
idc = 16963;
|
||||
text = "EUD's Address";
|
||||
@@ -68,12 +78,20 @@ class armatak_udp_socket_start_dialog {
|
||||
w = "0.20625 * safezoneW";
|
||||
h = "0.033 * safezoneH";
|
||||
};
|
||||
class armatak_gui_module_udp_socket_dialog_video_feed_url_text: RscText {
|
||||
idc = 16970;
|
||||
text = "Video Feed URL (Optional)";
|
||||
x = "0.391719 * safezoneW + safezoneX";
|
||||
y = "0.599 * safezoneH + safezoneY";
|
||||
w = "0.20625 * safezoneW";
|
||||
h = "0.033 * safezoneH";
|
||||
};
|
||||
class armatak_gui_module_udp_socket_dialog_address_button_cancel: RscButton {
|
||||
idc = 16965;
|
||||
text = "Cancel";
|
||||
action = "closeDialog 2;";
|
||||
x = "0.551563 * safezoneW + safezoneX";
|
||||
y = "0.632 * safezoneH + safezoneY";
|
||||
y = "0.709 * safezoneH + safezoneY";
|
||||
w = "0.0464063 * safezoneW";
|
||||
h = "0.055 * safezoneH";
|
||||
};
|
||||
@@ -82,7 +100,7 @@ class armatak_udp_socket_start_dialog {
|
||||
text = "Ok";
|
||||
action = QUOTE(call FUNC(startUDPSocket));
|
||||
x = "0.5 * safezoneW + safezoneX";
|
||||
y = "0.632 * safezoneH + safezoneY";
|
||||
y = "0.709 * safezoneH + safezoneY";
|
||||
w = "0.0464063 * safezoneW";
|
||||
h = "0.055 * safezoneH";
|
||||
};
|
||||
|
||||
@@ -14,19 +14,24 @@ disableSerialization;
|
||||
private _eud_address = ctrlText 16961;
|
||||
private _gnss_port = ctrlText 16962;
|
||||
private _mavlink_port = ctrlText 16967;
|
||||
private _video_feed_url = ctrlText 16969;
|
||||
|
||||
private _udp_socket_fulladdress = _eud_address + ":" + _gnss_port;
|
||||
private _mavlink_address = _eud_address + ":" + _mavlink_port;
|
||||
|
||||
player setVariable [QGVAR(udp_socket_address), _udp_socket_fulladdress];
|
||||
player setVariable [QGVAR(mavlink_address), _mavlink_address];
|
||||
player setVariable [QGVAR(video_feed_url), trim _video_feed_url];
|
||||
player setVariable [QGVAR(eudConnected), true];
|
||||
|
||||
private _advertised_video_uri = [objNull] call EFUNC(uav,resolveVideoUri);
|
||||
|
||||
"armatak" callExtension ["udp_socket:start", [_udp_socket_fulladdress]];
|
||||
"armatak" callExtension ["uas:start_endpoint", [parseNumber _mavlink_port]];
|
||||
|
||||
private _mdnsInstanceName = format ["ArmaTAK-%1", name player];
|
||||
"armatak" callExtension ["mdns:start_uas_advertisement", [_mdnsInstanceName, parseNumber _mavlink_port, "rtp://0.0.0.0:5600"]];
|
||||
"armatak" callExtension ["log", [["info", format ["Client UDP socket started for %1 and MAVLink target set to %2", _udp_socket_fulladdress, _mavlink_address]]]];
|
||||
"armatak" callExtension ["mdns:start_uas_advertisement", [_mdnsInstanceName, parseNumber _mavlink_port, _advertised_video_uri]];
|
||||
"armatak" callExtension ["log", [["info", format ["Client UDP socket started for %1, MAVLink target set to %2 and advertised video URI set to %3", _udp_socket_fulladdress, _mavlink_address, _advertised_video_uri]]]];
|
||||
|
||||
call EFUNC(uav,startMavlinkBroadcast);
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ class Cfg3den {
|
||||
};
|
||||
class armatak_attribute_marker_video_url {
|
||||
displayName = "Video Feed URL";
|
||||
tooltip = "Video feed URL injected into __video on TAK";
|
||||
tooltip = "Shared UAV video URL. This per-vehicle value overrides the optional session video URL from Connect to EUD.";
|
||||
property = "armatak_attribute_marker_video_url";
|
||||
control = "Edit";
|
||||
expression = "_this setVariable ['armatak_attribute_marker_video_url',_value]";
|
||||
|
||||
@@ -14,6 +14,7 @@ addMissionEventHandler ["ExtensionCallback", {
|
||||
case "EUD Disconnected": {
|
||||
SETVAR(player,EGVAR(client,eudConnected),false);
|
||||
call EFUNC(uav,stopMavlinkBroadcast);
|
||||
"armatak" callExtension ["uas:stop_endpoint", []];
|
||||
"armatak" callExtension ["mdns:stop", []];
|
||||
};
|
||||
default {};
|
||||
@@ -28,15 +29,45 @@ addMissionEventHandler ["ExtensionCallback", {
|
||||
if (_function == "UDP Socket is not running") then {
|
||||
SETVAR(player,EGVAR(client,eudConnected),false);
|
||||
call EFUNC(uav,stopMavlinkBroadcast);
|
||||
"armatak" callExtension ["uas:stop_endpoint", []];
|
||||
"armatak" callExtension ["mdns:stop", []];
|
||||
};
|
||||
|
||||
if (_function == "failed to bind UDP socket") then {
|
||||
SETVAR(player,EGVAR(client,eudConnected),false);
|
||||
call EFUNC(uav,stopMavlinkBroadcast);
|
||||
"armatak" callExtension ["uas:stop_endpoint", []];
|
||||
"armatak" callExtension ["mdns:stop", []];
|
||||
};
|
||||
};
|
||||
case "MAVLINK UDP ERROR": {
|
||||
_message = _function;
|
||||
if (_data isNotEqualTo "") then {
|
||||
_message = format ["%1: %2", _function, _data];
|
||||
};
|
||||
|
||||
[_message, "warning", _name] call FUNC(notify);
|
||||
};
|
||||
case "MAVLINK UDP": {
|
||||
private _history = missionNamespace getVariable ["armatak_uav_mavlink_callback_history", []];
|
||||
_history pushBack [diag_tickTime, _function, _data];
|
||||
if ((count _history) > 50) then {
|
||||
_history deleteRange [0, (count _history) - 50];
|
||||
};
|
||||
missionNamespace setVariable ["armatak_uav_mavlink_callback_history", _history];
|
||||
missionNamespace setVariable ["armatak_uav_last_mavlink_callback", [diag_tickTime, _function, _data]];
|
||||
|
||||
switch (_function) do {
|
||||
case "COMMAND_LONG";
|
||||
case "COMMAND_INT";
|
||||
case "COMMAND_ACK";
|
||||
case "MANUAL_CONTROL": {
|
||||
"armatak" callExtension ["log", [["info", format ["MAVLINK UDP CALLBACK %1 %2", _function, _data]]]];
|
||||
[_function, _data] call EFUNC(uav,handleMavlinkCallback);
|
||||
};
|
||||
default {};
|
||||
};
|
||||
};
|
||||
case "TCP SOCKET": {
|
||||
[_function, "success", _name] call FUNC(notify);
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
PREP(startMavlinkBroadcast);
|
||||
PREP(stopMavlinkBroadcast);
|
||||
PREP(updateMavlinkBroadcast);
|
||||
PREP(resolveVideoUri);
|
||||
PREP(handleMavlinkCallback);
|
||||
PREP(parseMavlinkCallbackData);
|
||||
|
||||
63
addons/uav/functions/fnc_handleMavlinkCallback.sqf
Normal file
63
addons/uav/functions/fnc_handleMavlinkCallback.sqf
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "..\script_component.hpp"
|
||||
|
||||
params ["_function", ["_data", "", [""]]];
|
||||
|
||||
if (!hasInterface) exitWith {};
|
||||
|
||||
private _payload = [_data] call FUNC(parseMavlinkCallbackData);
|
||||
private _uav = getConnectedUAV player;
|
||||
if (isNull _uav) exitWith {
|
||||
"armatak" callExtension ["log", [["warn", format ["Ignoring MAVLINK UDP callback %1 because no UAV is connected: %2", _function, _data]]]];
|
||||
};
|
||||
|
||||
private _command = parseNumber (_payload getOrDefault ["command", "-1"]);
|
||||
private _commandName = _payload getOrDefault ["command_name", "UNKNOWN"];
|
||||
|
||||
switch (_function) do {
|
||||
case "COMMAND_LONG": {
|
||||
switch (_command) do {
|
||||
case 400: {
|
||||
private _armValue = parseNumber (_payload getOrDefault ["param1", "0"]);
|
||||
private _doArm = _armValue >= 1;
|
||||
_uav engineOn _doArm;
|
||||
if (_doArm) then {
|
||||
_uav setFuel ((fuel _uav) max 0.1);
|
||||
};
|
||||
systemChat format ["ATAK %1 %2", ["DISARM", "ARM"] select _doArm, [_uav] call armatak_fnc_extract_marker_callsign];
|
||||
"armatak" callExtension ["log", [["info", format ["Applied MAVLINK COMMAND_LONG %1 (%2) to UAV %3", _command, _commandName, _uav]]]];
|
||||
};
|
||||
case 22: {
|
||||
_uav engineOn true;
|
||||
_uav setFuel ((fuel _uav) max 0.1);
|
||||
_uav flyInHeight 75;
|
||||
|
||||
if (_uav isKindOf "Helicopter" || {_uav isKindOf "VTOL_Base_F"} || {_uav isKindOf "Quadbike_01_F"}) then {
|
||||
private _velocity = velocityModelSpace _uav;
|
||||
_uav setVelocityModelSpace [
|
||||
_velocity select 0,
|
||||
(_velocity select 1) max 15,
|
||||
((_velocity select 2) max 0) + 8
|
||||
];
|
||||
};
|
||||
|
||||
systemChat format ["ATAK TAKEOFF %1", [_uav] call armatak_fnc_extract_marker_callsign];
|
||||
"armatak" callExtension ["log", [["info", format ["Applied MAVLINK TAKEOFF to UAV %1", _uav]]]];
|
||||
};
|
||||
default {
|
||||
"armatak" callExtension ["log", [["info", format ["Unhandled MAVLINK COMMAND_LONG %1 (%2): %3", _command, _commandName, _data]]]];
|
||||
};
|
||||
};
|
||||
};
|
||||
case "COMMAND_INT": {
|
||||
"armatak" callExtension ["log", [["info", format ["Received MAVLINK COMMAND_INT %1 (%2): %3", _command, _commandName, _data]]]];
|
||||
};
|
||||
case "COMMAND_ACK": {
|
||||
"armatak" callExtension ["log", [["info", format ["Received MAVLINK COMMAND_ACK %1 (%2): %3", _command, _commandName, _data]]]];
|
||||
};
|
||||
case "MANUAL_CONTROL": {
|
||||
"armatak" callExtension ["log", [["info", format ["Received MAVLINK MANUAL_CONTROL: %1", _data]]]];
|
||||
};
|
||||
default {
|
||||
"armatak" callExtension ["log", [["info", format ["Unhandled MAVLINK UDP callback %1: %2", _function, _data]]]];
|
||||
};
|
||||
};
|
||||
17
addons/uav/functions/fnc_parseMavlinkCallbackData.sqf
Normal file
17
addons/uav/functions/fnc_parseMavlinkCallbackData.sqf
Normal file
@@ -0,0 +1,17 @@
|
||||
#include "..\script_component.hpp"
|
||||
|
||||
params [["_raw", "", [""]]];
|
||||
|
||||
private _pairs = createHashMap;
|
||||
|
||||
{
|
||||
private _entry = _x;
|
||||
private _separatorIndex = _entry find "=";
|
||||
if (_separatorIndex > 0) then {
|
||||
private _key = _entry select [0, _separatorIndex];
|
||||
private _value = _entry select [_separatorIndex + 1];
|
||||
_pairs set [_key, _value];
|
||||
};
|
||||
} forEach (_raw splitString ";");
|
||||
|
||||
_pairs
|
||||
37
addons/uav/functions/fnc_resolveVideoUri.sqf
Normal file
37
addons/uav/functions/fnc_resolveVideoUri.sqf
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "..\script_component.hpp"
|
||||
|
||||
params [["_uav", objNull, [objNull]]];
|
||||
|
||||
private _defaultVideoUri = "rtsp://irontak.com:554/fpv";
|
||||
private _activelyControlledUav = if (!isNull player) then {getConnectedUAV player} else {objNull};
|
||||
|
||||
private _normalize = {
|
||||
params ["_rawUrl"];
|
||||
|
||||
private _url = trim _rawUrl;
|
||||
if (_url isEqualTo "") exitWith {""};
|
||||
|
||||
if (_url find "://" >= 0) exitWith {_url};
|
||||
|
||||
if (_url find "/" >= 0) exitWith {
|
||||
format ["rtsp://%1", _url]
|
||||
};
|
||||
|
||||
format ["rtp://%1", _url]
|
||||
};
|
||||
|
||||
if (!isNull _uav && {_activelyControlledUav isEqualTo _uav}) then {
|
||||
private _objectVideoUrl = [_uav] call armatak_fnc_extract_marker_video_url;
|
||||
private _normalizedObjectVideoUrl = [_objectVideoUrl] call _normalize;
|
||||
if (_normalizedObjectVideoUrl isNotEqualTo "") exitWith {
|
||||
_normalizedObjectVideoUrl
|
||||
};
|
||||
};
|
||||
|
||||
private _sessionVideoUrl = player getVariable [QEGVAR(client,video_feed_url), ""];
|
||||
private _normalizedSessionVideoUrl = [_sessionVideoUrl] call _normalize;
|
||||
if (_normalizedSessionVideoUrl isNotEqualTo "") exitWith {
|
||||
_normalizedSessionVideoUrl
|
||||
};
|
||||
|
||||
_defaultVideoUri
|
||||
@@ -37,6 +37,9 @@ private _mavlinkAddress = player getVariable [QEGVAR(client,mavlink_address), ""
|
||||
if (_mavlinkAddress isEqualTo "") exitWith {};
|
||||
|
||||
private _pos = [_uav] call EFUNC(client,extractClientPosition);
|
||||
private _uuid = [_uav] call armatak_fnc_extract_uuid;
|
||||
private _callsign = [_uav] call armatak_fnc_extract_marker_callsign;
|
||||
private _videoUri = [_uav] call FUNC(resolveVideoUri);
|
||||
private _dir = vectorDir _uav;
|
||||
private _up = vectorUp _uav;
|
||||
private _yaw = getDir _uav;
|
||||
@@ -45,24 +48,14 @@ private _roll = asin (((_up select 0) max -1) min 1);
|
||||
private _relAlt = ((getPosATL _uav) select 2) max 0;
|
||||
private _uavType = if (_uav isKindOf "Plane") then {1} else {[2, 3] select (_uav isKindOf "Helicopter")};
|
||||
|
||||
private _bodyPayload = [
|
||||
_mavlinkAddress,
|
||||
1,
|
||||
1,
|
||||
_uavType,
|
||||
_pos select 1,
|
||||
_pos select 2,
|
||||
_pos select 3,
|
||||
_relAlt,
|
||||
_pos select 5,
|
||||
_pos select 6,
|
||||
_roll,
|
||||
_pitch,
|
||||
_yaw,
|
||||
parseNumber isEngineOn _uav
|
||||
];
|
||||
|
||||
"armatak" callExtension ["mavlink_mock:send_uas_telemetry", [_bodyPayload]];
|
||||
private _gimbalRoll = 0;
|
||||
private _gimbalPitch = _pitch;
|
||||
private _gimbalYaw = _yaw;
|
||||
private _hfov = _uav getVariable ["armatak_uas_fov", 60];
|
||||
private _vfov = _uav getVariable ["armatak_uas_vfov", (_hfov * 0.5625)];
|
||||
private _imageLat = _pos select 1;
|
||||
private _imageLon = _pos select 2;
|
||||
private _imageAlt = _pos select 3;
|
||||
|
||||
private _laser = laserTarget _uav;
|
||||
if (!isNull _laser) then {
|
||||
@@ -84,27 +77,40 @@ if (!isNull _laser) then {
|
||||
|
||||
private _camYaw = ((_dirX atan2 _dirY) + 360) mod 360;
|
||||
private _camPitch = _dirZ atan2 (_horizontalMag max 0.001);
|
||||
_gimbalPitch = _camPitch;
|
||||
_gimbalYaw = _camYaw;
|
||||
|
||||
private _spiAgl = ASLToAGL _spiASL;
|
||||
private _camRelAlt = (_spiAgl select 2) max 0;
|
||||
|
||||
private _camPayload = [
|
||||
_mavlinkAddress,
|
||||
2,
|
||||
1,
|
||||
_uavType,
|
||||
_pos select 1,
|
||||
_pos select 2,
|
||||
_pos select 3,
|
||||
_camRelAlt,
|
||||
_camYaw,
|
||||
0,
|
||||
0,
|
||||
_camPitch,
|
||||
_camYaw,
|
||||
1
|
||||
];
|
||||
|
||||
"armatak" callExtension ["mavlink_mock:send_uas_telemetry", [_camPayload]];
|
||||
private _imageGeo = [_targetWorld select 0, _targetWorld select 1, _targetAslZ] call EFUNC(client,convertClientLocation);
|
||||
_imageLat = _imageGeo select 0;
|
||||
_imageLon = _imageGeo select 1;
|
||||
_imageAlt = _imageGeo select 2;
|
||||
};
|
||||
};
|
||||
|
||||
private _systemPayload = [
|
||||
_mavlinkAddress,
|
||||
_uuid,
|
||||
_callsign,
|
||||
_uavType,
|
||||
_pos select 1,
|
||||
_pos select 2,
|
||||
_pos select 3,
|
||||
_relAlt,
|
||||
_pos select 5,
|
||||
_pos select 6,
|
||||
_roll,
|
||||
_pitch,
|
||||
_yaw,
|
||||
parseNumber isEngineOn _uav,
|
||||
_gimbalRoll,
|
||||
_gimbalPitch,
|
||||
_gimbalYaw,
|
||||
_videoUri,
|
||||
_hfov,
|
||||
_vfov,
|
||||
_imageLat,
|
||||
_imageLon,
|
||||
_imageAlt
|
||||
];
|
||||
|
||||
"armatak" callExtension ["uas:send_uas_system", [_systemPayload]];
|
||||
|
||||
Reference in New Issue
Block a user