Fixes
This commit is contained in:
Frank 2020-10-01 23:55:39 +02:00
parent 6445cf01a2
commit 3737592734
5 changed files with 152 additions and 26 deletions

View File

@ -329,6 +329,17 @@ function ASTAR:SetValidNeighbourDistance(MaxDistance)
return self
end
--- Set valid neighbours to be in a certain distance.
-- @param #ASTAR self
-- @param #number MaxDistance Max distance between nodes in meters. Default is 2000 m.
-- @return #ASTAR self
function ASTAR:SetValidNeighbourRoad(MaxDistance)
self:SetValidNeighbourFunction(ASTAR.Road, MaxDistance)
return self
end
--- Set the function which calculates the "cost" to go from one to another node.
-- The first to arguments of this function are always the two nodes under consideration. But you can add optional arguments.
-- Very often the distance between nodes is a good measure for the cost.
@ -368,6 +379,16 @@ function ASTAR:SetCostDist3D()
return self
end
--- Set heuristic cost to go from one node to another to be their 3D distance.
-- @param #ASTAR self
-- @return #ASTAR self
function ASTAR:SetCostRoad()
self:SetCostFunction(ASTAR)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Grid functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -510,6 +531,22 @@ function ASTAR.LoS(nodeA, nodeB, corridor)
return los
end
--- Function to check if two nodes have a road connection.
-- @param #ASTAR.Node nodeA First node.
-- @param #ASTAR.Node nodeB Other node.
-- @return #boolean If true, two nodes are connected via a road.
function ASTAR.Road(nodeA, nodeB)
local path=land.findPathOnRoads("roads", nodeA.coordinate.x, nodeA.coordinate.z, nodeB.coordinate.x, nodeB.coordinate.z)
if path then
return true
else
return false
end
end
--- Function to check if distance between two nodes is less than a threshold distance.
-- @param #ASTAR.Node nodeA First node.
-- @param #ASTAR.Node nodeB Other node.
@ -533,7 +570,8 @@ end
-- @param #ASTAR.Node nodeB Other node.
-- @return #number Distance between the two nodes.
function ASTAR.Dist2D(nodeA, nodeB)
return nodeA.coordinate:Get2DDistance(nodeB)
local dist=nodeA.coordinate:Get2DDistance(nodeB)
return dist
end
--- Heuristic cost is given by the 3D distance between the nodes.
@ -541,7 +579,8 @@ end
-- @param #ASTAR.Node nodeB Other node.
-- @return #number Distance between the two nodes.
function ASTAR.Dist3D(nodeA, nodeB)
return nodeA.coordinate:Get3DDistance(nodeB.coordinate)
local dist=nodeA.coordinate:Get3DDistance(nodeB.coordinate)
return dist
end
--- Heuristic cost is given by the distance between the nodes on road.
@ -550,15 +589,26 @@ end
-- @return #number Distance between the two nodes.
function ASTAR.DistRoad(nodeA, nodeB)
local path, dist, gotpath=nodeA.coordinate:GetPathOnRoad(nodeB.coordinate, IncludeEndpoints, Railroad, MarkPath, SmokePath)
-- Get the path.
local path=land.findPathOnRoads("roads", nodeA.coordinate.x, nodeA.coordinate.z, nodeB.coordinate.x, nodeB.coordinate.z)
if gotpath then
return dist
else
return math.huge
end
if path then
local dist=0
for i=2,#path do
local b=path[i] --DCS#Vec2
local a=path[i-1] --DCS#Vec2
dist=dist+UTILS.VecDist2D(a,b)
end
return nodeA.coordinate:Get3DDistance(nodeB.coordinate)
return dist
end
return math.huge
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -167,14 +167,16 @@ end
-- @param #number Nshots Number of shots to fire. Default 3.
-- @param #number WeaponType Type of weapon. Default auto.
-- @param #number Prio Priority of the task.
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
function ARMYGROUP:AddTaskWaypointFireAtPoint(Coordinate, Waypoint, Radius, Nshots, WeaponType, Prio)
Waypoint=Waypoint or self:GetWaypointNext()
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
self:AddTaskWaypoint(DCStask, Waypoint, nil, Prio)
local task=self:AddTaskWaypoint(DCStask, Waypoint, nil, Prio)
return task
end
--- Add a *scheduled* task.
@ -184,12 +186,14 @@ end
-- @param #number WeaponType Type of weapon. Default auto.
-- @param #string Clock Time when to start the attack.
-- @param #number Prio Priority of the task.
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
function ARMYGROUP:AddTaskAttackGroup(TargetGroup, WeaponExpend, WeaponType, Clock, Prio)
local DCStask=CONTROLLABLE.TaskAttackGroup(nil, TargetGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit, GroupAttack)
self:AddTask(DCStask, Clock, nil, Prio)
local task=self:AddTask(DCStask, Clock, nil, Prio)
return task
end
--- Check if the group is currently holding its positon.
@ -737,6 +741,10 @@ function ARMYGROUP:_InitGroup()
-- Set default formation from first waypoint.
self.option.Formation=self:GetWaypoint(1).action
self.optionDefault.Formation=self.option.Formation
-- Default TACAN off.
self:SetDefaultTACAN(nil, nil, nil, nil, true)
self.tacan=UTILS.DeepCopy(self.tacanDefault)
-- Units of the group.
local units=self.group:GetUnits()

View File

@ -201,7 +201,7 @@ end
-- @param #number WeaponType Type of weapon. Default auto.
-- @param #number Prio Priority of the task.
-- @return Ops.OpsGroup#OPSGROUP.Task The task data.
function NAVYGROUP:AddTaskFireAtPoint(Coordinate, Radius, Nshots, WeaponType, Clock, Prio)
function NAVYGROUP:AddTaskFireAtPoint(Coordinate, Clock, Radius, Nshots, WeaponType, Prio)
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
@ -462,22 +462,37 @@ function NAVYGROUP:onafterStatus(From, Event, To)
local turning=tostring(self:IsTurning())
local alt=self.position.y
local speed=UTILS.MpsToKnots(self.velocity)
local speedExpected=UTILS.MpsToKnots(self.speedWp or 0)
local speedExpected=UTILS.MpsToKnots(self:GetExpectedSpeed()) --UTILS.MpsToKnots(self.speedWp or 0)
-- Waypoint stuff.
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 wpuidCurr=self:GetWaypointUIDFromIndex(wpidxCurr) or 0
local wpidxNext=self:GetWaypointIndexNext() or 0
local wpuidNext=self:GetWaypointUIDFromIndex(wpidxNext) or 0
local wpDist=UTILS.MetersToNM(self:GetDistanceToWaypoint() or 0)
local wpETA=UTILS.SecondsToClock(self:GetTimeToWaypoint() or 0, true)
-- Current ROE and alarm state.
local roe=self:GetROE() or 0
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, wpDist, wpETA, speed, speedExpected, alt, self.heading, turning, freepath, intowind)
fsmstate, roe, als, nTaskTot, nMissions, wpidxCurr, wpuidCurr, wpidxNext, wpuidNext, #self.waypoints or 0, wpDist, wpETA, speed, speedExpected, alt, self.heading, turning, freepath, intowind)
self:I(self.lid..text)
if false then
local text="Waypoints:"
for i,wp in pairs(self.waypoints) do
local waypoint=wp --Ops.OpsGroup#OPSGROUP.Waypoint
text=text..string.format("\n%d. UID=%d", i, waypoint.uid)
if i==self.currentwp then
text=text.." current!"
end
end
env.info(text)
end
end
else
@ -584,7 +599,7 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth)
for i=n, #self.waypoints do
-- Waypoint.
local wp=self.waypoints[i] --Ops.OpsGroup#OPSGROUP.Waypoint
local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint
-- Check if next wp.
if i==n then
@ -594,7 +609,10 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth)
-- Take speed specified.
wp.speed=UTILS.KnotsToMps(Speed)
else
-- Take default waypoint speed.
-- 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
if Depth then
@ -616,7 +634,7 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Depth)
-- Dive depth is applied to all other waypoints.
if self.depth then
wp.alt=-self.depth
else
else
-- Take default waypoint depth.
end
@ -1051,8 +1069,7 @@ function NAVYGROUP:_InitGroup()
self.isNaval=true
self.isGround=false
-- Helo group.
--TODO: Submarine check
--self.isSubmarine=self.group:IsSubmarine()
-- Ships are always AI.
@ -1081,6 +1098,14 @@ function NAVYGROUP:_InitGroup()
-- Set default formation. No really applicable for ships.
self.optionDefault.Formation="Off Road"
self.option.Formation=self.optionDefault.Formation
-- Default TACAN off.
self:SetDefaultTACAN(nil, nil, nil, nil, true)
self.tacan=UTILS.DeepCopy(self.tacanDefault)
-- Default ICLS off.
self:SetDefaultICLS(nil, nil, nil, true)
self.icls=UTILS.DeepCopy(self.iclsDefault)
-- Get all units of the group.
local units=self.group:GetUnits()

View File

@ -1096,6 +1096,22 @@ function OPSGROUP:GetWaypointByIndex(index)
return nil
end
--- Get the waypoint UID from its index, i.e. its current position in the waypoints table.
-- @param #OPSGROUP self
-- @param #number index Waypoint index.
-- @return #number Unique waypoint ID.
function OPSGROUP:GetWaypointUIDFromIndex(index)
for i,_waypoint in pairs(self.waypoints) do
local waypoint=_waypoint --#OPSGROUP.Waypoint
if i==index then
return waypoint.uid
end
end
return nil
end
--- Get the waypoint index (its position in the current waypoints table).
-- @param #OPSGROUP self
-- @param #number uid Waypoint unique ID.
@ -1367,7 +1383,7 @@ function OPSGROUP:RemoveWaypoint(wpindex)
local n=#self.waypoints
-- Debug info.
self:T(self.lid..string.format("Removing waypoint index %d, current wp index %d. N %d-->%d", wpindex, self.currentwp, N, n))
self:I(self.lid..string.format("Removing waypoint index %d, current wp index %d. N %d-->%d", wpindex, self.currentwp, N, n))
-- Waypoint was not reached yet.
if wpindex > self.currentwp then
@ -3861,7 +3877,7 @@ function OPSGROUP:SwitchICLS(Channel, Morse, UnitName)
self:SetDefaultICLS(Channel,Morse,UnitName)
self:T2(self.lid..string.format("Switching ICLS to Channel %d Morse %s on unit %s when GROUP is SPAWNED", self.iclsDefault.Channel, tostring(self.iclsDefault.Morse), self.iclsDefault.BeaconName))
self:T2(self.lid..string.format("Switching ICLS to Channel %d Morse %s on unit %s when GROUP is SPAWNED", self.iclsDefault.Channel, tostring(self.iclsDefault.Morse), tostring(self.iclsDefault.BeaconName)))
elseif self:IsAlive() then

View File

@ -909,6 +909,33 @@ function UTILS.VecNorm(a)
return math.sqrt(UTILS.VecDot(a, a))
end
--- Calculate the distance between two 2D vectors.
-- @param DCS#Vec2 a Vector in 3D with x, y components.
-- @param DCS#Vec2 b Vector in 3D with x, y components.
-- @return #number Distance between the vectors.
function UTILS.VecDist2D(a, b)
local c={x=b.x-a.x, y=b.y-a.y}
local d=math.sqrt(c.x*c.x+c.y*c.y)
return d
end
--- Calculate the distance between two 3D vectors.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
-- @return #number Distance between the vectors.
function UTILS.VecDist3D(a, b)
local c={x=b.x-a.x, y=b.y-a.y, z=b.z-a.z}
local d=math.sqrt(UTILS.VecDot(c, c))
return d
end
--- Calculate the [cross product](https://en.wikipedia.org/wiki/Cross_product) of two 3D vectors. The result is a 3D vector.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.