diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index 8e69fbeff..6b9d51128 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -618,7 +618,7 @@ end function AIRWING:onafterMissionRequest(From, Event, To, Mission) -- Set mission status to ASSIGNED. - Mission:Assign() + Mission:Requested() -- Some assets might already be spawned and even on a different mission (orbit). -- Need to dived to set into spawned and instock assets and handle the other diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 166ea6db5..6d6f6569d 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -21,6 +21,8 @@ -- @field #string type Mission type. -- @field #string status Mission status. -- @field #table flightstatus Status of flight missions. +-- @field #table flightgroups Flight groups of this mission. +-- @field #table flightdata Flight specific data. -- @field #string name Mission name. -- @field #number prio Mission priority. -- @field #boolean urgent Mission is urgent. Running missions with lower prio might be cancelled. @@ -96,7 +98,9 @@ AUFTRAG = { Debug = false, lid = nil, auftragsnummer = nil, + flightgroups = {}, flightstatus = {}, + flightdata = {}, } --- Global mission counter. @@ -144,9 +148,10 @@ AUFTRAG.Type={ -- @type AUFTRAG.Status -- @field #string PLANNED Mission is at the early planning stage. -- @field #string QUEUED Mission is queued at an airwing. +-- @field #string REQUESTED Mission assets were requested from the warehouse. -- @field #string ASSIGNED Mission was assigned to somebody. -- @field #string SCHEDULED Mission is scheduled in a FLIGHGROUP queue waiting to be started. --- @field #string STARTED Mission started but is not executed yet. +-- @field #string STARTED Mission has started but is not executed yet. -- @field #string EXECUTING Mission is being executed. -- @field #string DONE Mission is over. -- @field #string CANCELLED Mission was cancelled. @@ -179,6 +184,14 @@ AUFTRAG.FlightStatus={ DONE="done", } +--- Flight specific data. +-- @type AUFTRAG.FlightData +-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. +-- @field Core.Point#COORDINATE waypointcoordinate Waypoint coordinate. +-- @field #number waypointindex Waypoint index. +-- @field Ops.FlightGroup#FLIGHTGROUP.Task waypointtask Waypoint task. +-- @field #string status Flight mission status. + --- AUFTRAG class version. -- @field #string version @@ -228,7 +241,7 @@ function AUFTRAG:New(Type) -- FMS start state is PLANNED. self:SetStartState(self.status) - -- PLANNED --> (QUEUED) --> (ASSIGNED) --> SCHEDULED --> STARTED --> EXECUTING --> DONE + -- PLANNED --> (QUEUED) --> (REQUESTED) --> SCHEDULED --> STARTED --> EXECUTING --> DONE self:AddTransition(AUFTRAG.Status.PLANNED, "Queued", AUFTRAG.Status.QUEUED) -- Mission is in queue of an AIRWING. self:AddTransition(AUFTRAG.Status.QUEUED, "Requested", AUFTRAG.Status.REQUESTED) -- Mission assets have been requested from the warehouse. @@ -242,8 +255,8 @@ function AUFTRAG:New(Type) self:AddTransition("*", "Done", AUFTRAG.Status.DONE) -- All assets have reported that mission is done. self:AddTransition("*", "Cancel", AUFTRAG.Status.CANCELLED) -- Command to cancel the mission. - self:AddTransition("*", "Accomplished", "Success") - self:AddTransition("*", "Failed", "Failure") + self:AddTransition("*", "Accomplished", AUFTRAG.Status.SUCCESS) + self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED) self:AddTransition("*", "Status", "*") @@ -486,6 +499,23 @@ function AUFTRAG:SetROE(roe) end +--- Add a flight group to the mission. +-- @param #AUFTRAG self +-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FLIGHTGROUP object. +function AUFTRAG:AddFlightGroup(FlightGroup) + self:I(self.lid..string.format("Adding flight group %s", FlightGroup.groupname)) + + --table.insert(self.flightgroups, FlightGroup) + + local flightdata={} --#AUFTRAG.FlightData + flightdata.flightgroup=FlightGroup + flightdata.status=AUFTRAG.FlightStatus.SCHEDULED + flightdata.waypointcoordinate=nil + + self.flightdata[FlightGroup.groupname]=flightdata + +end + --- Check if mission is executing. -- @param #AUFTRAG self -- @return #boolean If true, mission is currently executing. @@ -515,40 +545,61 @@ function AUFTRAG:onafterStatus(From, Event, To) local fsmstate=self:GetState() - self:I(self.lid..string.format("FSM status %s, mission status=%s", fsmstate, self.status)) + self:I(self.lid..string.format("FSM status %s, mission status=%s, flightgroups=%d", fsmstate, self.status, #self.flightdata)) + self:__Status(-30) end ---- On after "Cancel" event. Cancells the mission. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterCancel(From, Event, To) - - for _,_asset in pairs(self.assets or {}) do - local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset - asset.flightgroup:MissionCancel(self) - end - -end - - --- Set flightgroup mission status. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. --- @param #string state New state. -function AUFTRAG:SetFlightStatus(flightgroup, state) - self.flightstatus[flightgroup.groupname]=state +-- @param #string status New status. +function AUFTRAG:SetFlightStatus(flightgroup, status) + self.flightdata[flightgroup.groupname].status=status end --- Get flightgroup mission status. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. function AUFTRAG:GetFlightStatus(flightgroup) - return self.flightstatus[flightgroup.groupname] + return self.flightdata[flightgroup.groupname].status end + +--- Set flightgroup waypoint coordinate. +-- @param #AUFTRAG self +-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. +-- @param Core.Point#COORDINATE coordinate Waypoint Coordinate. +function AUFTRAG:SetFlightWaypointCoordinate(flightgroup, coordinate) + self.flightdata[flightgroup.groupname].waypointcoordinate=coordinate +end + +--- Get flightgroup waypoint coordinate. +-- @param #AUFTRAG self +-- @return Core.Point#COORDINATE Waypoint Coordinate. +function AUFTRAG:GetFlightWaypointCoordinate(flightgroup) + return self.flightdata[flightgroup.groupname].waypointcoordinate +end + + +--- Set flightgroup waypoint task. +-- @param #AUFTRAG self +-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. +-- @param Ops.FlightGroup#FLIGHTGROUP.Task task Waypoint task. +function AUFTRAG:SetFlightWaypointTask(flightgroup, task) + self:I(self.lid..string.format("Setting waypoint task %s", task and task.description or "WTF")) + self.flightdata[flightgroup.groupname].waypointtask=task +end + +--- Get flightgroup waypoint task. +-- @param #AUFTRAG self +-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. +-- @return Ops.FlightGroup#FLIGHTGROUP.Task task Waypoint task. Waypoint task. +function AUFTRAG:GetFlightWaypointTask(flightgroup) + return self.flightdata[flightgroup.groupname].waypointtask +end + + --- Get flightgroup mission status. -- @param #AUFTRAG self -- @return #boolean If true, all flights are done with the mission. @@ -617,7 +668,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function AUFTRAG:onafterStart(From, Event, To) +function AUFTRAG:onafterStarted(From, Event, To) self.status=AUFTRAG.Status.STARTED self:I(self.lid..string.format("New mission status=%s", self.status)) end @@ -627,7 +678,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function AUFTRAG:onafterExecute(From, Event, To) +function AUFTRAG:onafterExecuting(From, Event, To) self.status=AUFTRAG.Status.EXECUTING self:I(self.lid..string.format("New mission status=%s", self.status)) end @@ -642,15 +693,28 @@ function AUFTRAG:onafterDone(From, Event, To) self:I(self.lid..string.format("New mission status=%s", self.status)) end - ---- On after "Cancel" event. +--- On after "Cancel" event. Cancells the mission. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterCancel(From, Event, To) - self.status=AUFTRAG.Status.DONE + + self.status=AUFTRAG.Status.CANCELLED self:I(self.lid..string.format("New mission status=%s", self.status)) + + --[[ + for _,_asset in pairs(self.assets or {}) do + local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset + asset.flightgroup:MissionCancel(self) + end + ]] + + for _,_flightdata in pairs(self.flightdata) do + local flightdata=_flightdata --#AUFTRAG.FlightData + flightdata.flightgroup:MissionCancel(self) + end + end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index ae94e2754..c903c1100 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -659,20 +659,23 @@ end -- @param Core.Point#COORDINATE WaypointCoordinate Coordinate of the mission waypoint -- @param #number WaypointIndex The waypoint number. Default is after all current air waypoints. -- @return #FLIGHTGROUP self -function FLIGHTGROUP:AddMission(Mission, WaypointCoordinate, WaypointIndex) +function FLIGHTGROUP:AddMission(Mission, WaypointCoordinate) Mission.waypointcoord=WaypointCoordinate - Mission.waypointindex=WaypointIndex + + -- Add flight group to mission. + Mission:AddFlightGroup(self) -- Set status to scheduled. Mission:SetFlightStatus(self, AUFTRAG.FlightStatus.SCHEDULED) + Mission:Scheduled() -- Add mission to queue. table.insert(self.missionqueue, Mission) -- Info text. - local text=string.format("Added %s mission %s at waypoint #%s. Starting at %s. Stopping at %s", - tostring(Mission.type), tostring(Mission.name), tostring(Mission.waypointindex), UTILS.SecondsToClock(Mission.Tstart, true), Mission.Tstop and UTILS.SecondsToClock(Mission.Tstop, true) or "N/A") + local text=string.format("Added %s mission %s starting at %s, stopping at %s", + tostring(Mission.type), tostring(Mission.name), UTILS.SecondsToClock(Mission.Tstart, true), Mission.Tstop and UTILS.SecondsToClock(Mission.Tstop, true) or "INF") self:I(self.lid..text) return self @@ -1337,8 +1340,8 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To) local mission=_mission --Ops.Auftrag#AUFTRAG local Cstart= UTILS.SecondsToClock(mission.Tstart, true) local Cstop = mission.Tstop and UTILS.SecondsToClock(mission.Tstop, true) or "INF" - text=text..string.format("\n[%d] %s (%s) status=%s, Time=%s-%s, waypoint=%s, prio=%d targets=%d", - i, tostring(mission.name), mission.type, tostring(mission.status), Cstart, Cstop, tostring(mission.waypointindex), mission.prio, mission:CountMissionTargets()) + text=text..string.format("\n[%d] %s (%s) status=%s (%s), Time=%s-%s, prio=%d targets=%d", + i, tostring(mission.name), mission.type, mission:GetFlightStatus(self), tostring(mission.status), Cstart, Cstop, mission.prio, mission:CountMissionTargets()) end self:I(self.lid..text) @@ -2990,30 +2993,48 @@ function FLIGHTGROUP:onafterTaskUnpause(From, Event, To) --self.task end ---- On after "TaskCancel" event. Cancels the current task. +--- On after "TaskCancel" event. Cancels the current task or simply sets the status to DONE if the task is not the current one. -- @param #FLIGHTGROUP self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function FLIGHTGROUP:onafterTaskCancel(From, Event, To) +-- @param #FLIGHTGROUP.Task Task The task to cancel. Default is the current task (if any). +function FLIGHTGROUP:onafterTaskCancel(From, Event, To, Task) -- Get current task. - local task=self:GetTaskCurrent() + local currenttask=self:GetTaskCurrent() - if task then + Task=Task or currenttask - -- Debug info. - local text=string.format("Task %s ID=%d cancelled.", task.description, task.id) - MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) + if Task then + + -- Check if the task is the current task? + if currenttask and Task.id==currenttask.id then + + -- Debug info. + local text=string.format("Current task %s ID=%d cancelled", Task.description, Task.id) + MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) + self:I(self.lid..text) + + -- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone() + Task.stopflag:Set(1) + + else + + self:I(self.lid..string.format("TaskCancel: Setting task %s ID=%d to DONE", Task.description, Task.id)) + Task.status=FLIGHTGROUP.TaskStatus.DONE + + if Task.type==FLIGHTGROUP.TaskType.WAYPOINT and Task.waypoint then + self:RemoveWaypoint(Task.waypoint) + end + end + + else + + local text=string.format("WARNING: No (current) task to cancel!") + MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) self:I(self.lid..text) - -- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone() - task.stopflag:Set(1) - - else - local text=string.format("WARNING: No current task to cancel!") - MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) - self:I(self.lid..text) end end @@ -3152,19 +3173,26 @@ end function FLIGHTGROUP:onafterMissionCancel(From, Event, To, Mission) if self.currentmission and Mission.auftragsnummer==self.currentmission then + + local Task=Mission:GetFlightWaypointTask(self) + + env.info(string.format("FF Cancel current mission %s. Task=%s", tostring(Mission.name), tostring(Task and Task.description or "WTF"))) -- Cancelling the mission is actually cancelling the current task. This will trigger the task done. - self:TaskCancel() + self:TaskCancel(Task) + + self.currentmission=nil else -- Not the current mission. So set status in queue. - -- TODO: remove mission from queue? - - -- Set missin flight status. - Mission:SetFlightStatus(self, AUFTRAG.Status.CANCELLED) + -- TODO: remove mission from queue? end + + -- Set missin flight status. + env.info("FF setting mission to cancelled") + Mission:SetFlightStatus(self, AUFTRAG.Status.CANCELLED) end @@ -3206,21 +3234,20 @@ function FLIGHTGROUP:RouteToMission(mission, delay) -- Next waypoint. local nextwaypoint=self.currentwp+1 - -- Execute mission at the given waypoint (but ensure it has not been passed already) or the next waypoint. - mission.waypointindex=mission.waypointindex and math.max(mission.waypointindex, nextwaypoint) or nextwaypoint - -- Add waypoint. - self:AddWaypointAir(mission.waypointcoord, mission.waypointindex, self.speedmax*0.8, false) + self:AddWaypointAir(mission.waypointcoord, nextwaypoint, self.speedmax*0.8, false) -- Add waypoint task. UpdateRoute is called inside. - -- TODO: The waypoint task is different for all assinged flights! - mission.waypointtask=self:AddTaskWaypoint(mission.DCStask, mission.waypointindex, mission.name, mission.prio, mission.duration) + local waypointtask=self:AddTaskWaypoint(mission.DCStask, nextwaypoint, mission.name, mission.prio, mission.duration) + + -- Set waypoint task. + mission:SetFlightWaypointTask(self, waypointtask) -- TODO: better marker text, mission.maker mission.marker=mission.waypointcoord:MarkToCoalition(mission.name, self:GetCoalition(), true) - self:SetROE(mission.optionROE) + --self:SetROE(mission.optionROE) end end @@ -3937,7 +3964,7 @@ function FLIGHTGROUP:AddWaypointAir(coordinate, wpnumber, speed, updateroute) -- Shift all waypoint tasks after the inserted waypoint. for _,_task in pairs(self.taskqueue) do local task=_task --#FLIGHTGROUP.Task - if task.type==FLIGHTGROUP.TaskType.WAYPOINT and task.status==FLIGHTGROUP.TaskStatus.SCHEDULED and task.waypoint>=wpnumber then + if task.type==FLIGHTGROUP.TaskType.WAYPOINT and task.waypoint and task.waypoint>=wpnumber then task.waypoint=task.waypoint+1 end end @@ -3945,7 +3972,7 @@ function FLIGHTGROUP:AddWaypointAir(coordinate, wpnumber, speed, updateroute) -- Shift all mission waypoints after the inserted waypoint. for _,_mission in pairs(self.missionqueue) do local mission=_mission --Ops.Auftrag#AUFTRAG - if mission.status==AUFTRAG.Status.SCHEDULED and mission.waypointindex and mission.waypointindex>=wpnumber then + if mission.waypointindex and mission.waypointindex>=wpnumber then mission.waypointindex=mission.waypointindex+1 end end @@ -3958,26 +3985,36 @@ function FLIGHTGROUP:AddWaypointAir(coordinate, wpnumber, speed, updateroute) return self end ---- Set the landing waypoint. +--- Remove a waypoint. -- @param #FLIGHTGROUP self --- @param Wrapper.Airbase#AIRBASE airbase The destination airbase. --- @param #number wpnumber Waypoint number. Default at the end. --- @param #number speed Speed in knots. Default 350 kts. +-- @param #number wpindex Waypoint number. -- @return #FLIGHTGROUP self function FLIGHTGROUP:RemoveWaypoint(wpindex) - for i, wp in pairs(self.waypoints) do - if i==wpindex then - table.remove(self.waypoints, i) - break - end - end + -- Remove waypoint. + table.remove(self.waypoints, wpindex) + -- Shift all waypoint tasks after the removed waypoint. + for _,_task in pairs(self.taskqueue) do + local task=_task --#FLIGHTGROUP.Task + if task.type==FLIGHTGROUP.TaskType.WAYPOINT and task.waypoint and task.waypoint>wpindex then + task.waypoint=task.waypoint-1 + end + end + + -- Shift all mission waypoints after the removerd waypoint. + for _,_mission in pairs(self.missionqueue) do + local mission=_mission --Ops.Auftrag#AUFTRAG + if mission.waypointindex and mission.waypointindex>wpindex then + mission.waypointindex=mission.waypointindex-1 + end + end --TODO update route? -- no, if <= self.currentwaypoint or WP is landing. - - --TODO shift task and mission waypoints + + self:__UpdateRoute(-1) + end