I asked it to generate a script to monitor a series of satellites against a downlink ground station. In this example, several ELINT birds looking to dump their data to NF fleet headquarters in Severomorsk. The script calculates the altitude of the bird and its field of view against the curvature of the earth. I have this LUA script currently on a timer executing every minute. There is a slight hiccup of course as it runs the calculation but its only noticeable on the higher time compression settings.
This should allow you to simulate a realistic Cold War era space based EO and LEO SIGINT/ELINT constellation.
Code: Select all
-- Define parameters
local comms_unit_name = "Severomorsk" -- Name of the ground station with the comms gear
local monitored_units = {"Kosmos 1603", "Kosmos 1656", "Kosmos 1697", "Kosmos 1714", "Kosmos 1844", "Kosmos 1943", "Kosmos 1980", "Kosmos 2082"} -- List of satellites being monitored
-- Earth radius in meters
local earth_radius = 6371000
-- Get reference to the ground station
local comms_unit = ScenEdit_GetUnit({name = comms_unit_name})
-- Check if the ground station exists
if comms_unit == nil then
print("Error: Ground station with downlink not found.")
return
end
-- Get the position of the ground station
local comms_unit_lat = math.rad(comms_unit.latitude)
local comms_unit_lon = math.rad(comms_unit.longitude)
local comms_unit_alt = comms_unit.altitude or 0 -- Ground station altitude (should be near zero)
-- Function to calculate angular separation between two points on a sphere
local function calculate_angular_distance(lat1, lon1, lat2, lon2)
return math.acos(math.sin(lat1) * math.sin(lat2) + math.cos(lat1) * math.cos(lat2) * math.cos(lon1 - lon2))
end
-- Function to calculate line-of-sight range based on altitudes
local function calculate_los_range(alt_ground, alt_satellite)
local ground_to_horizon = math.sqrt((earth_radius + alt_ground)^2 - earth_radius^2)
local sat_to_horizon = math.sqrt((earth_radius + alt_satellite)^2 - earth_radius^2)
return ground_to_horizon + sat_to_horizon
end
-- Iterate through the list of satellites
for _, satellite_name in ipairs(monitored_units) do
-- Get reference to the satellite
local monitored_unit = ScenEdit_GetUnit({name = satellite_name})
-- Check if the satellite exists
if monitored_unit == nil then
print("Error: Monitored satellite '" .. satellite_name .. "' not found.")
else
-- Get the position of the satellite
local monitored_unit_lat = math.rad(monitored_unit.latitude)
local monitored_unit_lon = math.rad(monitored_unit.longitude)
local monitored_unit_alt = monitored_unit.altitude or 0 -- Satellite altitude
-- Calculate the maximum line-of-sight range
local los_range = calculate_los_range(comms_unit_alt, monitored_unit_alt)
-- Calculate the angular distance between the ground station and the satellite
local angular_distance = calculate_angular_distance(comms_unit_lat, comms_unit_lon, monitored_unit_lat, monitored_unit_lon)
-- Convert angular distance to a great-circle distance in meters
local great_circle_distance = angular_distance * earth_radius
-- Check if the satellite is within line-of-sight range
if great_circle_distance > los_range then
-- Set the monitored unit out of communication
ScenEdit_SetUnit({name = satellite_name, outofcomms = true})
print(satellite_name .. " is out of communication.")
else
-- Ensure the monitored unit is in communication
ScenEdit_SetUnit({name = satellite_name, outofcomms = false})
print(satellite_name .. " is in communication.")
end
end
end