mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Navigation
This commit is contained in:
parent
1ece7238dc
commit
4e24a7bf80
@ -468,6 +468,23 @@ do -- COORDINATE
|
||||
end
|
||||
|
||||
|
||||
--- Returns the coordinate from the latitude and longitude given in degrees, minutes and seconds (DMS).
|
||||
-- @param #COORDINATE self
|
||||
-- @param #string Latitude Latitude in DMS as string, e.g. "`42° 24' 14.3"`". Not that the characters `°`, `'` and `"` are important.
|
||||
-- @param #string Longitude Longitude in DMS as string, e.g. "`42° 24' 14.3"`". Not that the characters `°`, `'` and `"` are important.
|
||||
-- @param #number Altitude (Optional) Altitude in meters. Default is the land height at the coordinate.
|
||||
-- @return #COORDINATE
|
||||
function COORDINATE:NewFromLLDMS(Latitude, Longitude, Altitude)
|
||||
|
||||
local lat=UTILS.LLDMSstringToDD(Latitude)
|
||||
local lon=UTILS.LLDMSstringToDD(Longitude)
|
||||
|
||||
self=COORDINATE:NewFromLLDD(lat, lon, Altitude)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Returns if the 2 coordinates are at the same 2D position.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #COORDINATE Coordinate
|
||||
|
||||
@ -270,6 +270,48 @@ function VECTOR:NewDirectionalVector(a, b)
|
||||
return c
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new VECTOR instance from given the latitude and longitude in decimal degrees (DD).
|
||||
-- @param #VECTOR self
|
||||
-- @param #number Latitude Latitude in decimal degrees.
|
||||
-- @param #number Longitude Longitude in decimal degrees.
|
||||
-- @param #number altitude (Optional) Altitude in meters. Default is the land height at the 2D position.
|
||||
-- @return #VECTOR self
|
||||
function VECTOR:NewFromLLDD(Latitude, Longitude, Altitude)
|
||||
|
||||
-- Returns a point from latitude and longitude in the vec3 format.
|
||||
local vec3=coord.LLtoLO(Latitude, Longitude)
|
||||
|
||||
-- Convert vec3 to coordinate object.
|
||||
self=VECTOR:NewFromVec(vec3)
|
||||
|
||||
-- -- Adjust height
|
||||
-- if Altitude==nil then
|
||||
-- self.y=self:GetSurfaceHeight()
|
||||
-- else
|
||||
-- self.y=Altitude
|
||||
-- end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a new VECTOR instance from given latitude and longitude in degrees, minutes and seconds (DMS).
|
||||
-- **Note** that latitude and longitude are passed as strings and the characters `°`, `'` and `"` are important.
|
||||
-- @param #VECTOR self
|
||||
-- @param #string Latitude Latitude in DMS as string, e.g. "`42° 24' 14.3"`".
|
||||
-- @param #string Longitude Longitude in DMS as string, e.g. "`42° 24' 14.3"`".
|
||||
-- @param #number Altitude (Optional) Altitude in meters. Default is the land height at the coordinate.
|
||||
-- @return #VECTOR
|
||||
function VECTOR:NewFromLLDMS(Latitude, Longitude, Altitude)
|
||||
|
||||
local lat=UTILS.LLDMSstringToDD(Latitude)
|
||||
local lon=UTILS.LLDMSstringToDD(Longitude)
|
||||
|
||||
self=VECTOR:NewFromLLDD(lat, lon, Altitude)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -25,11 +25,12 @@
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #table fixes Navigation fixes.
|
||||
-- @field Core.Pathline#PATHLINE pathline Pathline of the plan.
|
||||
-- @field Wrapper.Airbase#AIRBASE departureAirbase Departure airbase.
|
||||
-- @field Wrapper.Airbase#AIRBASE destinationAirbase Destination airbase.
|
||||
-- @field #number altitudeCruiseMin Minimum cruise altitude in feet MSL.
|
||||
-- @field #number altitudeCruiseMax Maximum cruise altitude in feet MSL.
|
||||
-- @extends Core.Base#BASE
|
||||
-- @extends Core.Pathline#PATHLINE
|
||||
|
||||
--- *Life is what happens to us while we are making other plans.* -- Allen Saunders
|
||||
--
|
||||
@ -37,12 +38,11 @@
|
||||
--
|
||||
-- # The FLIGHTPLAN Concept
|
||||
--
|
||||
-- A FLIGHTPLAN consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
-- This class has a great concept!
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `FLIGHTPLAN` object can be created with the @{#FLIGHTPLAN.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
|
||||
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
|
||||
-- A new `FLIGHTPLAN` object can be created with the @{#FLIGHTPLAN.New}() function.
|
||||
--
|
||||
-- myFlightplan=FLIGHTPLAN:New("Plan A")
|
||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
||||
@ -81,8 +81,10 @@ FLIGHTPLAN.version="0.0.1"
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: How to connect SID, STAR, ENROUTE, TRANSITION, APPROACH. Typical flightplan SID --> ENROUTE --> STAR --> APPROACH
|
||||
-- TODO: How to handle the FLIGHTGROUP:_LandAtAirBase
|
||||
-- TODO: Add approach.
|
||||
-- DONE: How to handle the FLIGHTGROUP:_LandAtAirBase
|
||||
-- TODO: Do we always need a holding pattern? https://www.faa.gov/air_traffic/publications/atpubs/aip_html/part2_enr_section_1.5.html#:~:text=If%20no%20holding%20pattern%20is,than%20that%20desired%20by%20ATC.
|
||||
-- DOEN: Read from MSFS file.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@ -94,8 +96,8 @@ FLIGHTPLAN.version="0.0.1"
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:New(Name)
|
||||
|
||||
-- Inherit everything from SCENERY class.
|
||||
self=BASE:Inherit(self, BASE:New()) -- #FLIGHTPLAN
|
||||
-- Inherit everything from BASE class.
|
||||
self=BASE:Inherit(self, PATHLINE:New(Name)) -- #FLIGHTPLAN
|
||||
|
||||
-- Set alias.
|
||||
self.alias=tostring(Name)
|
||||
@ -103,6 +105,8 @@ function FLIGHTPLAN:New(Name)
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("FLIGHTPLAN %s | ", self.alias)
|
||||
|
||||
--self.pathline=PATHLINE:New(Name)
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("Created FLIGHTPLAN!"))
|
||||
|
||||
@ -119,30 +123,55 @@ function FLIGHTPLAN:NewFromFlightPlan(FlightPlan)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Create a new FLIGHTPLAN instance from a given file.
|
||||
-- Currently, the file has to be an MSFS 2020 .pln file as, *e.g.*, exported from [Navigraph](https://navigraph.com/).
|
||||
--
|
||||
-- **Note** that the flight plan does only cover the departure, enroute and arrival portions but **not the approach** part!
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #string FileName Full path to file.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:NewFromFile(FileName)
|
||||
|
||||
if UTILS.FileExists(FileName) then
|
||||
|
||||
self=FLIGHTPLAN._ReadFileMSFS(FileName)
|
||||
|
||||
else
|
||||
error(string.format("ERROR: File not found! File name=%s", tostring(FileName)))
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add navigation fix to the flight plan.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param Navigation.NavFix#NAVFIX NavFix The nav fix.
|
||||
-- @param Navigation.Point#NAVPOINT NavFix The nav fix.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:AddNavFix(NavFix)
|
||||
|
||||
table.insert(self.fixes, NavFix)
|
||||
|
||||
local point=self:AddPointFromVec3(NavFix.vector:GetVec3(true))
|
||||
|
||||
point.navpoint=NavFix
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set depature airbase.
|
||||
--- Set departure airbase.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:SetDepartureAirbase(AirbaseName)
|
||||
|
||||
self.departureAirbase=AIRBASE:FindByName(AirbaseName)
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -171,6 +200,19 @@ function FLIGHTPLAN:SetCruiseAltitude(AltMin, AltMax)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set cruise speed.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @param #number SpeedMin Minimum speed in knots.
|
||||
-- @param #number SpeedMax Maximum speed in knots. Default is `SpeedMin`.
|
||||
-- @return #FLIGHTPLAN self
|
||||
function FLIGHTPLAN:SetCruiseSpeed(SpeedMin, SpeedMax)
|
||||
|
||||
self.speedCruiseMin=SpeedMin
|
||||
self.speedCruiseMax=SpeedMax or self.speedCruiseMin
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Get the name of this flight plan.
|
||||
-- @param #FLIGHTPLAN self
|
||||
@ -197,11 +239,242 @@ function FLIGHTPLAN:GetCruiseAltitude()
|
||||
return alt
|
||||
end
|
||||
|
||||
--- Get cruise speed. This returns a random speed between the set min/max cruise speeds.
|
||||
-- @param #FLIGHTPLAN self
|
||||
-- @return #number Cruise speed in knots.
|
||||
function FLIGHTPLAN:GetCruiseSpeed()
|
||||
|
||||
local speed=250
|
||||
|
||||
if self.speedCruiseMin and self.speedCruiseMax then
|
||||
speed=math.random(self.speedCruiseMin, self.speedCruiseMax)
|
||||
elseif self.speedCruiseMin then
|
||||
speed=self.speedCruiseMin
|
||||
elseif self.altitudeCruiseMax then
|
||||
speed=self.speedCruiseMax
|
||||
end
|
||||
|
||||
return speed
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Private Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- No private functions yet.
|
||||
--- Read flight plan from a given MSFS 2020 .plt file.
|
||||
-- @param #string FileName Name of the file.
|
||||
-- @return #FLIGHTPLAN The flight plan.
|
||||
function FLIGHTPLAN._ReadFileMSFS(FileName)
|
||||
|
||||
local function readfile(filename)
|
||||
|
||||
local lines = {}
|
||||
|
||||
-- Open file in read binary mode.
|
||||
local file=assert(io.open(filename, "rb"), string.format("File not found! File name = %s", tostring(filename)))
|
||||
|
||||
for line in file:lines() do
|
||||
lines[#lines+1] = line
|
||||
end
|
||||
|
||||
-- Close file.
|
||||
file:close()
|
||||
|
||||
-- Return data
|
||||
return lines
|
||||
end
|
||||
|
||||
|
||||
--- This function returns an XML element, i.e. the string between <...> and </...>.
|
||||
local function getXMLelement(line)
|
||||
local element=string.match(line, ">(.+)<")
|
||||
return element
|
||||
end
|
||||
|
||||
--- This function returns Latitude and Longitude
|
||||
local function getLatLong(line)
|
||||
local latlong=getXMLelement(line)
|
||||
-- The format is "N41° 38' 20.00",E41° 33' 19.00",+000000.00" so we still need to process that.
|
||||
local lat,long=string.match(latlong, "(.+),(.+),")
|
||||
return lat,long
|
||||
end
|
||||
|
||||
-- Read data from file.
|
||||
local data=readfile(FileName)
|
||||
|
||||
local flightplan={}
|
||||
local waypoints={}
|
||||
local wp=nil
|
||||
|
||||
local gotwaypoint=false
|
||||
for i,line in pairs(data) do
|
||||
|
||||
|
||||
--print(line)
|
||||
|
||||
-- Title
|
||||
if string.find(line, "<Title>") then
|
||||
flightplan.title=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Departure ICAO
|
||||
if string.find(line, "<DepartureID>") then
|
||||
flightplan.departureICAO=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Destination ICAO
|
||||
if string.find(line, "<DestinationID>") then
|
||||
flightplan.destinationICAO=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- FPType
|
||||
if string.find(line, "<FPType>") then
|
||||
flightplan.plantype=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Route type
|
||||
if string.find(line, "<RouteType>") then
|
||||
flightplan.routetype=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Cruise alt in feet
|
||||
if string.find(line, "<CruisingAlt>") then
|
||||
flightplan.altCruise=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Departure LLA
|
||||
if string.find(line, "<DepartureLLA>") then
|
||||
local lat,long=getLatLong(line)
|
||||
end
|
||||
|
||||
-- Destination LLA
|
||||
if string.find(line, "<DestinationLLA>") then
|
||||
local lat,long=getLatLong(line)
|
||||
end
|
||||
|
||||
-- Departure Name
|
||||
if string.find(line, "<DepartureName>") then
|
||||
local DepartureName=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- DestinationName
|
||||
if string.find(line, "<DestinationName>") then
|
||||
local DestinationName=getXMLelement(line)
|
||||
end
|
||||
|
||||
---
|
||||
-- Waypoint stuff
|
||||
---
|
||||
|
||||
-- New waypoint starts.
|
||||
if string.find(line, "ATCWaypoint id") then
|
||||
|
||||
--Get string inside quotes " and ".
|
||||
local wpid=string.match(line, [["(.+)"]])
|
||||
|
||||
-- Create a new wp table.
|
||||
wp={}
|
||||
|
||||
-- Set waypoint name.
|
||||
wp.name=wpid
|
||||
end
|
||||
|
||||
-- Waypoint info ends.
|
||||
if string.find(line, "</ATCWaypoint>") then
|
||||
-- This is the end of the waypoint.
|
||||
|
||||
-- Add info to waypoints table.
|
||||
table.insert(waypoints, wp)
|
||||
|
||||
-- Set waypoint to nil. We create an empty table if the next wp starts.
|
||||
wp=nil
|
||||
end
|
||||
|
||||
-- Waypoint type (Airport, Intersection, NDB, VORTAC)
|
||||
if string.find(line, "<ATCWaypointType>") then
|
||||
local wptype=getXMLelement(line)
|
||||
wp.type=wptype
|
||||
end
|
||||
|
||||
-- Waypoint position.
|
||||
if string.find(line, "<WorldPosition>") then
|
||||
wp.lat, wp.long=getLatLong(line)
|
||||
end
|
||||
|
||||
-- Runway should exist for initial and final WP if it is an airport.
|
||||
if string.find(line, "RunwayNumberFP") then
|
||||
wp.runway=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Runway designator: LEFT, RIGHT, CENTER
|
||||
if string.find(line, "RunwayDesignatorFP") then
|
||||
wp.runwayDesignator=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Segment is Departure
|
||||
if string.find(line, "<DepartureFP>") then
|
||||
wp.segment="Departure"
|
||||
end
|
||||
|
||||
-- Segment is Arrival
|
||||
if string.find(line, "<ArrivalFP>") then
|
||||
wp.segment="Arrival"
|
||||
end
|
||||
|
||||
-- Segment is Enroute
|
||||
if string.find(line, "<ATCAirway>") then
|
||||
wp.segment="Enroute"
|
||||
end
|
||||
|
||||
-- Approach type: VORDME, LOCALIZER
|
||||
if string.find(line, "ApproachTypeFP") then
|
||||
flightplan.approachtype=getXMLelement(line)
|
||||
end
|
||||
|
||||
-- Approach type suffic: Z
|
||||
if string.find(line, "SuffixFP") then
|
||||
local SuffixFP=getXMLelement(line)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
for key, value in pairs(flightplan) do
|
||||
env.info(string.format("Flightplan %s=%s", key, tostring(value)))
|
||||
end
|
||||
|
||||
env.info(string.format("Number of waypoints=%d", #waypoints))
|
||||
for i,wp in pairs(waypoints) do
|
||||
env.info(string.format("Waypoint name=%s type=%s segment=%s runway=%s lat=%s long=%s", wp.name, wp.type, tostring(wp.segment), tostring(wp.runway)..tostring(wp.runwayDesignator or ""), wp.lat, wp.long))
|
||||
end
|
||||
|
||||
-- Create a new flightplan.
|
||||
local fp=FLIGHTPLAN:New(flightplan.title)
|
||||
|
||||
-- Set cruise altitude.
|
||||
fp:SetCruiseAltitude(flightplan.altCruise)
|
||||
|
||||
-- Set departure and destination airports.
|
||||
fp:SetDepartureAirbase(flightplan.departureICAO)
|
||||
fp:SetDestinationAirbase(flightplan.destinationICAO)
|
||||
|
||||
--TODO: Remove first and last waypoint if they are identical to the departure/destination airport!
|
||||
|
||||
for i,wp in pairs(waypoints) do
|
||||
|
||||
-- Create a navpoint.
|
||||
local navpoint=NAVPOINT:NewFromLLDMS(wp.name, wp.type, wp.lat, wp.long)
|
||||
|
||||
navpoint:SetAltMin(flightplan.altCruise)
|
||||
|
||||
-- Add point to flightplan.
|
||||
-- TODO: section departure, enroute, arrival.
|
||||
fp:AddNavFix(navpoint)
|
||||
end
|
||||
|
||||
|
||||
|
||||
return fp
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -97,7 +97,7 @@ function NAVAID:New(ZoneName, SceneryName, Type)
|
||||
|
||||
self.zone=ZONE:FindByName(ZoneName)
|
||||
|
||||
self=self.zone:GetCoordinate()
|
||||
self.coordinate=self.zone:GetCoordinate()
|
||||
|
||||
if SceneryName then
|
||||
self.scenery=SCENERY:FindByNameInZone(SceneryName, ZoneName)
|
||||
@ -364,6 +364,7 @@ end
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #string name Name of the point.
|
||||
-- @field #string typePoint Type of the point, *e.g. "Intersection", "VOR", "Airport".
|
||||
-- @field Core.Vector#VECTOR vector Position vector of the fix.
|
||||
-- @field Wrapper.Marker#MARKER marker Marker on F10 map.
|
||||
-- @field #number altMin Minimum altitude in meters.
|
||||
@ -377,13 +378,16 @@ end
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The NAVFIX Concept
|
||||
-- # The NAVPOINT Concept
|
||||
--
|
||||
-- The NAVFIX class has a great concept!
|
||||
-- The NAVPOINT class has a great concept!
|
||||
--
|
||||
-- A NAVPOINT describes a geo position and can, *e.g.*, be part of a FLIGHTPLAN. It has a unique name and is of a certain type, *e.g.* "Intersection", "VOR", "Airbase" etc.
|
||||
-- It can also have further properties as min/max altitudes and speeds that aircraft need to obey when they pass the point.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
-- A new `NAVFIX` object can be created with the @{#NAVFIX.New}() function.
|
||||
-- A new `NAVPOINT` object can be created with the @{#NAVPOINT.New}() function.
|
||||
--
|
||||
-- myNavPoint=NAVPOINT:New()
|
||||
-- myTemplate:SetXYZ(X, Y, Z)
|
||||
@ -396,6 +400,21 @@ NAVPOINT = {
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- Type of point.
|
||||
-- @type NAVPOINT.Type
|
||||
-- @field #string VOR VOR
|
||||
-- @field #string NDB NDB
|
||||
NAVPOINT.Type={
|
||||
POINT="Point",
|
||||
INTERSECTION="Intersection",
|
||||
AIRPORT="Airport",
|
||||
VOR="VOR",
|
||||
DME="DME",
|
||||
VORDME="VOR/DME",
|
||||
LOC="Localizer",
|
||||
NDB="NDB",
|
||||
}
|
||||
|
||||
--- NAVPOINT class version.
|
||||
-- @field #string version
|
||||
NAVPOINT.version="0.0.1"
|
||||
@ -412,10 +431,11 @@ NAVPOINT.version="0.0.1"
|
||||
|
||||
--- Create a new NAVPOINT class instance from a given VECTOR.
|
||||
-- @param #NAVPOINT self
|
||||
-- @param #string Name Name of the fix. Should be unique!
|
||||
-- @param #string Name Name of the point. Should be unique!
|
||||
-- @param #string Type Type of the point. Default `NAVPOINT.Type.POINT`.
|
||||
-- @param Core.Vector#VECTOR Vector Position vector of the navpoint.
|
||||
-- @return #NAVPOINT self
|
||||
function NAVPOINT:NewFromVector(Name, Vector)
|
||||
function NAVPOINT:NewFromVector(Name, Type, Vector)
|
||||
|
||||
-- Inherit everything from BASE class.
|
||||
self=BASE:Inherit(self, BASE:New()) -- #NAVFIX
|
||||
@ -426,6 +446,8 @@ function NAVPOINT:NewFromVector(Name, Vector)
|
||||
-- Name of point.
|
||||
self.name=Name
|
||||
|
||||
self.typePoint=Type or NAVPOINT.Type.POINT
|
||||
|
||||
-- Marker on F10.
|
||||
self.marker=MARKER:New(Vector:GetCoordinate(true), self:_GetMarkerText())
|
||||
|
||||
@ -439,15 +461,59 @@ end
|
||||
--- Create a new NAVPOINT class instance from a given COORDINATE.
|
||||
-- @param #NAVPOINT self
|
||||
-- @param #string Name Name of the fix. Should be unique!
|
||||
-- @param #string Type Type of the point. Default `NAVPOINT.Type.POINT`.
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate of the point.
|
||||
-- @return #NAVPOINT self
|
||||
function NAVPOINT:NewFromCoordinate(Name, Coordinate)
|
||||
function NAVPOINT:NewFromCoordinate(Name, Type, Coordinate)
|
||||
|
||||
-- Create a VECTOR from the coordinate.
|
||||
local Vector=VECTOR:NewFromVec(Coordinate)
|
||||
self=NAVPOINT:NewFromVector(Name, Vector)
|
||||
|
||||
-- Create NAVPOINT.
|
||||
self=NAVPOINT:NewFromVector(Name, Type, Vector)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a new NAVPOINT class instance from a given NAVPOINT.
|
||||
|
||||
--- Create a new NAVPOINT instance from given latitude and longitude in degrees, minutes and seconds (DMS).
|
||||
-- @param #NAVPOINT self
|
||||
-- @param #string Name Name of the fix. Should be unique!
|
||||
-- @param #string Type Type of the point. Default `NAVPOINT.Type.POINT`.
|
||||
-- @param #string Latitude Latitude in DMS as string.
|
||||
-- @param #string Longitude Longitude in DMS as string.
|
||||
-- @return #NAVPOINT self
|
||||
function NAVPOINT:NewFromLLDMS(Name, Type, Latitude, Longitude)
|
||||
|
||||
-- Create a VECTOR from the coordinate.
|
||||
local Vector=VECTOR:NewFromLLDMS(Latitude, Longitude)
|
||||
|
||||
-- Create NAVPOINT.
|
||||
self=NAVPOINT:NewFromVector(Name, Type, Vector)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a new NAVPOINT instance from given latitude and longitude in decimal degrees (DD).
|
||||
-- @param #NAVPOINT self
|
||||
-- @param #string Name Name of the fix. Should be unique!
|
||||
-- @param #string Type Type of the point. Default `NAVPOINT.Type.POINT`.
|
||||
-- @param #number Latitude Latitude in DD.
|
||||
-- @param #number Longitude Longitude in DD.
|
||||
-- @return #NAVPOINT self
|
||||
function NAVPOINT:NewFromLLDD(Name, Type, Latitude, Longitude)
|
||||
|
||||
-- Create a VECTOR from the coordinate.
|
||||
local Vector=VECTOR:NewFromLLDD(Latitude, Longitude)
|
||||
|
||||
-- Create NAVPOINT.
|
||||
self=NAVPOINT:NewFromVector(Name, Type, Vector)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Create a new NAVPOINT class instance relative to a given other NAVPOINT.
|
||||
-- You have to specify the distance and bearing from the new point to the given point. *E.g.*, for a distance of 5 NM and a bearing of 090° (West), the
|
||||
-- new nav point is created 5 NM East of the given nav point. The reason is that this corresponts to convention used in most maps.
|
||||
-- You can, however, use the `Reciprocal` switch to create the new point in the direction you specify.
|
||||
@ -517,7 +583,19 @@ end
|
||||
-- @return #NAVPOINT self
|
||||
function NAVPOINT:SetSpeedMin(Speed)
|
||||
|
||||
self.speedMin=Altitude
|
||||
self.speedMin=Speed
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set maximum speed.
|
||||
-- @param #NAVPOINT self
|
||||
-- @param #number Speed Max speed in knots.
|
||||
-- @return #NAVPOINT self
|
||||
function NAVPOINT:SetSpeedMax(Speed)
|
||||
|
||||
self.speedMax=Speed
|
||||
|
||||
return self
|
||||
end
|
||||
@ -541,13 +619,13 @@ function NAVPOINT:SetFlyOver(FlyOver)
|
||||
end
|
||||
|
||||
|
||||
--- Get the altitude in feet MSL.
|
||||
--- Get the altitude in feet MSL. If min and max altitudes are set, it will return a random altitude between min and max.
|
||||
-- @param #NAVPOINT self
|
||||
-- @return #number Altitude in feet MSL. Can be `nil`, if neither min nor max altitudes have beeen set.
|
||||
function NAVPOINT:GetAltitude()
|
||||
|
||||
local alt=nil
|
||||
if self.altMin and self.altMax then
|
||||
if self.altMin and self.altMax and self.altMin~=self.altMax then
|
||||
alt=math.random(self.altMin, self.altMax)
|
||||
elseif self.altMin then
|
||||
alt=self.altMin
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
--- **NAVIGATION** - Prodedures for Departure (SID), Arrival (STAR) and Approach.
|
||||
--- **NAVIGATION** - Prodedures for Departure (*e.g.* SID), Enroute, Arrival (*e.g.* STAR) and Approach.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
|
||||
@ -3697,13 +3697,17 @@ end
|
||||
-- Flightplan Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check flightplans.
|
||||
--- Set flightplan and add waypoints.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param Navigation.FlightPlan#FLIGHTPLAN FlightPlan Flight plan.
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:_SetFlightPlan(FlightPlan)
|
||||
|
||||
self:I(self.lid..string.format("Setting flightplan %s", FlightPlan.alias))
|
||||
|
||||
self.flightplan=FlightPlan
|
||||
|
||||
self:SetDestinationbase(self.flightplan.destinationAirbase)
|
||||
|
||||
for i,_fix in pairs(FlightPlan.fixes) do
|
||||
local fix=_fix --Navigation.NavFix#NAVFIX
|
||||
@ -3714,7 +3718,7 @@ function FLIGHTGROUP:_SetFlightPlan(FlightPlan)
|
||||
|
||||
local altitude=(fix.altMin or fix.altMax)~=nil and fix:GetAltitude() or FlightPlan:GetCruiseAltitude()
|
||||
|
||||
local wp=self:AddWaypoint(fix.coordinate, Speed, AfterWaypointWithID, altitude or 10000, false)
|
||||
local wp=self:AddWaypoint(fix.vector, Speed, AfterWaypointWithID, altitude or 10000, false)
|
||||
wp.flightplan=FlightPlan
|
||||
|
||||
end
|
||||
|
||||
@ -13493,20 +13493,24 @@ end
|
||||
-- @return Core.Point#COORDINATE The coordinate of the object.
|
||||
function OPSGROUP:_CoordinateFromObject(Object)
|
||||
|
||||
env.info("FF coordfrom object")
|
||||
if Object then
|
||||
if Object:IsInstanceOf("COORDINATE") then
|
||||
if VECTOR._IsVector(Object) then
|
||||
env.info("FF VECTOR")
|
||||
return Object:GetCoordinate()
|
||||
elseif Object:IsInstanceOf("COORDINATE") then
|
||||
return Object
|
||||
else
|
||||
if Object:IsInstanceOf("POSITIONABLE") or Object:IsInstanceOf("ZONE_BASE") then
|
||||
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
|
||||
self:E(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
|
||||
local coord=Object:GetCoordinate()
|
||||
return coord
|
||||
else
|
||||
self:T(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
|
||||
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
|
||||
end
|
||||
end
|
||||
else
|
||||
self:T(self.lid.."ERROR: Object passed is nil!")
|
||||
self:E(self.lid.."ERROR: Object passed is nil!")
|
||||
end
|
||||
|
||||
return nil
|
||||
|
||||
@ -721,7 +721,22 @@ end
|
||||
-- @return #number Latitude or Longitude in decimal degrees.
|
||||
UTILS.LLDMSToDD = function(Degrees, Minutes, Seconds)
|
||||
|
||||
local dd=(Degrees or 0) + (Minutes or 0)/60 + (Seconds or 0)/3600
|
||||
local dd=tonumber(Degrees or 0) + tonumber(Minutes or 0)/60 + tonumber(Seconds or 0)/3600
|
||||
|
||||
return dd
|
||||
end
|
||||
|
||||
--- Convert latitude or longitude from degrees, minutes, seconds (DMS) given in text form to decimal degrees (DD).
|
||||
-- @param #string LatOrLongString Latitude or longitude passed as ttring in format `DD°MM'SS.SS"`.
|
||||
-- @return #number Latitude or Longitude in decimal degrees.
|
||||
UTILS.LLDMSstringToDD = function(LatOrLongString)
|
||||
|
||||
local hem=string.match(LatOrLongString, "(%a)")
|
||||
local Degrees=string.match(LatOrLongString, "(%d+)°")
|
||||
local Minutes=string.match(LatOrLongString, "(%d+)'")
|
||||
local Seconds=string.match(LatOrLongString, "([%d\.]+)\"")
|
||||
|
||||
local dd=UTILS.LLDMSToDD(Degrees, Minutes, Seconds)
|
||||
|
||||
return dd
|
||||
end
|
||||
|
||||
@ -753,6 +753,32 @@ AIRBASE.SpotStatus = {
|
||||
RESERVED="Reserved",
|
||||
}
|
||||
|
||||
--- ICAO Codes.
|
||||
-- @type AIRBASE.ICAO
|
||||
AIRBASE.ICAO = {
|
||||
UGTB=AIRBASE.Caucasus.Tbilisi_Lochini,
|
||||
UGKO=AIRBASE.Caucasus.Kutaisi,
|
||||
UG5X=AIRBASE.Caucasus.Kobuleti,
|
||||
UG24=AIRBASE.Caucasus.Soganlug,
|
||||
UG27=AIRBASE.Caucasus.Vaziani,
|
||||
UGSS=AIRBASE.Caucasus.Sukhumi_Babushara,
|
||||
UG23=AIRBASE.Caucasus.Gudauta,
|
||||
URSS=AIRBASE.Caucasus.Sochi_Adler,
|
||||
URMO=AIRBASE.Caucasus.Beslan,
|
||||
URMN=AIRBASE.Caucasus.Nalchik,
|
||||
XRMF=AIRBASE.Caucasus.Mozdok,
|
||||
URMM=AIRBASE.Caucasus.Mineralnye_Vody,
|
||||
URKH=AIRBASE.Caucasus.Maykop_Khanskaya,
|
||||
URKK=AIRBASE.Caucasus.Krasnodar_Pashkovsky,
|
||||
URKL=AIRBASE.Caucasus.Krasnodar_Center,
|
||||
URKG=AIRBASE.Caucasus.Gelendzhik,
|
||||
URKN=AIRBASE.Caucasus.Novorossiysk,
|
||||
URKW=AIRBASE.Caucasus.Krymsk,
|
||||
URKA=AIRBASE.Caucasus.Anapa_Vityazevo,
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Runway data.
|
||||
-- @type AIRBASE.Runway
|
||||
-- @field #string name Runway name.
|
||||
@ -875,14 +901,47 @@ end
|
||||
|
||||
--- Find a AIRBASE in the _DATABASE using the name of an existing DCS Airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @param #string AirbaseName The Airbase Name.
|
||||
-- @param #string AirbaseName The name of the airbase. Can also be the ICAO code or the airbase ID.
|
||||
-- @return #AIRBASE self
|
||||
function AIRBASE:FindByName( AirbaseName )
|
||||
|
||||
local AirbaseFound = _DATABASE:FindAirbase( AirbaseName )
|
||||
|
||||
if not AirbaseFound then
|
||||
AirbaseFound=self:FindByICAO(AirbaseName)
|
||||
end
|
||||
|
||||
if not AirbaseFound then
|
||||
AirbaseFound=self:FindByID(AirbaseName)
|
||||
end
|
||||
|
||||
return AirbaseFound
|
||||
end
|
||||
|
||||
|
||||
--- Find an AIRBASE in the _DATABASE using the [International Civil Aviation Organization](https://en.wikipedia.org/wiki/ICAO_airport_code) (ICAO) airport code.
|
||||
-- The code consists of four characters. Typically, the first one or two letters of the ICAO code indicate the country and the remaining letters identify the airport.
|
||||
--
|
||||
-- **NOTE** that the ICAO code cannot be retrieved via the DCS API and has to be hard coded into the MOOSE code. Therefore, it is a rare occasion where
|
||||
-- @param #AIRBASE self
|
||||
-- @param #string AirbaseICAO The Airbase ICAO code.
|
||||
-- @return #AIRBASE self
|
||||
function AIRBASE:FindByICAO( AirbaseICAO )
|
||||
|
||||
if AirbaseICAO then
|
||||
|
||||
local name=AIRBASE.ICAO[AirbaseICAO]
|
||||
|
||||
env.info(string.format("FF ICAO=%s, Name=%s", tostring(AirbaseICAO), tostring(name)))
|
||||
|
||||
local Airbase=self:FindByName(name)
|
||||
return Airbase
|
||||
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Find a AIRBASE in the _DATABASE by its ID.
|
||||
-- @param #AIRBASE self
|
||||
-- @param #number id Airbase ID.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user