Enhanced Groups

This commit is contained in:
Frank 2020-07-30 01:08:25 +02:00
parent 2f6d9b640f
commit 0d42b12658
4 changed files with 352 additions and 274 deletions

View File

@ -458,27 +458,25 @@ end
-- @param #string To To state. -- @param #string To To state.
-- @param Core.Point#COORDINATE Coordinate Coordinate where to go. -- @param Core.Point#COORDINATE Coordinate Coordinate where to go.
-- @param #number Speed Speed in knots. Default cruise speed. -- @param #number Speed Speed in knots. Default cruise speed.
-- @param #number Formation Formation the group will use. -- @param #number Formation Formation of the group.
-- @param #number ResumeRoute If true, resume route after detour point was reached. -- @param #number ResumeRoute If true, resume route after detour point was reached. If false, the group will stop at the detour point and wait for futher commands.
function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation, ResumeRoute) function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation, ResumeRoute)
-- Waypoints. -- Speed in knots.
local waypoints={} Speed=Speed or self:GetSpeedCruise()
-- Get current speed in km/h. -- ID of current waypoint.
local speed=Speed and UTILS.KnotsToKmph(Speed) or self.group:GetVelocityKMH() local uid=self:GetWaypointCurrent().uid
-- Current waypoint. -- Add waypoint after current.
local current=self:GetCoordinate():WaypointGround(Speed, Formation) local wp=self:AddWaypoint(Coordinate, Speed, uid, Formation, true)
table.insert(waypoints, current)
-- At each waypoint report passing. -- Set if we want to resume route after reaching the detour waypoint.
local Task=self.group:TaskFunction("ARMYGROUP._DetourReached", self, ResumeRoute) if ResumeRoute then
wp.detour=1
local detour=Coordinate:WaypointGround(Speed, Formation, {Task}) else
table.insert(waypoints, detour) wp.detour=0
end
self:Route(waypoints)
end end
@ -491,25 +489,6 @@ function ARMYGROUP:onafterDetourReached(From, Event, To)
self:I(self.lid.."Group reached detour coordinate.") self:I(self.lid.."Group reached detour coordinate.")
end end
--- Function called when a group is passing a waypoint.
--@param Wrapper.Group#GROUP group Group that passed the waypoint
--@param #ARMYGROUP armygroup Army group object.
--@param #boolean resume Resume route.
function ARMYGROUP._DetourReached(group, armygroup, resume)
-- Debug message.
local text=string.format("Group reached detour coordinate")
armygroup:I(armygroup.lid..text)
if resume then
local indx=armygroup:GetWaypointIndexNext(true)
local speed=armygroup:GetSpeedToWaypoint(indx)
armygroup:__UpdateRoute(-1, indx, speed, armygroup.formation)
end
armygroup:DetourReached()
end
--- On after "FullStop" event. --- On after "FullStop" event.
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
@ -684,29 +663,36 @@ end
--- Add an a waypoint to the route. --- Add an a waypoint to the route.
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
-- @param Core.Point#COORDINATE coordinate The coordinate of the waypoint. Use COORDINATE:SetAltitude(altitude) to define the altitude. -- @param Core.Point#COORDINATE Coordinate The coordinate of the waypoint. Use COORDINATE:SetAltitude(altitude) to define the altitude.
-- @param #number speed Speed in knots. Default is default cruise speed or 70% of max speed. -- @param #number Speed Speed in knots. Default is default cruise speed or 70% of max speed.
-- @param #number wpnumber Waypoint number. Default at the end. -- @param #number AfterWaypointWithID Insert waypoint after waypoint given ID. Default is to insert as last waypoint.
-- @param #number formation Formation the group will use. -- @param #number Formation Formation the group will use.
-- @param #boolean updateroute If true or nil, call UpdateRoute. If false, no call. -- @param #boolean Updateroute If true or nil, call UpdateRoute. If false, no call.
-- @return #number Waypoint index. -- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table.
function ARMYGROUP:AddWaypoint(coordinate, speed, wpnumber, formation, updateroute) function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation, Updateroute)
-- Waypoint number. Default is at the end. -- Set waypoint index.
wpnumber=wpnumber or #self.waypoints+1 local wpnumber=#self.waypoints+1
if wpnumber then
local index=self:GetWaypointIndex(AfterWaypointWithID)
if index then
wpnumber=index+1
end
end
-- Check if final waypoint is still passed.
if wpnumber>self.currentwp then if wpnumber>self.currentwp then
self.passedfinalwp=false self.passedfinalwp=false
end end
-- Speed in knots. -- Speed in knots.
speed=speed or self:GetSpeedCruise() Speed=Speed or self:GetSpeedCruise()
-- Speed at waypoint. -- Speed at waypoint.
local speedkmh=UTILS.KnotsToKmph(speed) local speedkmh=UTILS.KnotsToKmph(Speed)
-- Create a Naval waypoint. -- Create a Naval waypoint.
local wp=coordinate:WaypointGround(speedkmh, formation) local wp=Coordinate:WaypointGround(speedkmh, Formation)
-- Create waypoint data table. -- Create waypoint data table.
local waypoint=self:_CreateWaypoint(wp) local waypoint=self:_CreateWaypoint(wp)
@ -715,15 +701,15 @@ function ARMYGROUP:AddWaypoint(coordinate, speed, wpnumber, formation, updaterou
self:_AddWaypoint(waypoint, wpnumber) self:_AddWaypoint(waypoint, wpnumber)
-- Debug info. -- Debug info.
self:T(self.lid..string.format("Adding GROUND waypoint #%d, speed=%.1f knots. Last waypoint passed was #%s. Total waypoints #%d", wpnumber, speed, self.currentwp, #self.waypoints)) self:T(self.lid..string.format("Adding GROUND waypoint #%d, speed=%.1f knots. Last waypoint passed was #%s. Total waypoints #%d", wpnumber, Speed, self.currentwp, #self.waypoints))
-- Update route. -- Update route.
if updateroute==nil or updateroute==true then if Updateroute==nil or Updateroute==true then
self:_CheckGroupDone(1) self:_CheckGroupDone(1)
end end
return wpnumber return waypoint
end end
--- Initialize group parameters. Also initializes waypoints if self.waypoints is nil. --- Initialize group parameters. Also initializes waypoints if self.waypoints is nil.
@ -822,7 +808,7 @@ function ARMYGROUP:_InitGroup()
--text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn)) --text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn))
--text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles) --text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState()) text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self.group:IsAlive())) text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated())) text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
self:I(self.lid..text) self:I(self.lid..text)
@ -838,49 +824,6 @@ end
-- Misc Functions -- Misc Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Check if group is done, i.e.
--
-- * passed the final waypoint,
-- * no current task
-- * no current mission
-- * number of remaining tasks is zero
-- * number of remaining missions is zero
--
-- @param #ARMYGROUP self
-- @param #number delay Delay in seconds.
function ARMYGROUP:_CheckGroupDone(delay)
if self:IsAlive() and self.ai then
if delay and delay>0 then
-- Delayed call.
self:ScheduleOnce(delay, ARMYGROUP._CheckGroupDone, self)
else
if self.passedfinalwp then
if #self.waypoints>1 and self.adinfinitum then
local speed=self:GetSpeedToWaypoint(1)
-- Start route at first waypoint.
self:__UpdateRoute(-1, 1, speed, self.formation)
end
else
self:UpdateRoute(nil, nil, self.formation)
end
end
end
end
--- Get default cruise speed. --- Get default cruise speed.
-- @param #ARMYGROUP self -- @param #ARMYGROUP self
-- @return #number Cruise speed (>0) in knots. -- @return #number Cruise speed (>0) in knots.
@ -888,21 +831,6 @@ function ARMYGROUP:GetSpeedCruise()
return UTILS.KmphToKnots(self.speedCruise or self.speedmax*0.7) return UTILS.KmphToKnots(self.speedCruise or self.speedmax*0.7)
end end
--- Returns a non-zero speed to the next waypoint (even if the waypoint speed is zero).
-- @param #ARMYGROUP self
-- @param #number indx Waypoint index.
-- @return #number Speed to next waypoint (>0) in knots.
function ARMYGROUP:GetSpeedToWaypoint(indx)
local speed=self:GetWaypointSpeed(indx)
if speed<=0.1 then
speed=self:GetSpeedCruise()
end
return speed
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -1778,7 +1778,6 @@ function FLIGHTGROUP:_CheckGroupDone(delay)
return return
end end
-- Number of tasks remaining. -- Number of tasks remaining.
local nTasks=self:CountRemainingTasks() local nTasks=self:CountRemainingTasks()

View File

@ -93,6 +93,7 @@ function NAVYGROUP:New(GroupName)
-- Defaults -- Defaults
self:SetDefaultROE() self:SetDefaultROE()
self:SetDefaultAlarmstate()
self:SetDetection() self:SetDetection()
self:SetPatrolAdInfinitum(true) self:SetPatrolAdInfinitum(true)
@ -419,10 +420,22 @@ function NAVYGROUP:onafterStatus(From, Event, To)
local nMissions=self:CountRemainingMissison() local nMissions=self:CountRemainingMissison()
local intowind=self:IsSteamingIntoWind() and UTILS.SecondsToClock(self.intowind.Tstop-timer.getAbsTime(), true) or "N/A" local intowind=self:IsSteamingIntoWind() and UTILS.SecondsToClock(self.intowind.Tstop-timer.getAbsTime(), true) or "N/A"
local turning=tostring(self:IsTurning())
local alt=pos.y
local speedExpected=UTILS.MpsToKnots(self.speed or 0)
local wpidxCurr=self.currentwp
local wpuidCurr=0
local wpidxNext=self:GetWaypointIndexNext()
local wpuidNext=0
local wpDist=UTILS.MetersToNM(self:GetDistanceToWaypoint())
local wpETA=UTILS.SecondsToClock(self:GetTimeToWaypoint(), true)
local roe=self:GetROE() or 0
local als=self:GetAlarmstate() or 0
-- Info text. -- Info text.
local text=string.format("%s (T=%d,M=%d): Wp=%d-->%d (of %d) Speed=%.1f (%.1f) Depth=%.1f Hdg=%03d Turn=%s Collision=%d IntoWind=%s ROE=%d AS=%d", local text=string.format("%s [ROE=%d,AS=%d, T/M=%d/%d]: Wp=%d[%d]-->%d[%d] (of %d) Dist=%.1f NM ETA=%s - Speed=%.1f (%.1f) kts, Depth=%.1f m, Hdg=%03d, Turn=%s Collision=%d IntoWind=%s",
fsmstate, nTaskTot, nMissions, self.currentwp, self:GetWaypointIndexNext(), #self.waypoints, speed, UTILS.MpsToKnots(self.speed or 0), pos.y, hdg, tostring(self:IsTurning()), freepath, intowind, 0, 0) fsmstate, roe, als, nTaskTot, nMissions, wpidxCurr, wpuidCurr, wpidxNext, wpuidNext, #self.waypoints, wpDist, wpETA, speed, speedExpected, alt, hdg, turning, freepath, intowind)
self:I(self.lid..text) self:I(self.lid..text)
else else
@ -536,16 +549,15 @@ function NAVYGROUP:onafterSpawned(From, Event, To)
if self.ai then if self.ai then
-- Set default ROE and ROT options. -- Set default ROE and Alarmstate options.
self:SetOptionROE(self.roe) self:SetOptionROE(self.roe)
self:SetOptionAlarmstate(self.alarmstate)
end end
-- Get orientation. -- Get orientation.
self.Corientlast=self.group:GetUnit(1):GetOrientationX() self.Corientlast=self.group:GetUnit(1):GetOrientationX()
self.depth=self.group:GetHeight()
-- Update route. -- Update route.
self:Cruise() self:Cruise()
@ -562,7 +574,7 @@ end
function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth) function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth)
-- Update route from this waypoint number onwards. -- Update route from this waypoint number onwards.
n=n or self:GetWaypointIndexNext(self.adinfinitum) n=n or self:GetWaypointIndexNext()
-- Debug info. -- Debug info.
self:T(self.lid..string.format("FF Update route n=%d", n)) self:T(self.lid..string.format("FF Update route n=%d", n))
@ -637,10 +649,11 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth)
else else
--- ---
-- No waypoints left -- No waypoints left ==> Full Stop
--- ---
self:I(self.lid..string.format("No waypoints left")) self:E(self.lid..string.format("WARNING: No waypoints left ==> Full Stop!"))
self:FullStop()
end end
@ -657,19 +670,19 @@ end
-- @param #number ResumeRoute If true, resume route after detour point was reached. If false, the group will stop at the detour point and wait for futher commands. -- @param #number ResumeRoute If true, resume route after detour point was reached. If false, the group will stop at the detour point and wait for futher commands.
function NAVYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Depth, ResumeRoute) function NAVYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Depth, ResumeRoute)
-- Waypoints.
local waypoints={}
-- Depth for submarines. -- Depth for submarines.
local depth=Depth or 0 Depth=Depth or 0
-- Speed in knots. -- Speed in knots.
Speed=Speed or self:GetSpeedCruise() Speed=Speed or self:GetSpeedCruise()
local wpindx=self.currentwp+1 -- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid
local wp=self:AddWaypoint(Coordinate, Speed, wpindx, true) -- Add waypoint after current.
local wp=self:AddWaypoint(Coordinate, Speed, uid, Depth, true)
-- Set if we want to resume route after reaching the detour waypoint.
if ResumeRoute then if ResumeRoute then
wp.detour=1 wp.detour=1
else else
@ -687,26 +700,6 @@ function NAVYGROUP:onafterDetourReached(From, Event, To)
self:I(self.lid.."Group reached detour coordinate.") self:I(self.lid.."Group reached detour coordinate.")
end end
--- Function called when a group is passing a waypoint.
--@param Wrapper.Group#GROUP group Group that passed the waypoint
--@param #NAVYGROUP navygroup Navy group object.
--@param #boolean resume Resume route.
function NAVYGROUP._DetourReached(group, navygroup, resume)
-- Debug message.
local text=string.format("Group reached detour coordinate")
navygroup:I(navygroup.lid..text)
if resume then
local indx=navygroup:GetWaypointIndexNext(true)
local speed=navygroup:GetSpeedToWaypoint(indx)
navygroup:UpdateRoute(indx, speed, navygroup.depth)
end
navygroup:DetourReached()
end
--- On after "TurnIntoWind" event. --- On after "TurnIntoWind" event.
-- @param #NAVYGROUP self -- @param #NAVYGROUP self
-- @param #string From From state. -- @param #string From From state.
@ -740,9 +733,10 @@ function NAVYGROUP:onafterTurnIntoWind(From, Event, To, IntoWind)
local coord=self:GetCoordinate() local coord=self:GetCoordinate()
local Coord=coord:Translate(distance, IntoWind.Heading) local Coord=coord:Translate(distance, IntoWind.Heading)
local wpindex=self.currentwp+1 --self:GetWaypointIndexNext(false) -- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid
local wptiw=self:AddWaypoint(Coord, speed, wpindex, true) local wptiw=self:AddWaypoint(Coord, speed, uid)
wptiw.intowind=true wptiw.intowind=true
IntoWind.waypoint=wptiw IntoWind.waypoint=wptiw
@ -751,14 +745,6 @@ function NAVYGROUP:onafterTurnIntoWind(From, Event, To, IntoWind)
IntoWind.Coordinate:MarkToAll("Return coord") IntoWind.Coordinate:MarkToAll("Return coord")
end end
--[[
local wp={}
wp[1]=coord:WaypointNaval(UTILS.KnotsToKmph(speed))
wp[2]=Coord:WaypointNaval(UTILS.KnotsToKmph(speed))
self:Route(wp)
]]
end end
--- On after "TurnIntoWindOver" event. --- On after "TurnIntoWindOver" event.
@ -816,10 +802,10 @@ end
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param #number Speed Speed in knots until next waypoint is reached. -- @param #number Speed Speed in knots until next waypoint is reached. Default is speed set for waypoint.
function NAVYGROUP:onafterCruise(From, Event, To, Speed) function NAVYGROUP:onafterCruise(From, Event, To, Speed)
-- -- No set depth.
self.depth=nil self.depth=nil
self:__UpdateRoute(-1, nil, Speed) self:__UpdateRoute(-1, nil, Speed)
@ -1001,28 +987,36 @@ end
--- Add an a waypoint to the route. --- Add an a waypoint to the route.
-- @param #NAVYGROUP self -- @param #NAVYGROUP self
-- @param Core.Point#COORDINATE coordinate The coordinate of the waypoint. Use COORDINATE:SetAltitude(altitude) to define the altitude. -- @param Core.Point#COORDINATE Coordinate The coordinate of the waypoint. Use COORDINATE:SetAltitude(altitude) to define the altitude.
-- @param #number speed Speed in knots. Default is default cruise speed or 70% of max speed. -- @param #number Speed Speed in knots. Default is default cruise speed or 70% of max speed.
-- @param #number wpnumber Waypoint number. Default at the end. -- @param #number AfterWaypointWithID Insert waypoint after waypoint given ID. Default is to insert as last waypoint.
-- @param #boolean updateroute If true or nil, call UpdateRoute. If false, no call. -- @param #number Depth Depth at waypoint in meters.
-- @param #boolean Updateroute If true or nil, call UpdateRoute. If false, no call.
-- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table. -- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table.
function NAVYGROUP:AddWaypoint(coordinate, speed, wpnumber, updateroute) function NAVYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Updateroute)
-- Waypoint number. Default is at the end. -- Set waypoint index.
wpnumber=wpnumber or #self.waypoints+1 local wpnumber=#self.waypoints+1
if wpnumber then
local index=self:GetWaypointIndex(AfterWaypointWithID)
if index then
wpnumber=index+1
end
end
-- Check if final waypoint is still passed.
if wpnumber>self.currentwp then if wpnumber>self.currentwp then
self.passedfinalwp=false self.passedfinalwp=false
end end
-- Speed in knots. -- Speed in knots.
speed=speed or self:GetSpeedCruise() Speed=Speed or self:GetSpeedCruise()
-- Speed at waypoint. -- Speed at waypoint.
local speedkmh=UTILS.KnotsToKmph(speed) local speedkmh=UTILS.KnotsToKmph(Speed)
-- Create a Naval waypoint. -- Create a Naval waypoint.
local wp=coordinate:WaypointNaval(speedkmh) local wp=Coordinate:WaypointNaval(speedkmh)
-- Create waypoint data table. -- Create waypoint data table.
local waypoint=self:_CreateWaypoint(wp) local waypoint=self:_CreateWaypoint(wp)
@ -1031,10 +1025,10 @@ function NAVYGROUP:AddWaypoint(coordinate, speed, wpnumber, updateroute)
self:_AddWaypoint(waypoint, wpnumber) self:_AddWaypoint(waypoint, wpnumber)
-- Debug info. -- Debug info.
self:I(self.lid..string.format("Adding NAVAL waypoint index=%d uid=%d, speed=%.1f knots. Last waypoint passed was #%d. Total waypoints #%d", wpnumber, waypoint.uid, speed, self.currentwp, #self.waypoints)) self:I(self.lid..string.format("Adding NAVAL waypoint index=%d uid=%d, speed=%.1f knots. Last waypoint passed was #%d. Total waypoints #%d", wpnumber, waypoint.uid, Speed, self.currentwp, #self.waypoints))
-- Update route. -- Update route.
if updateroute==nil or updateroute==true then if Updateroute==nil or Updateroute==true then
self:_CheckGroupDone(1) self:_CheckGroupDone(1)
end end
@ -1076,8 +1070,8 @@ function NAVYGROUP:_InitGroup()
-- Max speed in km/h. -- Max speed in km/h.
self.speedmax=self.group:GetSpeedMax() self.speedmax=self.group:GetSpeedMax()
-- Cruise speed: 70% of max speed but within limit. -- Cruise speed: 70% of max speed.
--self.speedCruise=self.speedmax*0.7 self.speedCruise=self.speedmax*0.7
-- Group ammo. -- Group ammo.
--self.ammo=self:GetAmmoTot() --self.ammo=self:GetAmmoTot()
@ -1106,6 +1100,7 @@ function NAVYGROUP:_InitGroup()
end end
end end
-- Get all units of the group.
local units=self.group:GetUnits() local units=self.group:GetUnits()
for _,_unit in pairs(units) do for _,_unit in pairs(units) do
@ -1351,58 +1346,18 @@ function NAVYGROUP:_CheckStuck()
local ExpectedSpeed=self:GetExpectedSpeed() local ExpectedSpeed=self:GetExpectedSpeed()
local speed=self.group:GetVelocityMPS() local speed=self:GetVelocity()
if speed<0.5 and ExpectedSpeed>0 then if speed<0.5 and ExpectedSpeed>0 then
if not self.holdtimestamp then if not self.holdtimestamp then
self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f expected=%.1f knots", speed, ExpectedSpeed)) self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected", speed, ExpectedSpeed))
self.holdtimestamp=timer.getTime() self.holdtimestamp=timer.getTime()
end end
end end
end end
--- Check if group is done, i.e.
--
-- * passed the final waypoint,
-- * no current task
-- * no current mission
-- * number of remaining tasks is zero
-- * number of remaining missions is zero
--
-- @param #NAVYGROUP self
-- @param #number delay Delay in seconds.
function NAVYGROUP:_CheckGroupDone(delay)
if self:IsAlive() and self.ai then
if delay and delay>0 then
-- Delayed call.
self:ScheduleOnce(delay, NAVYGROUP._CheckGroupDone, self)
else
if self.passedfinalwp then
if #self.waypoints>1 and self.adinfinitum then
local speed=self:GetSpeedToWaypoint(1)
-- Start route at first waypoint.
self:__UpdateRoute(-1, 1, speed, self.depth)
end
else
self:__UpdateRoute(-1, nil, nil, self.depth)
end
end
end
end
--- Check queued turns into wind. --- Check queued turns into wind.
-- @param #NAVYGROUP self -- @param #NAVYGROUP self
@ -1466,33 +1421,7 @@ function NAVYGROUP:GetSpeedCruise()
return UTILS.KmphToKnots(self.speedCruise or self.speedmax*0.7) return UTILS.KmphToKnots(self.speedCruise or self.speedmax*0.7)
end end
--- Returns a non-zero speed to the next waypoint (even if the waypoint speed is zero).
-- @param #NAVYGROUP self
-- @param #number indx Waypoint index.
-- @return #number Speed to next waypoint (>0) in knots.
function NAVYGROUP:GetSpeedToWaypoint(indx)
local speed=self:GetWaypointSpeed(indx)
if speed<=0.1 then
speed=self:GetSpeedCruise()
end
return speed
end
--- Returns the currently expected speed.
-- @param #NAVYGROUP self
-- @return #number Expected speed in m/s.
function NAVYGROUP:GetExpectedSpeed()
if self:IsHolding() then
return 0
else
return self.speed or 0
end
end
--- Check queued turns into wind. --- Check queued turns into wind.
-- @param #NAVYGROUP self -- @param #NAVYGROUP self
@ -1602,16 +1531,24 @@ function NAVYGROUP:_FindPathToNextWaypoint()
if path then if path then
-- Loop over nodes in found path. -- Loop over nodes in found path.
local uid=self:GetWaypointCurrent().uid -- ID of current waypoint.
for i,_node in ipairs(path) do for i,_node in ipairs(path) do
local node=_node --Core.Astar#ASTAR.Node local node=_node --Core.Astar#ASTAR.Node
-- Waypoint index. -- Waypoint index.
local wpindex=self:GetWaypointIndexCurrent()+i local wpindex=self:GetWaypointIndexCurrent()+i
-- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid
-- Add waypoints along detour path to next waypoint. -- Add waypoints along detour path to next waypoint.
local wp=self:AddWaypoint(node.coordinate, speed, wpindex) local wp=self:AddWaypoint(node.coordinate, speed, uid)
wp.astar=true wp.astar=true
-- Update id so the next wp is added after this one.
uid=wp.uid
-- Debug: smoke and mark path. -- Debug: smoke and mark path.
node.coordinate:MarkToAll(string.format("Path node #%d", i)) node.coordinate:MarkToAll(string.format("Path node #%d", i))

View File

@ -95,9 +95,10 @@
-- --
-- # The OPSGROUP Concept -- # The OPSGROUP Concept
-- --
-- The OPSGROUP class contains common functions used by other classes such as FLIGHGROUP, NAVYGROUP. -- The OPSGROUP class contains common functions used by other classes such as FLIGHGROUP, NAVYGROUP and ARMYGROUP.
-- Those classes inherit everything of this class and extend it with features specific to their unit category.
-- --
-- This class is **not** meant to be used itself by the end user. -- This class is **NOT** meant to be used by the end user itself.
-- --
-- --
-- @field #OPSGROUP -- @field #OPSGROUP
@ -229,7 +230,7 @@ OPSGROUP.TaskType={
--- NavyGroup version. --- NavyGroup version.
-- @field #string version -- @field #string version
OPSGROUP.version="0.1.0" OPSGROUP.version="0.2.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -431,6 +432,18 @@ function OPSGROUP:GetCoordinate()
return nil return nil
end end
--- Get current velocity of the group.
-- @param #OPSGROUP self
-- @return #number Velocity in m/s.
function OPSGROUP:GetVelocity()
if self:IsAlive()~=nil then
return self.group:GetVelocityMPS()
else
self:E(self.lid.."WARNING: Group is not alive. Cannot get velocity!")
end
return nil
end
--- Get current heading of the group. --- Get current heading of the group.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @return #number Current heading of the group in degrees. -- @return #number Current heading of the group in degrees.
@ -690,8 +703,9 @@ end
--- Get coordinate of next waypoint of the group. --- Get coordinate of next waypoint of the group.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @param #boolean cyclic If true, return first waypoint if last waypoint was reached.
-- @return Core.Point#COORDINATE Coordinate of the next waypoint. -- @return Core.Point#COORDINATE Coordinate of the next waypoint.
function OPSGROUP:GetNextWaypointCoordinate() function OPSGROUP:GetNextWaypointCoordinate(cyclic)
-- Get next waypoint -- Get next waypoint
local waypoint=self:GetWaypointNext(cyclic) local waypoint=self:GetWaypointNext(cyclic)
@ -726,6 +740,98 @@ function OPSGROUP:GetWaypointSpeed(indx)
return nil return nil
end end
--- Get unique ID of waypoint.
-- @param #OPSGROUP self
-- @param #number indx Waypoint index.
-- @return #number Unique ID.
function OPSGROUP:GetWaypointID(indx)
local waypoint=self:GetWaypoint(indx)
if waypoint then
return waypoint.uid
end
return nil
end
--- Returns a non-zero speed to the next waypoint (even if the waypoint speed is zero).
-- @param #OPSGROUP self
-- @param #number indx Waypoint index.
-- @return #number Speed to next waypoint (>0) in knots.
function OPSGROUP:GetSpeedToWaypoint(indx)
local speed=self:GetWaypointSpeed(indx)
if speed<=0.1 then
speed=self:GetSpeedCruise()
end
return speed
end
--- Get distance to waypoint.
-- @param #OPSGROUP self
-- @param #number indx Waypoint index. Default is the next waypoint.
-- @return #number Distance in meters.
function OPSGROUP:GetDistanceToWaypoint(indx)
local dist=0
if #self.waypoints>0 then
indx=indx or self:GetWaypointIndexNext()
local wp=self:GetWaypoint(indx)
if wp then
local coord=self:GetCoordinate()
dist=coord:Get2DDistance(wp.coordinate)
end
end
return dist
end
--- Get time to waypoint based on current velocity.
-- @param #OPSGROUP self
-- @param #number indx Waypoint index. Default is the next waypoint.
-- @return #number Time in seconds. If velocity is 0
function OPSGROUP:GetTimeToWaypoint(indx)
local s=self:GetDistanceToWaypoint(indx)
local v=self:GetVelocity()
local t=s/v
if t==math.inf then
return 365*24*60*60
elseif t==math.nan then
return 0
else
return t
end
end
--- Returns the currently expected speed.
-- @param #OPSGROUP self
-- @return #number Expected speed in m/s.
function OPSGROUP:GetExpectedSpeed()
if self:IsHolding() then
return 0
else
return self.speed or 0
end
end
--- Remove a waypoint with a ceratin UID. --- Remove a waypoint with a ceratin UID.
-- @param #OPSGROUP self -- @param #OPSGROUP self
@ -765,7 +871,9 @@ function OPSGROUP:RemoveWaypoint(wpindex)
-- Waypoint was not reached yet. -- Waypoint was not reached yet.
if wpindex > self.currentwp then if wpindex > self.currentwp then
-- Could be that we just removed the only remaining waypoint ==> passedfinalwp=true. ---
-- Removed a FUTURE waypoint
---
-- TODO: patrol adinfinitum. -- TODO: patrol adinfinitum.
@ -773,16 +881,16 @@ function OPSGROUP:RemoveWaypoint(wpindex)
self.passedfinalwp=true self.passedfinalwp=true
end end
env.info("FF passed final waypoint after remove current wp = "..self.currentwp) env.info("FF passed final waypoint after remove! current wp = "..self.currentwp)
self:_CheckGroupDone(1) self:_CheckGroupDone(1)
--elseif wpindex==self.currentwp then
-- Removed the waypoint we just passed.
else else
---
-- Removed a waypoint ALREADY PASSED
---
-- If an already passed waypoint was deleted, we do not need to update the route. -- If an already passed waypoint was deleted, we do not need to update the route.
-- If current wp = 1 it stays 1. Otherwise decrease current wp. -- If current wp = 1 it stays 1. Otherwise decrease current wp.
@ -962,20 +1070,17 @@ end
--- Add a *waypoint* task. --- Add a *waypoint* task.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @param #table task DCS task table structure. -- @param #table task DCS task table structure.
-- @param #number waypointindex Number of waypoint. Counting starts at one! Default is the as *next* waypoint. -- @param #OPSGROUP.Waypoint Waypoint where the task is executed. Default is the at *next* waypoint.
-- @param #string description Brief text describing the task, e.g. "Attack SAM". -- @param #string description Brief text describing the task, e.g. "Attack SAM".
-- @param #number prio Priority of the task. Number between 1 and 100. Default is 50. -- @param #number prio Priority of the task. Number between 1 and 100. Default is 50.
-- @param #number duration Duration before task is cancelled in seconds counted after task started. Default never. -- @param #number duration Duration before task is cancelled in seconds counted after task started. Default never.
-- @return #OPSGROUP.Task The task structure. -- @return #OPSGROUP.Task The task structure.
function OPSGROUP:AddTaskWaypoint(task, waypointindex, description, prio, duration) function OPSGROUP:AddTaskWaypoint(task, Waypoint, description, prio, duration)
-- Index. -- Waypoint of task.
waypointindex=waypointindex or (self.currentwp and self.currentwp+1 or 2) Waypoint=Waypoint or self:GetWaypointNext()
-- Get waypoint if Waypoint then
local waypoint=self:GetWaypointByIndex(waypointindex)
if waypoint then
-- Increase counter. -- Increase counter.
self.taskcounter=self.taskcounter+1 self.taskcounter=self.taskcounter+1
@ -989,7 +1094,7 @@ function OPSGROUP:AddTaskWaypoint(task, waypointindex, description, prio, durati
newtask.id=self.taskcounter newtask.id=self.taskcounter
newtask.duration=duration newtask.duration=duration
newtask.time=0 newtask.time=0
newtask.waypoint=waypoint.uid newtask.waypoint=Waypoint.uid
newtask.type=OPSGROUP.TaskType.WAYPOINT newtask.type=OPSGROUP.TaskType.WAYPOINT
newtask.stopflag=USERFLAG:New(string.format("%s StopTaskFlag %d", self.groupname, newtask.id)) newtask.stopflag=USERFLAG:New(string.format("%s StopTaskFlag %d", self.groupname, newtask.id))
newtask.stopflag:Set(0) newtask.stopflag:Set(0)
@ -1002,7 +1107,6 @@ function OPSGROUP:AddTaskWaypoint(task, waypointindex, description, prio, durati
self:T3({newtask=newtask}) self:T3({newtask=newtask})
-- Update route. -- Update route.
--self:_CheckGroupDone(1)
self:__UpdateRoute(-1) self:__UpdateRoute(-1)
return newtask return newtask
@ -1807,8 +1911,8 @@ function OPSGROUP:RouteToMission(mission, delay)
self:ScheduleOnce(delay, OPSGROUP.RouteToMission, self, mission) self:ScheduleOnce(delay, OPSGROUP.RouteToMission, self, mission)
else else
-- Next waypoint. -- ID of current waypoint.
local nextwaypoint=self.currentwp+1 local uid=self:GetWaypointCurrent().uid
-- Get coordinate where the mission is executed. -- Get coordinate where the mission is executed.
local waypointcoord=mission:GetMissionWaypointCoord(self.group) local waypointcoord=mission:GetMissionWaypointCoord(self.group)
@ -1818,8 +1922,11 @@ function OPSGROUP:RouteToMission(mission, delay)
self:AddTaskEnroute(task) self:AddTaskEnroute(task)
end end
-- Speed to mission waypoint.
local SpeedToMission=UTILS.KmphToKnots(self.speedCruise)
-- Add waypoint. -- Add waypoint.
local waypoint=self:AddWaypoint(waypointcoord, UTILS.KmphToKnots(self.speedCruise), nextwaypoint, false) local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, nil, false)
-- Special for Troop transport. -- Special for Troop transport.
if mission.type==AUFTRAG.Type.TROOPTRANSPORT then if mission.type==AUFTRAG.Type.TROOPTRANSPORT then
@ -1841,7 +1948,7 @@ function OPSGROUP:RouteToMission(mission, delay)
end end
-- Add waypoint task. UpdateRoute is called inside. -- Add waypoint task. UpdateRoute is called inside.
local waypointtask=self:AddTaskWaypoint(mission.DCStask, nextwaypoint, mission.name, mission.prio, mission.duration) local waypointtask=self:AddTaskWaypoint(mission.DCStask, waypoint, mission.name, mission.prio, mission.duration)
-- Set waypoint task. -- Set waypoint task.
mission:SetGroupWaypointTask(self, waypointtask) mission:SetGroupWaypointTask(self, waypointtask)
@ -2126,6 +2233,10 @@ function OPSGROUP:onafterCheckZone(From, Event, To)
end end
end end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Internal Check Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Check if group is in zones. --- Check if group is in zones.
-- @param #OPSGROUP self -- @param #OPSGROUP self
function OPSGROUP:_CheckInZones() function OPSGROUP:_CheckInZones()
@ -2248,6 +2359,106 @@ function OPSGROUP:_CheckDetectedUnits()
end end
--- Check if passed the final waypoint and, if necessary, update route.
-- @param #OPSGROUP self
-- @param #number delay Delay in seconds.
function OPSGROUP:_CheckGroupDone(delay)
if self:IsAlive() and self.ai then
if delay and delay>0 then
-- Delayed call.
self:ScheduleOnce(delay, self._CheckGroupDone, self)
else
if self.passedfinalwp then
---
-- Passed FINAL waypoint
---
if #self.waypoints>1 then
if self.adinfinitum then
-- Get positive speed to first waypoint.
local speed=self:GetSpeedToWaypoint(1)
-- Start route at first waypoint.
self:__UpdateRoute(-1, 1, speed)
self:I(self.lid..string.format("Passed final WP, #WP>1, adinfinitum=TRUE ==> Goto WP 1 at speed>0"))
self.passedfinalwp=false
else
-- No further waypoints. Command a full stop.
self:__FullStop(-1)
self:I(self.lid..string.format("Passed final WP, #WP>1, adinfinitum=FALSE ==> Full Stop"))
end
elseif #self.waypoints==1 then
--- Only one WP left
-- The last waypoint.
local waypoint=self.waypoints[1] --Ops.OpsGroup#OPSGROUP.Waypoint
local dist=self:GetCoordinate():Get2DDistance(waypoint.coordinate)
if self.adinfinitum and dist>1000 then -- Note that dist>100 caused the same wp to be passed a lot of times.
self:I(self.lid..string.format("Passed final WP, #WP=1, adinfinitum=TRUE dist>1000 ==> Goto WP 1 at speed>0"))
-- Get positive speed to first waypoint.
local speed=self:GetSpeedToWaypoint(1)
-- Start route at first waypoint.
self:__UpdateRoute(-1, 1, speed)
self.passedfinalwp=false
else
self:I(self.lid..string.format("Passed final WP, #WP=1, adinfinitum=FALSE or dist<1000 ==> Full Stop"))
self:__FullStop(-1)
end
else
--- No waypoints left
-- No further waypoints. Command a full stop.
self:__FullStop(-1)
end
else
---
-- Final waypoint NOT passed yet
---
if #self.waypoints>0 then
self:I(self.lid..string.format("NOT Passed final WP, #WP>0 ==> Update Route"))
self:__UpdateRoute(-1)
else
self:E(self.lid..string.format("WARNING: No waypoints left! Commanding a Full Stop"))
self:__FullStop(-1)
end
end
end
end
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Waypoints & Routing -- Waypoints & Routing
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -2261,11 +2472,11 @@ function OPSGROUP:_CreateWaypoint(waypoint, formation, detour)
waypoint.uid=self.wpcounter waypoint.uid=self.wpcounter
waypoint.coordinate=COORDINATE:New(waypoint.x, waypoint.alt, waypoint.y) waypoint.coordinate=COORDINATE:New(waypoint.x, waypoint.alt, waypoint.y)
waypoint.detour=detour and detour or false waypoint.detour=detour and detour or false
waypoint.formation=formation
if formation then if formation then
waypoint.action=formation waypoint.action=formation
end end
waypoint.onroad=onroad and onroad or false waypoint.npassed=0
waypoint.patrol=false
self.wpcounter=self.wpcounter+1 self.wpcounter=self.wpcounter+1
@ -2412,6 +2623,9 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid)
-- Get the current waypoint index. -- Get the current waypoint index.
opsgroup.currentwp=opsgroup:GetWaypointIndex(uid) opsgroup.currentwp=opsgroup:GetWaypointIndex(uid)
-- Increase passing counter.
waypoint.npassed=waypoint.npassed+1
-- Set expected speed and formation from the next WP. -- Set expected speed and formation from the next WP.
local wpnext=opsgroup:GetWaypointNext() local wpnext=opsgroup:GetWaypointNext()
if wpnext then if wpnext then