Satellite Store and Forward LUA Script

All discussions & material related to Command's Lua interface

Moderators: RoryAndersonCDT, michaelm75au, angster, MOD_Command

Post Reply
User avatar
ThunderCBR
Posts: 60
Joined: Sun Mar 02, 2014 4:27 pm
Location: Sterling, VA
Contact:

Satellite Store and Forward LUA Script

Post by ThunderCBR »

As a space professional, one of the annoying things about CMANO/CMO has always been the satellite comms for Cold War era intelligence assets. Back then, most satellites especially on the Soviet side relied on store and forward to disseminate their collects. Thus they required to be in range of their downlink ground station. But alas, its the year 2025 and ChatGPT to the rescue! I for one welcome our new AI overlords...

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
Parel803
Posts: 932
Joined: Thu Oct 10, 2019 3:39 pm
Location: Netherlands

Re: Satellite Store and Forward LUA Script

Post by Parel803 »

Good evening,
Thank you for sharing.
regards GJ
thewood1
Posts: 9916
Joined: Sun Nov 27, 2005 6:24 pm
Location: Boston

Re: Satellite Store and Forward LUA Script

Post by thewood1 »

Would it be simpler to have the satellite out of comms until it enters a zone around the downlink station. Then when it enters the zone, a trigger kicks of a single lua command to turn comms back on. You can make the zone any size. I actually used that in a scenario where I created multiple levels of delays to get info into a task force commander's hands.
User avatar
ThunderCBR
Posts: 60
Joined: Sun Mar 02, 2014 4:27 pm
Location: Sterling, VA
Contact:

Re: Satellite Store and Forward LUA Script

Post by ThunderCBR »

thewood1 wrote: Fri Feb 07, 2025 11:57 pm Would it be simpler to have the satellite out of comms until it enters a zone around the downlink station. Then when it enters the zone, a trigger kicks of a single lua command to turn comms back on. You can make the zone any size. I actually used that in a scenario where I created multiple levels of delays to get info into a task force commander's hands.
YES but...

That method is a simpler method that doesn't take into account the slant range to the bird based on its altitude. If all the LEO birds were at the same altitude I would 100% do as you've described. But this script I feel gives a better simulation of space to ground comms (well kinda, I just thought that I should add a check that its only in comms when at least 5 to 10 degrees above the horizon since you typically won't lock in the signal until its a few degrees elevation). Even that script doesn't take into account a lot of the other variables that go into spacecraft uplink and downlink comms like a full link budget analysis, but this is good enough for our needs. The script above will work on any satellite to a ground link since it calculates the correct field of view based on altitude, curvature of the earth, etc to determine if the ground station can see the satellite as it peaks over the horizon.

So short answer is yeah, if looking for a basic approximation of all LEO constellations then you can do as you described. You'd just have to calculate the FOV of the constellation you want to model in order to set the circle range from the ground station. I guess if you only have a single constellation in your scenario at a specific altitude then yeah your idea would work perfectly as well.
RidgeMadden
Posts: 1
Joined: Thu Jan 30, 2025 6:10 am

Re: Satellite Store and Forward LUA Script

Post by RidgeMadden »

This LUA script is a great solution for simulating satellite communication in a Cold War era space scenario. It efficiently monitors satellites like Kosmos units and checks if they’re in communication with the Severomorsk ground station, factoring in altitude and line-of-sight calculations. The script is well-structured and can realistically model ELINT/EO satellites. If you have academic assignments to submit and need assistance, I found an online platform OxEssays. Visit https://oxessays.com/do-my-assignment to explore how they can assist you with your academic needs. OxEssays offers a fantastic do my assignment service to help you get it done.
Post Reply

Return to “Lua Legion”