diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index aff6142e5..76b5007f5 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -7351,6 +7351,28 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) self:T3(string.format("l1=%.1f l2=%.1f s=%.1f d=%.1f ==> safe=%s", l1,l2,safedist,dist,tostring(safe))) return safe end + + -- Get client coordinates. + local function _clients() + local clients=_DATABASE.CLIENTS + local coords={} + for clientname, client in pairs(clients) do + local template=_DATABASE:GetGroupTemplateFromUnitName(clientname) + local units=template.units + for i,unit in pairs(units) do + local coord=COORDINATE:New(unit.x, unit.alt, unit.y) + coords[unit.name]=coord + --[[ + local airbase=coord:GetClosestAirbase() + local _,TermID, dist, spot=coord:GetClosestParkingSpot(airbase) + if dist<=10 then + env.info(string.format("Found client %s on parking spot %d at airbase %s", unit.name, TermID, airbase:GetName())) + end + ]] + end + end + return coords + end -- Get parking spot data table. This contains all free and "non-free" spots. local parkingdata=airbase:GetParkingSpotsTable() @@ -7379,15 +7401,10 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) end -- Check all clients. - --[[ - for _,_unit in pairs(_units) do - local unit=_unit --Wrapper.Unit#UNIT - local _coord=unit:GetCoordinate() - local _size=self:_GetObjectSize(unit:GetDCSObject()) - local _name=unit:GetName() - table.insert(obstacles, {coord=_coord, size=_size, name=_name, type="client"}) + local clientcoords=_clients() + for clientname,_coord in pairs(clientcoords) do + table.insert(obstacles, {coord=_coord, size=15, name=clientname, type="client"}) end - ]] -- Check all statics. for _,static in pairs(_statics) do @@ -7444,9 +7461,10 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) local problem=nil -- Safe parking using TO_AC from DCS result. + self:I(self.wid..string.format("Parking spot %d TOAC=%s (safe park=%s).", _termid, tostring(_toac), tostring(self.safeparking))) if self.safeparking and _toac then free=false - self:T(self.wid..string.format("Parking spot %d is occupied by other aircraft taking off or landing.", _termid)) + self:I(self.wid..string.format("Parking spot %d is occupied by other aircraft taking off (TOAC).", _termid)) end -- Check if spot is reserved. @@ -7455,7 +7473,7 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) local reserved=fc:IsParkingReserved(parkingspot) if reserved then free=false - self:T(self.wid..string.format("Parking spot %d is reserved for flight element %s", _termid, tostring(reserved))) + self:I(self.wid..string.format("Parking spot %d is reserved for flight element %s", _termid, tostring(reserved))) end end @@ -7486,7 +7504,7 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) -- Add parkingspot for this asset unit. table.insert(parking[_asset.uid], parkingspot) - self:T(self.wid..string.format("Parking spot #%d is free for asset id=%d!", _termid, _asset.uid)) + self:I(self.wid..string.format("Parking spot %d is free for asset id=%d!", _termid, _asset.uid)) -- Add the unit as obstacle so that this spot will not be available for the next unit. table.insert(obstacles, {coord=_spot, size=_asset.size, name=_asset.templatename, type="asset"}) @@ -7497,7 +7515,7 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) else -- Debug output for occupied spots. - self:T(self.wid..string.format("Parking spot #%d is occupied or not big enough!", _termid)) + self:I(self.wid..string.format("Parking spot %d is occupied or not big enough!", _termid)) if self.Debug then local coord=problem.coord --Core.Point#COORDINATE local text=string.format("Obstacle blocking spot #%d is %s type %s with size=%.1f m and distance=%.1f m.", _termid, problem.name, problem.type, problem.size, problem.dist) @@ -7511,7 +7529,7 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) -- No parking spot for at least one asset :( if not gotit then - self:T(self.wid..string.format("WARNING: No free parking spot for asset id=%d",_asset.uid)) + self:I(self.wid..string.format("WARNING: No free parking spot for asset id=%d",_asset.uid)) return nil end end -- loop over asset units diff --git a/Moose Development/Moose/Ops/FlightControl.lua b/Moose Development/Moose/Ops/FlightControl.lua index 2abaea322..2cfeb982e 100644 --- a/Moose Development/Moose/Ops/FlightControl.lua +++ b/Moose Development/Moose/Ops/FlightControl.lua @@ -307,7 +307,21 @@ function FLIGHTCONTROL:onafterStatus() self:I(self.lid..text) -- Next status update in ~30 seconds. - self:__Status(-30) + self:__Status(-20) +end + +--- Start FLIGHTCONTROL FSM. Handle events. +-- @param #FLIGHTCONTROL self +function FLIGHTCONTROL:onafterStop() + + -- Handle events. + self:HandleEvent(EVENTS.Birth) + self:HandleEvent(EVENTS.EngineStartup) + self:HandleEvent(EVENTS.Takeoff) + self:HandleEvent(EVENTS.Land) + self:HandleEvent(EVENTS.EngineShutdown) + self:HandleEvent(EVENTS.Crash) + end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -432,7 +446,6 @@ function FLIGHTCONTROL:_CheckQueues() self:_PrintQueue(self.Qwaiting, "Holding") self:_PrintQueue(self.Qlanding, "Landing") end - -- Number of groups landing. local nlanding=#self.Qlanding @@ -915,6 +928,14 @@ function FLIGHTCONTROL:_UpdateParkingSpots() -- Parking spots of airbase. local parkingdata=self.airbase:GetParkingSpotsTable() + for _,_parking in pairs(self.parking) do + local parking=_parking --#FLIGHTCONTROL.ParkingSpot + if parking.markerid then + parking.Coordinate:RemoveMark(parking.markerid) + parking.markerid=nil + end + end + -- Loop over all spots. local message="Parking Spots:" for _,_spot in pairs(parkingdata) do @@ -923,23 +944,17 @@ function FLIGHTCONTROL:_UpdateParkingSpots() -- Parking. local parking=self.parking[spot.TerminalID] --#FLIGHTCONTROL.ParkingSpot - -- Mark position. - if parking.markerid then - parking.Coordinate:RemoveMark(parking.markerid) - parking.markerid=nil - end - -- Check if any known flight has reserved this spot. local reserved=self:IsParkingReserved(spot) - - local text=string.format("ID=%03d, Terminal=%03d, Free=%s, TOAC=%s, reserved=%s", parking.TerminalID, parking.TerminalType, tostring(parking.Free), tostring(parking.TOAC), tostring(reserved)) - if reserved then - message=message.."\n"..text - end + + -- Message text. + --local text=string.format("ID=%03d, Terminal=%03d, Free=%s, TOAC=%s, reserved=%s", parking.TerminalID, parking.TerminalType, tostring(parking.Free), tostring(parking.TOAC), tostring(reserved)) + local text=string.format("ID=%03d, Terminal=%03d, Free=%s, TOAC=%s, reserved=%s", spot.TerminalID, spot.TerminalType, tostring(spot.Free), tostring(spot.TOAC), tostring(reserved)) -- Place marker on non-free spots. if parking.Free==false or parking.TOAC or reserved~=nil then parking.markerid=parking.Coordinate:MarkToAll(text) + message=message.."\n"..text end end @@ -1405,7 +1420,7 @@ function FLIGHTCONTROL:_LandAI(flight, parking) element.parking=spot unit.parking_landing=spot.TerminalID local text=string.format("FF Reserving parking spot %d for unit %s", spot.TerminalID, tostring(unit.name)) - spot.Coordinate:MarkToAll(text) + --spot.Coordinate:MarkToAll(text) self:I(self.lid..text) else env.info("FF error could not get element to assign parking!") diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 0387bd2b4..8deb3da21 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -66,7 +66,7 @@ -- @field #FLIGHTGROUP FLIGHTGROUP = { ClassName = "FLIGHTGROUP", - Debug = nil, + Debug = false, sid = nil, groupname = nil, group = nil, @@ -369,7 +369,7 @@ function FLIGHTGROUP:New(groupname) -- Debug trace. if false then - self.Debug=true + self.Debug=false BASE:TraceOnOff(true) BASE:TraceClass(self.ClassName) BASE:TraceLevel(1) @@ -727,6 +727,33 @@ function FLIGHTGROUP:onafterStart(From, Event, To) self:__FlightStatus(-1) end +--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers. +-- @param #FLIGHTGROUP self +-- @param Wrapper.Group#GROUP Group Flight group. +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function FLIGHTGROUP:onafterStop(From, Event, To) + + -- Handle events: + self:UnHandleEvent(EVENTS.Birth) + self:UnHandleEvent(EVENTS.EngineStartup) + self:UnHandleEvent(EVENTS.Takeoff) + self:UnHandleEvent(EVENTS.Land) + self:UnHandleEvent(EVENTS.EngineShutdown) + self:UnHandleEvent(EVENTS.PilotDead) + self:UnHandleEvent(EVENTS.Ejection) + self:UnHandleEvent(EVENTS.Crash) + self:UnHandleEvent(EVENTS.RemoveUnit) + + _DATABASE.FLIGHTGROUPS[self.groupname]=nil + + self={} + self=nil + +end + + --- On after "FlightStatus" event. -- @param #FLIGHTGROUP self -- @param Wrapper.Group#GROUP Group Flight group. @@ -788,7 +815,7 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To) if #self.elements==0 then text=text.." none!" end - self:I(self.sid..text) + self:T(self.sid..text) -- Low fuel? if fuelmin0 then - self:I(self.sid..text) + self:T(self.sid..text) end @@ -1099,7 +1126,7 @@ end -- @param #string To To state. -- @param #FLIGHTGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element) - self:I(self.sid..string.format("Element spawned %s.", Element.name)) + self:T(self.sid..string.format("Element spawned %s.", Element.name)) -- Set element status. self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.SPAWNED) @@ -1129,7 +1156,7 @@ end -- @param #string To To state. -- @param #FLIGHTGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementParking(From, Event, To, Element) - self:I(self.sid..string.format("Element parking %s at spot %s.", Element.name, tostring(Element.parking.TerminalID))) + self:T(self.sid..string.format("Element parking %s at spot %s.", Element.name, tostring(Element.parking.TerminalID))) -- Set element status. self:_UpdateStatus(Element, FLIGHTGROUP.ElementStatus.PARKING) @@ -1278,7 +1305,7 @@ end -- @param #string Event Event. -- @param #string To To state. function FLIGHTGROUP:onafterFlightParking(From, Event, To) - self:I(self.sid..string.format("Flight is parking %s.", self.groupname)) + self:T(self.sid..string.format("Flight is parking %s.", self.groupname)) local airbase=self.group:GetCoordinate():GetClosestAirbase() @@ -1428,8 +1455,8 @@ end -- @param #number N Final waypoint number. function FLIGHTGROUP:onafterPassingWaypoint(From, Event, To, n, N) local text=string.format("Flight %s passed waypoint %d/%d", self.groupname, n, N) - self:I(self.sid..text) - MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug) + self:T(self.sid..text) + --MESSAGE:New(text, 30, "DEBUG"):ToAllIf(self.Debug) end --- On after "FuelLow" event. @@ -1927,6 +1954,8 @@ function FLIGHTGROUP._ReachedHolding(group, flightgroup) -- Add flight to waiting/holding queue. if flightgroup.flightcontrol then + -- Add flight to all flights. + table.insert(flightgroup.flightcontrol.flights, flightgroup) flightgroup.flightcontrol:_AddFlightToHoldingQueue(flightgroup) end end @@ -2300,7 +2329,7 @@ function FLIGHTGROUP:_UpdateRoute(n) -- Add overhead waypoint. local wpoverhead=coordoverhead:WaypointAir(nil, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.FlyoverPoint, 500, false, nil, {TaskOverhead}, "Destination Overhead") - self:I(self.sid..string.format("Adding overhead waypoint as #%d", #wp)) + self:T(self.sid..string.format("Adding overhead waypoint as #%d", #wp)) table.insert(wp, #wp, wpoverhead) @@ -2308,7 +2337,7 @@ function FLIGHTGROUP:_UpdateRoute(n) -- Debug info. - self:I(self.sid..string.format("Updating route for WP>=%d (%d/%d) homebase=%s destination=%s", n, #wp, #self.waypoints, self.homebase and self.homebase:GetName() or "unknown", self.destination and self.destination:GetName() or "unknown")) + self:T(self.sid..string.format("Updating route for WP>=%d (%d/%d) homebase=%s destination=%s", n, #wp, #self.waypoints, self.homebase and self.homebase:GetName() or "unknown", self.destination and self.destination:GetName() or "unknown")) if #wp>0 then @@ -3154,6 +3183,21 @@ function FLIGHTGROUP:GetParking(airbase) self:T3(string.format("l1=%.1f l2=%.1f s=%.1f d=%.1f ==> safe=%s", l1,l2,safedist,dist,tostring(safe))) return safe end + + -- Get client coordinates. + local function _clients() + local clients=_DATABASE.CLIENTS + local coords={} + for clientname, client in pairs(clients) do + local template=_DATABASE:GetGroupTemplateFromUnitName(clientname) + local units=template.units + for i,unit in pairs(units) do + local coord=COORDINATE:New(unit.x, unit.alt, unit.y) + coords[unit.name]=coord + end + end + return coords + end -- Get airbase category. local airbasecategory=airbase:GetAirbaseCategory() @@ -3181,17 +3225,12 @@ function FLIGHTGROUP:GetParking(airbase) local _name=unit:GetName() table.insert(obstacles, {coord=_coord, size=_size, name=_name, type="unit"}) end - + -- Check all clients. - --[[ - for _,_unit in pairs(_units) do - local unit=_unit --Wrapper.Unit#UNIT - local _coord=unit:GetCoordinate() - local _size=self:_GetObjectSize(unit:GetDCSObject()) - local _name=unit:GetName() - table.insert(obstacles, {coord=_coord, size=_size, name=_name, type="client"}) + local clientcoords=_clients() + for clientname,_coord in pairs(clientcoords) do + table.insert(obstacles, {coord=_coord, size=15, name=clientname, type="client"}) end - ]] -- Check all statics. for _,static in pairs(_statics) do @@ -3217,9 +3256,7 @@ function FLIGHTGROUP:GetParking(airbase) local parking={} -- Get terminal type. - -- TODO: get terminal type local terminaltype=self:_GetTerminal(self.attribute, airbase:GetAirbaseCategory()) - --local terminaltype=AIRBASE.TerminalType.OpenMedOrBig -- Loop over all units - each one needs a spot. for i,_element in pairs(self.elements) do