mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
WEAPON v0.1.0
**WEAPON** - Improments of class - ARTY works - FOX works - RANGE should work, not tested.
This commit is contained in:
@@ -167,7 +167,7 @@ end
|
||||
|
||||
--- Get the DCS unit object.
|
||||
-- @param #UNIT self
|
||||
-- @return DCS#Unit
|
||||
-- @return DCS#Unit The DCS unit object.
|
||||
function UNIT:GetDCSObject()
|
||||
|
||||
local DCSUnit = Unit.getByName( self.UnitName )
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Convenient access to DCS API functions
|
||||
-- * Track weapon and get impact position
|
||||
-- * Track weapon and get impact position
|
||||
-- * Get launcher and target of weapon
|
||||
-- * Define callback function when weapon impacts
|
||||
-- * Destroy weapon before impact
|
||||
-- * Define callback function when tracking weapon
|
||||
-- * Mark impact points on F10 map
|
||||
-- * Put coloured smoke on impact points
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -31,7 +33,8 @@
|
||||
-- @field DCS#Weapon weapon The DCS weapon object.
|
||||
-- @field #string name Name of the weapon object.
|
||||
-- @field #string typeName Type name of the weapon.
|
||||
-- @field #number category Weapon category 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB (Weapon.Category.X).
|
||||
-- @field #number category Weapon category 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB, 4=TORPEDO (Weapon.Category.X).
|
||||
-- @field #number categoryMissile Missile category 0=AAM, 1=SAM, 2=BM, 3=ANTI_SHIP, 4=CRUISE, 5=OTHER (Weapon.MissileCategory.X).
|
||||
-- @field #number coalition Coalition ID.
|
||||
-- @field #number country Country ID.
|
||||
-- @field DCS#Desc desc Descriptor table.
|
||||
@@ -45,11 +48,18 @@
|
||||
-- @field #table trackArg Optional arguments for the track callback function.
|
||||
-- @field DCS#Vec3 vec3 Last known 3D position vector of the tracked weapon.
|
||||
-- @field DCS#Position3 pos3 Last known 3D position and direction vector of the tracked weapon.
|
||||
-- @field Core.Point#COORDINATE coordinate Coordinate object of the weapon. Can be used in other classes.
|
||||
-- @field DCS#Vec3 impactVec3 Impact 3D vector.
|
||||
-- @field Core.Point#COORDINATE impactCoord Impact coordinate.
|
||||
-- @field #number trackScheduleID Tracking scheduler ID. Can be used to remove/destroy the scheduler function.
|
||||
-- @field #boolean tracking If `true`, scheduler will keep tracking. Otherwise, function will return nil and stop tracking.
|
||||
-- @field #boolean markImpact If `true`, the impact point is marked on the F10 map. Requires tracking to be started.
|
||||
-- @field #boolean impactMark If `true`, the impact point is marked on the F10 map. Requires tracking to be started.
|
||||
-- @field #boolean impactSmoke If `true`, the impact point is marked by smoke. Requires tracking to be started.
|
||||
-- @field #number impactSmokeColor Colour of impact point smoke.
|
||||
-- @field #boolean impactDestroy If `true`, destroy weapon before impact. Requires tracking to be started and sufficiently small time step.
|
||||
-- @field #number impactDestroyDist Distance in meters to the estimated impact point. If smaller, then weapon is destroyed.
|
||||
-- @field #number distIP Distance in meters for the intercept point estimation.
|
||||
-- @field Wrapper.Unit#UNIT target Last known target.
|
||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
--- *In the long run, the sharpest weapon of all is a kind and gentle spirit.* -- Anne Frank
|
||||
@@ -68,15 +78,21 @@
|
||||
--
|
||||
-- # Tracking
|
||||
--
|
||||
-- The status of the weapon can be tracked with the @{#WEAPON.StartTrack}() function. This function will try to determin the position of the weapon in (normally) relatively
|
||||
-- small time steps. The time step can be set via the @{#WEAPON.SetTimeStepTrack} function and is by default set to 0.01 secons.
|
||||
-- The status of the weapon can be tracked with the @{#WEAPON.StartTrack} function. This function will try to determin the position of the weapon in (normally) relatively
|
||||
-- small time steps. The time step can be set via the @{#WEAPON.SetTimeStepTrack} function and is by default set to 0.01 seconds.
|
||||
--
|
||||
-- Once the position cannot be retrieved any more, the weapon has impacted (or was destroyed otherwise) and the last known position is safed as the impact point.
|
||||
-- The impact point can be accessed with the @{#WEAPON.GetImpactVec3} or @{#WEAPON.GetImpactCoordinate} functions.
|
||||
--
|
||||
-- ## Impact Point Marking
|
||||
--
|
||||
-- You can mark the impact point on the F10 map with @{#WEAPON.SetMarkImpact}.
|
||||
--
|
||||
-- You can also trigger coloured smoke at the impact point via @{#WEAPON.SetSmokeImpact}.
|
||||
--
|
||||
-- ## Callback functions
|
||||
--
|
||||
-- It is possible to define functions that are called during the tracking of the weapon and upon impact.
|
||||
-- It is possible to define functions that are called during the tracking of the weapon and upon impact, which help you to customize further actions.
|
||||
--
|
||||
-- ### Callback on Impact
|
||||
--
|
||||
@@ -86,6 +102,38 @@
|
||||
--
|
||||
-- The function called each time the weapon status is tracked can be set with @{#WEAPON.SetFuncTrack}
|
||||
--
|
||||
-- # Target
|
||||
--
|
||||
-- If the weapon has a specific target, you can get it with the @{#WEAPON.GetTarget} function. Note that the object, which is returned can vary. Normally, it is a UNIT
|
||||
-- but it could also be a STATIC object.
|
||||
--
|
||||
-- Also note that the weapon does not always have a target, it can loose a target and re-aquire it and the target might change to another unit.
|
||||
--
|
||||
-- You can get the target name with the @{#WEAPON.GetTargetName} function.
|
||||
--
|
||||
-- The distance to the target is returned by the @{#WEAPON.GetTargetDistance} function.
|
||||
--
|
||||
-- # Category
|
||||
--
|
||||
-- The category (bomb, rocket, missile, shell, torpedo) of the weapon can be retrieved with the @{#WEAPON.GetCategory} function.
|
||||
--
|
||||
-- You can check if the weapon is a
|
||||
--
|
||||
-- * bomb with @{#WEAPON.IsBomb}
|
||||
-- * rocket with @{#WEAPON.IsRocket}
|
||||
-- * missile with @{#WEAPON.IsMissile}
|
||||
-- * shell with @{#WEAPON.IsShell}
|
||||
-- * torpedo with @{#WEAPON.IsTorpedo}
|
||||
--
|
||||
-- # Parameters
|
||||
--
|
||||
-- You can get various parameters of the weapon, *e.g.*
|
||||
--
|
||||
-- * position: @{#WEAPON.GetVec3}, @{#WEAPON.GetVec2 }, @{#WEAPON.GetCoordinate}
|
||||
-- * speed: @{#WEAPON.GetSpeed}
|
||||
-- * coalition: @{#WEAPON.GetCoalition}
|
||||
-- * country: @{#WEAPON.GetCountry}
|
||||
--
|
||||
-- # Dependencies
|
||||
--
|
||||
-- This class is used (at least) in the MOOSE classes:
|
||||
@@ -103,7 +151,7 @@ WEAPON = {
|
||||
|
||||
--- WEAPON class version.
|
||||
-- @field #string version
|
||||
WEAPON.version="0.0.1"
|
||||
WEAPON.version="0.1.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -149,7 +197,7 @@ function WEAPON:New(WeaponObject)
|
||||
end
|
||||
|
||||
-- Get type name.
|
||||
self.typeName=WeaponObject:getTypeName()
|
||||
self.typeName=WeaponObject:getTypeName() or "Unknown Type"
|
||||
|
||||
-- Get name of object. Usually a number like "1234567".
|
||||
self.name=WeaponObject:getName()
|
||||
@@ -170,18 +218,23 @@ function WEAPON:New(WeaponObject)
|
||||
self.launcherUnit=UNIT:Find(self.launcher)
|
||||
end
|
||||
|
||||
-- Init the coordinate of the weapon from that of the launcher.
|
||||
self.coordinate=COORDINATE:NewFromVec3(self.launcher:getPoint())
|
||||
|
||||
-- Set log ID.
|
||||
self.lid=string.format("[%s] %s | ", self.typeName, self.name)
|
||||
|
||||
-- Set default parameters
|
||||
self:SetTimeStepTrack()
|
||||
self:SetDistanceInterceptPoint()
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("FF Weapon: Name=%s, TypeName=%s, Category=%s, Coalition=%d, Country=%d, Launcher=%s",
|
||||
self.name, self.typeName, self.category, self.coalition, self.country, self.launcherName)
|
||||
env.info(text)
|
||||
local text=string.format("Weapon v%s\nName=%s, TypeName=%s, Category=%s, Coalition=%d, Country=%d, Launcher=%s",
|
||||
self.version, self.name, self.typeName, self.category, self.coalition, self.country, self.launcherName)
|
||||
self:T(self.lid..text)
|
||||
|
||||
self:I(self.desc)
|
||||
-- Descriptors.
|
||||
self:T2(self.desc)
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -208,6 +261,19 @@ function WEAPON:SetTimeStepTrack(TimeStep)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set distance of intercept point for estimated impact point.
|
||||
-- If the weapon cannot be tracked any more, the intercept point from its last known position and direction is used to get
|
||||
-- a better approximation of the impact point. Can be useful when using longer time steps in the tracking and still achieve
|
||||
-- a good result on the impact point.
|
||||
-- It uses the DCS function [getIP](https://wiki.hoggitworld.com/view/DCS_func_getIP).
|
||||
-- @param #WEAPON self
|
||||
-- @param #number Distance Distance in meters. Default is 50 m. Set to 0 to deactivate.
|
||||
-- @return #WEAPON self
|
||||
function WEAPON:SetDistanceInterceptPoint(Distance)
|
||||
self.distIP=Distance or 50
|
||||
return self
|
||||
end
|
||||
|
||||
--- Mark impact point on the F10 map. This requires that the tracking has been started.
|
||||
-- @param #WEAPON self
|
||||
-- @param #boolean Switch If `true` or nil, impact is marked.
|
||||
@@ -215,14 +281,33 @@ end
|
||||
function WEAPON:SetMarkImpact(Switch)
|
||||
|
||||
if Switch==false then
|
||||
self.markImpact=false
|
||||
self.impactMark=false
|
||||
else
|
||||
self.markImpact=true
|
||||
self.impactMark=true
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Put smoke on impact point. This requires that the tracking has been started.
|
||||
-- @param #WEAPON self
|
||||
-- @param #boolean Switch If `true` or nil, impact is smoked.
|
||||
-- @param #number SmokeColor Color of smoke. Default is `SMOKECOLOR.Red`.
|
||||
-- @return #WEAPON self
|
||||
function WEAPON:SetSmokeImpact(Switch, SmokeColor)
|
||||
|
||||
if Switch==false then
|
||||
self.impactSmoke=false
|
||||
else
|
||||
self.impactSmoke=true
|
||||
end
|
||||
|
||||
self.impactSmokeColor=SmokeColor or SMOKECOLOR.Red
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set callback function when weapon is tracked and still alive. The first argument will be the WEAPON object.
|
||||
-- Note that this can be called many times per second. So be careful for performance reasons.
|
||||
-- @param #WEAPON self
|
||||
@@ -284,20 +369,19 @@ function WEAPON:GetTarget()
|
||||
-- Get object category.
|
||||
local category=object:getCategory()
|
||||
|
||||
-- Get object name.
|
||||
--Target name
|
||||
local name=object:getName()
|
||||
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("Got Target Object %s, category=%d", name, category))
|
||||
|
||||
self:T(self.lid..string.format("Got Target Object %s, category=%d", object:getName(), category))
|
||||
|
||||
if category==Object.Category.UNIT then
|
||||
|
||||
target=UNIT:Find(object)
|
||||
target=UNIT:FindByName(name)
|
||||
|
||||
elseif category==Object.Category.STATIC then
|
||||
|
||||
target=STATIC:Find(object)
|
||||
target=STATIC:FindByName(name, false)
|
||||
|
||||
elseif category==Object.Category.SCENERY then
|
||||
self:E(self.lid..string.format("ERROR: Scenery target not implemented yet!"))
|
||||
@@ -308,10 +392,57 @@ function WEAPON:GetTarget()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return target
|
||||
end
|
||||
|
||||
--- Get the distance to the current target the weapon is guiding to.
|
||||
-- @param #WEAPON self
|
||||
-- @param #function ConversionFunction (Optional) Conversion function from meters to desired unit, *e.g.* `UTILS.MpsToKmph`.
|
||||
-- @return #number Distance from weapon to target in meters.
|
||||
function WEAPON:GetTargetDistance(ConversionFunction)
|
||||
|
||||
-- Get the target of the weapon.
|
||||
local target=self:GetTarget() --Wrapper.Unit#UNIT
|
||||
|
||||
local distance=nil
|
||||
if target then
|
||||
|
||||
-- Current position of target.
|
||||
local tv3=target:GetVec3()
|
||||
|
||||
-- Current position of weapon.
|
||||
local wv3=self:GetVec3()
|
||||
|
||||
if tv3 and wv3 then
|
||||
distance=UTILS.VecDist3D(tv3, wv3)
|
||||
|
||||
if ConversionFunction then
|
||||
distance=ConversionFunction(distance)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return distance
|
||||
end
|
||||
|
||||
|
||||
--- Get name the current target the weapon is guiding to.
|
||||
-- @param #WEAPON self
|
||||
-- @return #string Name of the target or "None" if no target.
|
||||
function WEAPON:GetTargetName()
|
||||
|
||||
-- Get the target of the weapon.
|
||||
local target=self:GetTarget() --Wrapper.Unit#UNIT
|
||||
|
||||
local name="None"
|
||||
if target then
|
||||
name=target:GetName()
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
--- Get velocity vector of weapon.
|
||||
-- @param #WEAPON self
|
||||
@@ -326,8 +457,9 @@ end
|
||||
|
||||
--- Get speed of weapon.
|
||||
-- @param #WEAPON self
|
||||
-- @param #function ConversionFunction (Optional) Conversion function from m/s to desired unit, *e.g.* `UTILS.MpsToKmph`.
|
||||
-- @return #number Speed in meters per second.
|
||||
function WEAPON:GetSpeed()
|
||||
function WEAPON:GetSpeed(ConversionFunction)
|
||||
|
||||
local speed=nil
|
||||
|
||||
@@ -337,6 +469,10 @@ function WEAPON:GetSpeed()
|
||||
|
||||
speed=UTILS.VecNorm(v)
|
||||
|
||||
if ConversionFunction then
|
||||
speed=ConversionFunction(speed)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return speed
|
||||
@@ -344,7 +480,7 @@ end
|
||||
|
||||
--- Get the current 3D position vector.
|
||||
-- @param #WEAPON self
|
||||
-- @return DCS#Vec3
|
||||
-- @return DCS#Vec3 Current position vector in 3D.
|
||||
function WEAPON:GetVec3()
|
||||
|
||||
local vec3=nil
|
||||
@@ -355,6 +491,24 @@ function WEAPON:GetVec3()
|
||||
return vec3
|
||||
end
|
||||
|
||||
|
||||
--- Get the current 2D position vector.
|
||||
-- @param #WEAPON self
|
||||
-- @return DCS#Vec2 Current position vector in 2D.
|
||||
function WEAPON:GetVec2()
|
||||
|
||||
local vec3=self:GetVec3()
|
||||
|
||||
if vec3 then
|
||||
|
||||
local vec2={x=vec3.x, y=vec3.z}
|
||||
|
||||
return vec2
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get type name.
|
||||
-- @param #WEAPON self
|
||||
-- @return #string The type name.
|
||||
@@ -469,6 +623,7 @@ function WEAPON:Destroy(Delay)
|
||||
else
|
||||
if self.weapon then
|
||||
self:T(self.lid.."Destroying Weapon NOW!")
|
||||
self:StopTrack()
|
||||
self.weapon:destroy()
|
||||
end
|
||||
end
|
||||
@@ -481,10 +636,11 @@ end
|
||||
-- the (approximate) impact point. Of course, the smaller the time step, the better the position can be determined. However, this can hit the performance as many
|
||||
-- calculations per second need to be carried out.
|
||||
-- @param #WEAPON self
|
||||
-- @param #number Delay Delay in seconds before the tracking starts. Default 0.001 sec. This is also the minimum.
|
||||
-- @param #number Delay Delay in seconds before the tracking starts. Default 0.001 sec.
|
||||
-- @return #WEAPON self
|
||||
function WEAPON:StartTrack(Delay)
|
||||
|
||||
-- Set delay before start.
|
||||
Delay=math.max(Delay or 0.001, 0.001)
|
||||
|
||||
-- Debug info.
|
||||
@@ -530,7 +686,9 @@ end
|
||||
function WEAPON:_TrackWeapon(time)
|
||||
|
||||
-- Debug info.
|
||||
self:T3(self.lid..string.format("Tracking at T=%.5f", time))
|
||||
if self.verbose>=20 then
|
||||
self:I(self.lid..string.format("Tracking at T=%.5f", time))
|
||||
end
|
||||
|
||||
-- Protected call to get the weapon position. If the position cannot be determined any more, the weapon has impacted and status is nil.
|
||||
local status, pos3= pcall(
|
||||
@@ -550,33 +708,41 @@ function WEAPON:_TrackWeapon(time)
|
||||
self.pos3 = pos3
|
||||
|
||||
-- Update last known vec3.
|
||||
self.vec3 = self.pos3.p
|
||||
self.vec3 = UTILS.DeepCopy(self.pos3.p)
|
||||
|
||||
-- Update coordinate.
|
||||
self.coordinate:UpdateFromVec3(self.vec3)
|
||||
|
||||
-- Keep on tracking by returning the next time below.
|
||||
self.tracking=true
|
||||
|
||||
-- Callback function.
|
||||
if self.trackFunc then
|
||||
self.trackFunc(self, unpack(self.trackArg or {}))
|
||||
self.trackFunc(self, unpack(self.trackArg))
|
||||
end
|
||||
|
||||
-- Verbose output.
|
||||
if self.verbose>=5 then
|
||||
|
||||
-- Get vec2 of current position.
|
||||
local vec2={x=self.vec3.x, y=self.vec3.z}
|
||||
|
||||
-- Land hight.
|
||||
local height=land.getHeight(vec2)
|
||||
|
||||
-- Current height above ground level.
|
||||
local agl=self.vec3.y-height
|
||||
|
||||
-- Estimated IP (if any)
|
||||
local ip=self:_GetIP(100)
|
||||
local ip=self:_GetIP(self.distIP)
|
||||
|
||||
-- Distance between positon and estimated impact.
|
||||
local d=0
|
||||
if ip then
|
||||
d=UTILS.VecDist3D(self.vec3, ip)
|
||||
end
|
||||
|
||||
-- Output.
|
||||
self:I(self.lid..string.format("T=%.3f: Height=%.3f m AGL=%.3f m, dIP=%.3f", time, height, agl, d))
|
||||
|
||||
end
|
||||
@@ -588,10 +754,12 @@ function WEAPON:_TrackWeapon(time)
|
||||
---------------------------
|
||||
|
||||
-- Get intercept point from position (p) and direction (x) in 50 meters.
|
||||
local ip = self:_GetIP(50)
|
||||
local ip = self:_GetIP(self.distIP)
|
||||
|
||||
if ip then
|
||||
env.info("FF Got intercept point!")
|
||||
if self.verbose>=10 and ip then
|
||||
|
||||
-- Output.
|
||||
self:I(self.lid.."Got intercept point!")
|
||||
|
||||
-- Coordinate of the impact point.
|
||||
local coord=COORDINATE:NewFromVec3(ip)
|
||||
@@ -603,7 +771,8 @@ function WEAPON:_TrackWeapon(time)
|
||||
-- Distance to last known pos.
|
||||
local d=UTILS.VecDist3D(ip, self.vec3)
|
||||
|
||||
env.info(string.format("FF d(ip, vec3)=%.3f meters", d))
|
||||
-- Output.
|
||||
self:I(self.lid..string.format("FF d(ip, vec3)=%.3f meters", d))
|
||||
|
||||
end
|
||||
|
||||
@@ -614,10 +783,15 @@ function WEAPON:_TrackWeapon(time)
|
||||
self.impactCoord=COORDINATE:NewFromVec3(self.vec3)
|
||||
|
||||
-- Mark impact point on F10 map.
|
||||
if self.markImpact then
|
||||
if self.impactMark then
|
||||
self.impactCoord:MarkToAll(string.format("Impact point of weapon %s\ntype=%s\nlauncher=%s", self.name, self.typeName, self.launcherName))
|
||||
end
|
||||
|
||||
-- Smoke on impact point.
|
||||
if self.impactSmoke then
|
||||
self.impactCoord:Smoke(self.impactSmokeColor)
|
||||
end
|
||||
|
||||
-- Call callback function.
|
||||
if self.impactFunc then
|
||||
self.impactFunc(self, unpack(self.impactArg or {}))
|
||||
@@ -642,12 +816,20 @@ end
|
||||
|
||||
--- Compute estimated intercept/impact point (IP) based on last known position and direction.
|
||||
-- @param #WEAPON self
|
||||
-- @param #number Distance Distance in meters. Default 20 m.
|
||||
-- @param #number Distance Distance in meters. Default 50 m.
|
||||
-- @return DCS#Vec3 Estimated intercept/impact point. Can also return `nil`, if no IP can be determined.
|
||||
function WEAPON:_GetIP(Distance)
|
||||
|
||||
-- Get intercept point from position (p) and direction (x) in 20 meters.
|
||||
local ip = land.getIP(self.pos3.p, self.pos3.x, Distance or 20) --DCS#Vec3
|
||||
Distance=Distance or 50
|
||||
|
||||
local ip=nil --DCS#Vec3
|
||||
|
||||
if Distance>0 and self.pos3 then
|
||||
|
||||
-- Get intercept point from position (p) and direction (x) in 20 meters.
|
||||
ip = land.getIP(self.pos3.p, self.pos3.x, Distance or 20) --DCS#Vec3
|
||||
|
||||
end
|
||||
|
||||
return ip
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user