From ad0b32c0ee1a8275a0e97a960af8587da612ebbd Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 3 Sep 2021 00:05:58 +0200 Subject: [PATCH] OPS - Found and fixed bugs for ARMY and NAVY groups, which caused only one waypoint to be processed - Added Duration for AUFTRAG - Fixed bug in auftrag if no legion was assigned and mission was canceled at opsgroup level - Trying (again) to include the whole route for ARMY and NAVY when UpdateRoute - Simpler task function for passing waypoint STILL a lot to do/check! --- Moose Development/Moose/Ops/ArmyGroup.lua | 104 ++++++++++++---------- Moose Development/Moose/Ops/Auftrag.lua | 30 ++++++- Moose Development/Moose/Ops/NavyGroup.lua | 72 ++++++++------- Moose Development/Moose/Ops/OpsGroup.lua | 40 +++++++-- 4 files changed, 157 insertions(+), 89 deletions(-) diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index 3adde055d..f30287d80 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -190,7 +190,8 @@ end -- @param #ARMYGROUP self -- @return Core.Point#COORDINATE Coordinate of a road closest to the group. function ARMYGROUP:GetClosestRoad() - return self:GetCoordinate():GetClosestPointToRoad() + local coord=self:GetCoordinate():GetClosestPointToRoad() + return coord end --- Get 2D distance to the closest road. @@ -568,12 +569,13 @@ function ARMYGROUP:onafterSpawned(From, Event, To) -- Formation if not self.option.Formation then - self.option.Formation=self.optionDefault.Formation + -- Will be set in update route. + --self.option.Formation=self.optionDefault.Formation end -- Update route. if #self.waypoints>1 then - self:Cruise(nil, self.option.Formation or self.optionDefault.Formation) + self:Cruise(nil, self.option.Formation) else self:FullStop() end @@ -624,72 +626,76 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation) -- Update route from this waypoint number onwards. n=n or self:GetWaypointIndexNext(self.adinfinitum) - -- Update waypoint tasks, i.e. inject WP tasks into waypoint table. - self:_UpdateWaypointTasks(n) - + -- Update waypoint tasks, i.e. inject WP tasks into waypoint table. OBSOLETE! + --self:_UpdateWaypointTasks(n) + -- Waypoints. local waypoints={} - -- Next waypoint. - local wp=UTILS.DeepCopy(self.waypoints[n]) --Ops.OpsGroup#OPSGROUP.Waypoint + local formationlast=nil + for i=n, #self.waypoints do - -- Do we want to drive on road to the next wp? - local onroad=wp.action==ENUMS.Formation.Vehicle.OnRoad - - -- Speed. - if Speed then - wp.speed=UTILS.KnotsToMps(Speed) - else - -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum. - if wp.speed<0.1 then --self.adinfinitum and - wp.speed=UTILS.KmphToMps(self.speedCruise) + -- Next waypoint. + local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint + + -- Speed. + if Speed then + wp.speed=UTILS.KnotsToMps(Speed) + else + -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum. + if wp.speed<0.1 then --self.adinfinitum and + wp.speed=UTILS.KmphToMps(self.speedCruise) + end end + + -- Formation. + if self.formationPerma then + wp.action=self.formationPerma + elseif Formation then + wp.action=Formation + end + + -- Add waypoint in between because this waypoint is "On Road" but lies "Off Road". + if wp.action==ENUMS.Formation.Vehicle.OnRoad and wp.roaddist>10 then + + -- The real waypoint is actually off road. + wp.action=ENUMS.Formation.Vehicle.OffRoad + + -- Add "On Road" waypoint in between. + local wproad=wp.roadcoord:WaypointGround(wp.speed, ENUMS.Formation.Vehicle.OnRoad) --Ops.OpsGroup#OPSGROUP.Waypoint + + -- Insert road waypoint. + table.insert(waypoints, wproad) + end + + -- Add waypoint. + table.insert(waypoints, wp) + + -- Last formation. + formationlast=wp.action end - -- Formation. - if self.formationPerma then - wp.action=self.formationPerma - elseif Formation then - wp.action=Formation - end + -- First (next wp). + local wp=waypoints[1] --Ops.OpsGroup#OPSGROUP.Waypoint -- Current set formation. self.option.Formation=wp.action - - -- Current set speed in m/s. - self.speedWp=wp.speed - - -- Add waypoint in between because this waypoint is "On Road" but lies "Off Road". - if onroad then - - -- The real waypoint is actually off road. - wp.action=ENUMS.Formation.Vehicle.OffRoad - - -- Add "On Road" waypoint in between. - local wproad=wp.roadcoord:WaypointGround(wp.speed, ENUMS.Formation.Vehicle.OnRoad) --Ops.OpsGroup#OPSGROUP.Waypoint - -- Insert road waypoint. - table.insert(waypoints, wproad) - end - - -- Add waypoint. - table.insert(waypoints, wp) + -- Current set speed in m/s. + self.speedWp=wp.speed - -- Apply formation at the current position or it will only be changed when reaching the next waypoint. - local formation=ENUMS.Formation.Vehicle.OffRoad - if wp.action~=ENUMS.Formation.Vehicle.OnRoad then - formation=wp.action - end + local formation0=wp.action==ENUMS.Formation.Vehicle.OnRoad and ENUMS.Formation.Vehicle.OffRoad or wp.action -- Current point. - local current=self:GetCoordinate():WaypointGround(UTILS.MpsToKmph(self.speedWp), formation) + local current=self:GetCoordinate():WaypointGround(UTILS.MpsToKmph(self.speedWp), formation0) table.insert(waypoints, 1, current) -- Insert a point on road. - if onroad then + if wp.action==ENUMS.Formation.Vehicle.OnRoad then local current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad) table.insert(waypoints, 2, current) end + -- Debug output. if false then diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 3c7f2e6f1..5ebec3140 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -1521,6 +1521,15 @@ function AUFTRAG:SetTime(ClockStart, ClockStop) return self end +--- Set time how low the mission is executed. Once this time limit has passed, the mission is cancelled. +-- @param #AUFTRAG self +-- @param #number Duration Duration in seconds. +-- @return #AUFTRAG self +function AUFTRAG:SetDuration(Duration) + self.durationExe=Duration + return self +end + --- Set mission push time. This is the time the mission is executed. If the push time is not passed, the group will wait at the mission execution waypoint. -- @param #AUFTRAG self @@ -2341,10 +2350,21 @@ function AUFTRAG:onafterStatus(From, Event, To) -- All groups have reported MISSON DONE. self:Done() - elseif (self.Tstop and Tnow>self.Tstop+10) or (Ntargets0>0 and Ntargets==0) then - + elseif (self.Tstop and Tnow>self.Tstop+10) then + -- Cancel mission if stop time passed. - --self:Cancel() + self:Cancel() + + elseif self.durationExe and self.Texecuting and Tnow-self.Texecuting>self.durationExe then + + -- Cancel mission if stop time passed. + self:Cancel() + + elseif (Ntargets0>0 and Ntargets==0) then + + -- Cancel mission if mission targets are gone (if there were any in the beginning). + -- TODO: I commented this out for some reason but I forgot why... + self:Cancel() end @@ -2893,6 +2913,7 @@ end -- @param #string To To state. function AUFTRAG:onafterStarted(From, Event, To) self.status=AUFTRAG.Status.STARTED + self.Tstarted=timer.getAbsTime() self:T(self.lid..string.format("New mission status=%s", self.status)) end @@ -2903,6 +2924,7 @@ end -- @param #string To To state. function AUFTRAG:onafterExecuting(From, Event, To) self.status=AUFTRAG.Status.EXECUTING + self.Texecuting=timer.getAbsTime() self:T(self.lid..string.format("New mission status=%s", self.status)) end @@ -3006,7 +3028,7 @@ function AUFTRAG:onafterCancel(From, Event, To) -- COMMANDER will cancel the mission. self.commander:MissionCancel(self) - elseif self.legions then + elseif self.legions and #self.legions>0 then -- Loop over all LEGIONs. for _,_legion in pairs(self.legions or {}) do diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index 65b32e2f3..739f54ac8 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -539,13 +539,15 @@ function NAVYGROUP:Status(From, Event, To) local turning=tostring(self:IsTurning()) local alt=self.position.y local speed=UTILS.MpsToKnots(self.velocity) - local speedExpected=UTILS.MpsToKnots(self:GetExpectedSpeed()) --UTILS.MpsToKnots(self.speedWp or 0) + local speedExpected=UTILS.MpsToKnots(self:GetExpectedSpeed()) -- Waypoint stuff. local wpidxCurr=self.currentwp local wpuidCurr=self:GetWaypointUIDFromIndex(wpidxCurr) or 0 local wpidxNext=self:GetWaypointIndexNext() or 0 local wpuidNext=self:GetWaypointUIDFromIndex(wpidxNext) or 0 + local wpN=#self.waypoints or 0 + local wpF=tostring(self.passedfinalwp) local wpDist=UTILS.MetersToNM(self:GetDistanceToWaypoint() or 0) local wpETA=UTILS.SecondsToClock(self:GetTimeToWaypoint() or 0, true) @@ -554,8 +556,8 @@ function NAVYGROUP:Status(From, Event, To) local als=self:GetAlarmstate() or 0 -- Info text. - 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, roe, als, nTaskTot, nMissions, wpidxCurr, wpuidCurr, wpidxNext, wpuidNext, #self.waypoints or 0, wpDist, wpETA, speed, speedExpected, alt, self.heading, turning, freepath, intowind) + local text=string.format("%s [ROE=%d,AS=%d, T/M=%d/%d]: Wp=%d[%d]-->%d[%d] /%d [%s] Dist=%.1f NM ETA=%s - Speed=%.1f (%.1f) kts, Depth=%.1f m, Hdg=%03d, Turn=%s Collision=%d IntoWind=%s", + fsmstate, roe, als, nTaskTot, nMissions, wpidxCurr, wpuidCurr, wpidxNext, wpuidNext, wpN, wpF, wpDist, wpETA, speed, speedExpected, alt, self.heading, turning, freepath, intowind) self:I(self.lid..text) end @@ -742,49 +744,57 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth) n=n or self:GetWaypointIndexNext() -- Update waypoint tasks, i.e. inject WP tasks into waypoint table. - self:_UpdateWaypointTasks(n) + --self:_UpdateWaypointTasks(n) -- Waypoints. local waypoints={} - -- Waypoint. - local wp=UTILS.DeepCopy(self.waypoints[n]) --Ops.OpsGroup#OPSGROUP.Waypoint - - -- Speed. - if Speed then - -- Take speed specified. - wp.speed=UTILS.KnotsToMps(Speed) - else - -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum. - if self.adinfinitum and wp.speed<0.1 then - wp.speed=UTILS.KmphToMps(self.speedCruise) + for i=n, #self.waypoints do + + -- Waypoint. + local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint + + -- Speed. + if Speed then + -- Take speed specified. + wp.speed=UTILS.KnotsToMps(Speed) + else + -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum. + if self.adinfinitum and wp.speed<0.1 then + wp.speed=UTILS.KmphToMps(self.speedCruise) + end + end + + -- Depth. + if Depth then + wp.alt=-Depth + elseif self.depth then + wp.alt=-self.depth + else + -- Take default waypoint alt. + wp.alt=wp.alt or 0 + end + + -- Current set speed in m/s. + if i==n then + self.speedWp=wp.speed + self.altWp=wp.alt end - end - if Depth then - wp.alt=-Depth - elseif self.depth then - wp.alt=-self.depth - else - -- Take default waypoint alt. - wp.alt=wp.alt or 0 - end + -- Add waypoint. + table.insert(waypoints, wp) - -- Current set speed in m/s. - self.speedWp=wp.speed - - -- Add waypoint. - table.insert(waypoints, wp) + end -- Current waypoint. - local current=self:GetCoordinate():WaypointNaval(UTILS.MpsToKmph(self.speedWp), wp.alt) + local current=self:GetCoordinate():WaypointNaval(UTILS.MpsToKmph(self.speedWp), self.altWp) table.insert(waypoints, 1, current) if self:IsEngaging() or not self.passedfinalwp then -- Debug info. - self:T(self.lid..string.format("Updateing route: WP %d-->%d (%d/%d), Speed=%.1f knots, Depth=%d m", self.currentwp, n, #waypoints, #self.waypoints, UTILS.MpsToKnots(self.speedWp), wp.alt)) + self:T(self.lid..string.format("Updateing route: WP %d-->%d (%d/%d), Speed=%.1f knots, Depth=%d m", self.currentwp, n, #waypoints, #self.waypoints, UTILS.MpsToKnots(self.speedWp), self.altWp)) -- Route group to all defined waypoints remaining. self:Route(waypoints) diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 69455dd07..aef995c88 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -4097,7 +4097,7 @@ function OPSGROUP:RouteToMission(mission, delay) --waypointcoord:MarkToAll(string.format("Mission %s alt=%d m", mission:GetName(), waypointcoord.y)) -- Add waypoint. - local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, nil, formation, false) + local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, nil, formation, false) ; waypoint.ismission=true -- Add waypoint task. UpdateRoute is called inside. local waypointtask=self:AddTaskWaypoint(mission.DCStask, waypoint, mission.name, mission.prio, mission.duration) @@ -4111,7 +4111,7 @@ function OPSGROUP:RouteToMission(mission, delay) local egress=mission:GetMissionEgressCoord() if egress then - local waypoint=self:AddWaypoint(egress, SpeedToMission, nil, formation, false) + local waypoint=self:AddWaypoint(egress, SpeedToMission, nil, formation, false) ; waypoint.ismission=true end --- @@ -4384,7 +4384,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint) -- Check if all tasks/mission are done? -- Note, we delay it for a second to let the OnAfterPassingwaypoint function to be executed in case someone wants to add another waypoint there. - if ntasks==0 and self:HasPassedFinalWaypoint() then + if ntasks==0 and (self:HasPassedFinalWaypoint()) then-- or self:IsArmygroup() or self:IsNavygroup()) then self:_CheckGroupDone(0.01) end @@ -7910,6 +7910,26 @@ end -- Waypoints & Routing ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--- Simple task function. Can be used to call a function which has the warehouse and the executing group as parameters. +-- @param #OPSGROUP self +-- @param #string Function The name of the function to call passed as string. +-- @param #number uid Waypoint UID. +function OPSGROUP:_SimpleTaskFunction(Function, uid) + + -- Task script. + local DCSScript = {} + + --_DATABASE:FindOpsGroup(groupname) + + DCSScript[#DCSScript+1] = string.format('local mygroup = _DATABASE:FindOpsGroup(\"%s\") ', self.groupname) -- The group that executes the task function. Very handy with the "...". + DCSScript[#DCSScript+1] = string.format('%s(mygroup, %d)', Function, uid) -- Call the function, e.g. myfunction.(warehouse,mygroup) + + -- Create task. + local DCSTask=CONTROLLABLE.TaskWrappedAction(self, CONTROLLABLE.CommandDoScript(self, table.concat(DCSScript))) + + return DCSTask +end + --- Enhance waypoint table. -- @param #OPSGROUP self -- @param #OPSGROUP.Waypoint Waypoint data. @@ -7933,6 +7953,17 @@ function OPSGROUP:_CreateWaypoint(waypoint) waypoint.detour=false waypoint.astar=false waypoint.temp=false + + -- Tasks of this waypoint + local taskswp={} + + -- At each waypoint report passing. + --local TaskPassingWaypoint=self.group:TaskFunction("OPSGROUP._PassingWaypoint", self, waypoint.uid) + local TaskPassingWaypoint=self:_SimpleTaskFunction("OPSGROUP._PassingWaypoint", waypoint.uid) + table.insert(taskswp, TaskPassingWaypoint) + + -- Waypoint task combo. + waypoint.task=self.group:TaskCombo(taskswp) -- Increase UID counter. self.wpcounter=self.wpcounter+1 @@ -8117,10 +8148,9 @@ end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Function called when a group is passing a waypoint. ---@param Wrapper.Group#GROUP group Group that passed the waypoint. --@param #OPSGROUP opsgroup Ops group object. --@param #number uid Waypoint UID. -function OPSGROUP._PassingWaypoint(group, opsgroup, uid) +function OPSGROUP._PassingWaypoint(opsgroup, uid) -- Debug message. local text=string.format("Group passing waypoint uid=%d", uid)