This commit is contained in:
Frank 2022-10-27 23:19:35 +02:00
parent 6f82fd7eb6
commit 2840865b83
5 changed files with 352 additions and 60 deletions

View File

@ -59,6 +59,7 @@
-- @field #number Nelements Number of elements (units) assigned to mission.
-- @field #number dTevaluate Time interval in seconds before the mission result is evaluated after mission is over.
-- @field #number Tover Mission abs. time stamp, when mission was over.
-- @field #boolean updateDCSTask If `true`, DCS task is updated at every status update of the assigned groups.
-- @field #table conditionStart Condition(s) that have to be true, before the mission will be started.
-- @field #table conditionSuccess If all conditions are true, the mission is cancelled.
-- @field #table conditionFailure If all conditions are true, the mission is cancelled.
@ -68,7 +69,9 @@
-- @field #number orbitAltitude Orbit altitude in meters.
-- @field #number orbitHeading Orbit heading in degrees.
-- @field #number orbitLeg Length of orbit leg in meters.
-- @field Core.Point#COORDINATE orbitRaceTrack Race-track orbit coordinate.
-- @field DCS#Vec2 orbitOffsetVec2 2D offset vector.
-- @field DCS#Vec2 orbitVec2 2D orbit vector.
-- @field #number orbitDeltaR Distance threshold in meters for moving orbit targets.
--
-- @field Ops.Target#TARGET engageTarget Target data to engage.
--
@ -1020,7 +1023,7 @@ end
--- **[AIR]** Create an ORBIT mission, which can be either a circular orbit or a race-track pattern.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to orbit.
-- @param #number Altitude Orbit altitude in feet. Default is y component of `Coordinate`.
-- @param #number Altitude Orbit altitude in feet above sea level. Default is y component of `Coordinate`.
-- @param #number Speed Orbit speed in knots. Default 350 KIAS.
-- @param #number Heading Heading of race-track pattern in degrees. If not specified, a circular orbit is performed.
-- @param #number Leg Length of race-track in NM. If not specified, a circular orbit is performed.
@ -1028,26 +1031,35 @@ end
function AUFTRAG:NewORBIT(Coordinate, Altitude, Speed, Heading, Leg)
local mission=AUFTRAG:New(AUFTRAG.Type.ORBIT)
-- Altitude.
-- Target.
mission:_TargetFromObject(Coordinate)
-- Set Altitude.
if Altitude then
mission.orbitAltitude=UTILS.FeetToMeters(Altitude)
else
mission.orbitAltitude=Coordinate.y
end
Coordinate.y=mission.orbitAltitude
mission:_TargetFromObject(Coordinate)
mission.orbitSpeed = UTILS.KnotsToMps(Speed or 350) -- the DCS Task itself will shortly be build with this so MPS
-- Orbit speed in m/s.
mission.orbitSpeed = UTILS.KnotsToMps(Speed or 350)
-- Mission speed in km/h.
mission.missionSpeed = UTILS.KnotsToKmph(Speed or 350)
if Heading and Leg then
mission.orbitHeading=Heading
if Leg then
mission.orbitLeg=UTILS.NMToMeters(Leg)
mission.orbitRaceTrack=Coordinate:Translate(mission.orbitLeg, mission.orbitHeading, true)
end
-- Relative heading
if Heading and Heading<0 then
mission.orbitHeadingRel=true
Heading=-Heading
end
-- Heading if given.
mission.orbitHeading=Heading
end
-- Mission options:
mission.missionAltitude=mission.orbitAltitude*0.9
@ -1093,6 +1105,32 @@ function AUFTRAG:NewORBIT_RACETRACK(Coordinate, Altitude, Speed, Heading, Leg)
return mission
end
--- **[AIR]** Create an ORBIT mission, where the aircraft will fly a circular or race-track pattern over a given group or unit.
-- @param #AUFTRAG self
-- @param Wrapper.Group#GROUP Group Group where to orbit around. Can also be a UNIT object.
-- @param #number Altitude Orbit altitude in feet. Default is 7,000 ft.
-- @param #number Speed Orbit speed in knots. Default 350 KIAS.
-- @param #number Leg Length of race-track in NM. Default nil.
-- @param #number Heading Heading of race-track pattern in degrees. Default is heading of the group.
-- @param DCS#Vec2 OffsetVec2 Offset 2D-vector in meters with respect to the group. Default `{x=0, y=0}`, *i.e.* directly overhead.
-- @param #number Distance Threshold distance in meters before orbit pattern is updated. Default 1000 m.
-- @return #AUFTRAG self
function AUFTRAG:NewORBIT_GROUP(Group, Altitude, Speed, Leg, Heading, OffsetVec2, Distance)
Altitude = Altitude or 7000
-- Create orbit mission.
local mission=AUFTRAG:NewORBIT(Group, Altitude, Speed, Heading, Leg)
mission.updateDCSTask=true
mission.orbitOffsetVec2=OffsetVec2 or {x=0, y=0}
mission.orbitDeltaR=1000
return mission
end
--- **[AIR]** Create a Ground Controlled CAP (GCICAP) mission. Flights with this task are considered for A2A INTERCEPT missions by the CHIEF class. They will perform a compat air patrol but not engage by
-- themselfs. They wait for the CHIEF to tell them whom to engage.
-- @param #AUFTRAG self
@ -4970,6 +5008,17 @@ function AUFTRAG:GetTargetCoordinate()
return nil
end
--- Get heading of target.
-- @param #AUFTRAG self
-- @return #number Heading of target in degrees.
function AUFTRAG:GetTargetHeading()
if self.engageTarget then
local heading=self.engageTarget:GetHeading()
return heading
end
return nil
end
--- Get name of the target.
-- @param #AUFTRAG self
-- @return #string Name of the target or "N/A".
@ -5235,6 +5284,17 @@ function AUFTRAG:_SetLogID()
return self
end
--- Update DCS task.
-- @param #AUFTRAG self
-- @return #AUFTRAG self
function AUFTRAG:_UpdateTask()
return self
end
--- Update mission F10 map marker.
-- @param #AUFTRAG self
-- @return #AUFTRAG self
@ -5892,11 +5952,67 @@ function AUFTRAG:GetDCSMissionTask()
-- ORBIT Mission --
-------------------
local Coordinate=self:GetTargetCoordinate()
local DCStask=CONTROLLABLE.TaskOrbit(nil, Coordinate, self.orbitAltitude, self.orbitSpeed, self.orbitRaceTrack)
table.insert(DCStasks, DCStask)
-- Get/update orbit vector.
self.orbitVec2=self:GetTargetVec2()
if self.orbitVec2 then
-- Check for race-track pattern.
local orbitRaceTrack=nil --DCS#Vec2
if self.orbitLeg then
-- Default heading is due North.
local heading=0
-- Check if specific heading was specified.
if self.orbitHeading then
-- Is heading realtive to target?
if self.orbitHeadingRel then
-- Get heading of target.
local hdg=self:GetTargetHeading()
-- Relative heading wrt target.
heading=hdg+self.orbitHeading
else
-- Take given heading.
heading=self.orbitHeading
end
else
-- Not specific heading specified ==> Take heading of target.
heading=self:GetTargetHeading() or 0
end
-- Race-track vector.
orbitRaceTrack=UTILS.Vec2Translate(self.orbitVec2, self.orbitLeg, heading)
-- Debug show arrow.
COORDINATE:NewFromVec2(self.orbitVec2):ArrowToAll(COORDINATE:NewFromVec2(orbitRaceTrack))
end
local OffsetVec2=self.orbitOffsetVec2 and UTILS.DeepCopy(self.orbitOffsetVec2) or nil
if OffsetVec2 then
env.info("FF 1000")
OffsetVec2.x=self.orbitOffsetVec2.r and self.orbitOffsetVec2.r*math.cos(math.rad(self.orbitOffsetVec2.phi) or 0) or self.orbitOffsetVec2.x
OffsetVec2.y=self.orbitOffsetVec2.r and self.orbitOffsetVec2.r*math.sin(math.rad(self.orbitOffsetVec2.phi) or 0) or self.orbitOffsetVec2.y
end
-- Actual orbit position with possible offset.
local orbitVec2=OffsetVec2 and UTILS.Vec2Add(self.orbitVec2, OffsetVec2) or self.orbitVec2
-- Debug
local coord=COORDINATE:NewFromVec2(self.orbitVec2):MarkToAll("Orbit Center")
-- Create orbit task.
local DCStask=CONTROLLABLE.TaskOrbit(nil, orbitVec2, self.orbitAltitude, self.orbitSpeed, orbitRaceTrack)
-- Add DCS task.
table.insert(DCStasks, DCStask)
end
end
@ -6083,6 +6199,8 @@ function AUFTRAG.CheckMissionCapabilityAll(MissionTypes, Capabilities)
return res
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -899,6 +899,43 @@ function FLIGHTGROUP:Status()
end
end
-- Get current mission (if any).
local mission=self:GetMissionCurrent()
-- If mission, check if DCS task needs to be updated.
if mission and mission.updateDCSTask then
-- Orbit missions might need updates.
if mission:GetType()==AUFTRAG.Type.ORBIT and mission.orbitVec2 then
-- Get 2D vector of orbit target.
local vec2=mission:GetTargetVec2()
-- Distance to previous position.
local dist=UTILS.VecDist2D(vec2, mission.orbitVec2)
-- Debug info.
self:I(self.lid..string.format("FF Checking orbit mission dist=%d meters", dist))
-- Check if distance is larger than threshold.
if dist>mission.orbitDeltaR then
-- Update DCS task. This also sets the new mission.orbitVec2.
local DCSTask=mission:GetDCSMissionTask() --DCS#Task
-- Get task.
local Task=self:GetTaskByID(mission.auftragsnummer)
-- Reset current orbit task.
self.controller:resetTask()
-- Push task after one second. We need to give resetTask some time or it will not work!
self:_SandwitchDCSTask(DCSTask, Task, false, 1)
end
end
end
-- TODO: _CheckParking() function

View File

@ -4070,6 +4070,23 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Get mission of this task (if any).
local Mission=self:GetMissionByTaskID(self.taskcurrent)
self:_UpdateTask(Task, Mission)
-- Set AUFTRAG status.
if Mission then
self:MissionExecute(Mission)
end
end
--- Push task
-- @param #OPSGROUP self
-- @param Ops.OpsGroup#OPSGROUP.Task Task The task.
function OPSGROUP:_UpdateTask(Task, Mission)
local Mission=Mission or self:GetMissionByTaskID(self.taskcurrent)
if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
-- Set of group(s) to follow Mother.
@ -4434,39 +4451,8 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
---
DCSTask=Task.dcstask
end
local DCStasks={}
if DCSTask.id=='ComboTask' then
-- Loop over all combo tasks.
for TaskID, Task in ipairs(DCSTask.params.tasks) do
table.insert(DCStasks, Task)
end
else
table.insert(DCStasks, DCSTask)
end
-- Combo task.
local TaskCombo=self.group:TaskCombo(DCStasks)
-- Stop condition!
local TaskCondition=self.group:TaskCondition(nil, Task.stopflag:GetName(), 1, nil, Task.duration)
-- Controlled task.
local TaskControlled=self.group:TaskControlled(TaskCombo, TaskCondition)
-- Task done.
local TaskDone=self.group:TaskFunction("OPSGROUP._TaskDone", self, Task)
-- Final task.
local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone})
-- Set task for group.
-- NOTE: I am pushing the task instead of setting it as it seems to keep the mission task alive.
-- There were issues that flights did not proceed to a later waypoint because the task did not finish until the fired missiles
-- impacted (took rather long). Then the flight flew to the nearest airbase and one lost completely the control over the group.
self:PushTask(TaskFinal)
--self:SetTask(TaskFinal)
self:_SandwitchDCSTask(DCSTask, Task)
elseif Task.type==OPSGROUP.TaskType.WAYPOINT then
-- Waypoint tasks are executed elsewhere!
@ -4475,15 +4461,62 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
end
end
end
--- Sandwitch DCS task in stop condition and push the task to the group.
-- @param #OPSGROUP self
-- @param DCS#Task DCSTask The DCS task.
-- @param Ops.OpsGroup#OPSGROUP.Task Task
-- @param #boolean SetTask Set task instead of pushing it.
-- @param #number Delay Delay in seconds. Default nil.
function OPSGROUP:_SandwitchDCSTask(DCSTask, Task, SetTask, Delay)
-- Set AUFTRAG status.
if Mission then
self:MissionExecute(Mission)
if Delay and Delay>0 then
-- Delayed call.
self:ScheduleOnce(Delay, OPSGROUP._SandwitchDCSTask, self, DCSTask, Task, SetTask)
else
local DCStasks={}
if DCSTask.id=='ComboTask' then
-- Loop over all combo tasks.
for TaskID, Task in ipairs(DCSTask.params.tasks) do
table.insert(DCStasks, Task)
end
else
table.insert(DCStasks, DCSTask)
end
-- Combo task.
local TaskCombo=self.group:TaskCombo(DCStasks)
-- Stop condition!
local TaskCondition=self.group:TaskCondition(nil, Task.stopflag:GetName(), 1, nil, Task.duration)
-- Controlled task.
local TaskControlled=self.group:TaskControlled(TaskCombo, TaskCondition)
-- Task done.
local TaskDone=self.group:TaskFunction("OPSGROUP._TaskDone", self, Task)
-- Final task.
local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone})
-- Set task for group.
-- NOTE: I am pushing the task instead of setting it as it seems to keep the mission task alive.
-- There were issues that flights did not proceed to a later waypoint because the task did not finish until the fired missiles
-- impacted (took rather long). Then the flight flew to the nearest airbase and one lost completely the control over the group.
if SetTask then
self:SetTask(TaskFinal)
else
self:PushTask(TaskFinal)
end
end
end
--- On after "TaskCancel" event. Cancels the current task or simply sets the status to DONE if the task is not the current one.
-- @param #OPSGROUP self
-- @param #string From From state.

View File

@ -1019,7 +1019,7 @@ function TARGET:GetTargetLife(Target)
end
--- Get current life points.
--- Get current total life points. This is the sum of all target objects.
-- @param #TARGET self
-- @return #number Life points of target.
function TARGET:GetLife()
@ -1221,6 +1221,89 @@ function TARGET:GetTargetVec3(Target, Average)
self:E(self.lid.."ERROR: Unknown TARGET type! Cannot get Vec3")
end
--- Get heading of the target.
-- @param #TARGET self
-- @param #TARGET.Object Target Target object.
-- @return #number Heading in degrees.
function TARGET:GetTargetHeading(Target)
if Target.Type==TARGET.ObjectType.GROUP then
local object=Target.Object --Wrapper.Group#GROUP
if object and object:IsAlive() then
local heading=object:GetHeading()
if heading then
return heading
else
return nil
end
else
return nil
end
elseif Target.Type==TARGET.ObjectType.UNIT then
local object=Target.Object --Wrapper.Unit#UNIT
if object and object:IsAlive() then
local heading=object:GetHeading()
return heading
else
return nil
end
elseif Target.Type==TARGET.ObjectType.STATIC then
local object=Target.Object --Wrapper.Static#STATIC
if object and object:IsAlive() then
local heading=object:GetHeading()
return heading
else
return nil
end
elseif Target.Type==TARGET.ObjectType.SCENERY then
local object=Target.Object --Wrapper.Scenery#SCENERY
if object then
local heading=object:GetHeading()
return heading
else
return nil
end
elseif Target.Type==TARGET.ObjectType.AIRBASE then
local object=Target.Object --Wrapper.Airbase#AIRBASE
-- Airbase has no real heading. Return 0. Maybe take the runway heading?
return 0
elseif Target.Type==TARGET.ObjectType.COORDINATE then
local object=Target.Object --Core.Point#COORDINATE
-- A coordinate has no heading. Return 0.
return 0
elseif Target.Type==TARGET.ObjectType.ZONE then
local object=Target.Object --Core.Zone#ZONE
-- A zone has no heading. Return 0.
return 0
end
self:E(self.lid.."ERROR: Unknown TARGET type! Cannot get heading")
end
--- Get target coordinate.
-- @param #TARGET self
@ -1378,7 +1461,7 @@ function TARGET:GetAverageCoordinate()
for _,_target in pairs(self.targets) do
local Target=_target --#TARGET.Object
local coordinate=self:GetTargetCoordinate(Target,true)
local coordinate=self:GetTargetCoordinate(Target, true)
if coordinate then
return coordinate
@ -1390,6 +1473,26 @@ function TARGET:GetAverageCoordinate()
return nil
end
--- Get heading of target.
-- @param #TARGET self
-- @return #number Heading of the target in degrees.
function TARGET:GetHeading()
for _,_target in pairs(self.targets) do
local Target=_target --#TARGET.Object
local heading=self:GetTargetHeading(Target)
if heading then
return heading
end
end
self:E(self.lid..string.format("ERROR: Cannot get heading of target %s", tostring(self.name)))
return nil
end
--- Get category.
-- @param #TARGET self
-- @return #string Target category. See `TARGET.Category.X`, where `X=AIRCRAFT, GROUND`.
@ -1397,6 +1500,7 @@ function TARGET:GetCategory()
return self.category
end
--- Get target category.
-- @param #TARGET self
-- @param #TARGET.Object Target Target object.

View File

@ -1259,7 +1259,7 @@ end
--- (AIR) Orbit at a position with at a given altitude and speed. Optionally, a race track pattern can be specified.
-- @param #CONTROLLABLE self
-- @param Core.Point#COORDINATE Coord Coordinate at which the CONTROLLABLE orbits.
-- @param Core.Point#COORDINATE Coord Coordinate at which the CONTROLLABLE orbits. Can also be given as a `DCS#Vec3` or `DCS#Vec2` object.
-- @param #number Altitude Altitude in meters of the orbit pattern. Default y component of Coord.
-- @param #number Speed Speed [m/s] flying the orbit pattern. Default 128 m/s = 250 knots.
-- @param Core.Point#COORDINATE CoordRaceTrack (Optional) If this coordinate is specified, the CONTROLLABLE will fly a race-track pattern using this and the initial coordinate.
@ -1268,11 +1268,11 @@ function CONTROLLABLE:TaskOrbit( Coord, Altitude, Speed, CoordRaceTrack )
local Pattern = AI.Task.OrbitPattern.CIRCLE
local P1 = Coord:GetVec2()
local P1 = {x=Coord.x, y=Coord.z or Coord.y}
local P2 = nil
if CoordRaceTrack then
Pattern = AI.Task.OrbitPattern.RACE_TRACK
P2 = CoordRaceTrack:GetVec2()
P2 = {x=CoordRaceTrack.x, y=CoordRaceTrack.z or CoordRaceTrack.y}
end
local Task = {