Add checks and argument for ground station horizon
Signed-off-by: Pierros Papadeas <pierros@papadeas.gr>merge-requests/24/head
parent
5c2cca6dc8
commit
6869ce2635
|
@ -10,7 +10,7 @@ import argparse
|
|||
import logging
|
||||
from utils import get_active_transmitter_info, get_transmitter_stats, \
|
||||
get_groundstation_info, get_scheduled_passes_from_network, ordered_scheduler, \
|
||||
efficiency, find_passes, schedule_observation, read_priorities_transmitters, \
|
||||
report_efficiency, find_passes, schedule_observation, read_priorities_transmitters, \
|
||||
get_satellite_info, update_needed, get_priority_passes
|
||||
import settings
|
||||
from tqdm import tqdm
|
||||
|
@ -91,6 +91,10 @@ def main():
|
|||
help="Minimum horizon [default 0.0]",
|
||||
type=float,
|
||||
default=0.)
|
||||
parser.add_argument("-z",
|
||||
"--horizon",
|
||||
help="Don't respect station horizon (schedule 0 to 0 elevation)",
|
||||
action="store_true")
|
||||
parser.add_argument("-f",
|
||||
"--no-search-transmitters",
|
||||
help="Do not search good transmitters [default searching]",
|
||||
|
@ -137,13 +141,13 @@ def main():
|
|||
|
||||
# Settings
|
||||
ground_station_id = args.station
|
||||
if args.duration>0.0:
|
||||
if args.duration > 0.0:
|
||||
length_hours = args.duration
|
||||
else:
|
||||
length_hours = 1.0
|
||||
if args.wait<=0:
|
||||
if args.wait <= 0:
|
||||
wait_time_seconds = 0
|
||||
elif args.wait<=3600:
|
||||
elif args.wait <= 3600:
|
||||
wait_time_seconds = args.wait
|
||||
else:
|
||||
wait_time_seconds = 3600
|
||||
|
@ -189,8 +193,8 @@ def main():
|
|||
norad_cat_ids = sorted(
|
||||
set([
|
||||
transmitter["norad_cat_id"] for transmitter in transmitters.values()
|
||||
if transmitter["norad_cat_id"] < settings.MAX_NORAD_CAT_ID
|
||||
and transmitter["norad_cat_id"] in alive_norad_cat_ids
|
||||
if transmitter["norad_cat_id"] < settings.MAX_NORAD_CAT_ID and
|
||||
transmitter["norad_cat_id"] in alive_norad_cat_ids
|
||||
]))
|
||||
|
||||
# Store transmitters
|
||||
|
@ -228,7 +232,10 @@ def main():
|
|||
observer.lon = str(ground_station['lng'])
|
||||
observer.lat = str(ground_station['lat'])
|
||||
observer.elevation = ground_station['altitude']
|
||||
if not args.horizon:
|
||||
observer.horizon = str(ground_station['min_horizon'])
|
||||
minimum_altitude = max(ground_station['min_horizon'], min_horizon_arg)
|
||||
min_pass_duration = settings.MIN_PASS_DURATION
|
||||
|
||||
# Read tles
|
||||
with open(os.path.join(cache_dir, "tles_%d.txt" % ground_station_id), "r") as f:
|
||||
|
@ -250,7 +257,7 @@ def main():
|
|||
satellites.append(satellite(tle, uuid, success_rate, good_count, data_count))
|
||||
|
||||
# Find passes
|
||||
passes = find_passes(satellites, observer, tmin, tmax, minimum_altitude)
|
||||
passes = find_passes(satellites, observer, tmin, tmax, minimum_altitude, min_pass_duration)
|
||||
|
||||
priorities, favorite_transmitters = read_priorities_transmitters(priority_filename)
|
||||
|
||||
|
@ -273,10 +280,8 @@ def main():
|
|||
normalpasses = sorted(normalpasses, key=lambda satpass: -satpass['priority'])
|
||||
scheduledpasses = ordered_scheduler(normalpasses, scheduledpasses, wait_time_seconds)
|
||||
|
||||
# Compute scheduling efficiency
|
||||
dt, dttot, eff = efficiency(scheduledpasses)
|
||||
logging.info("%d passes selected out of %d, %.0f s out of %.0f s at %.3f%% efficiency" %
|
||||
(len(scheduledpasses), len(passes), dt, dttot, 100 * eff))
|
||||
# Report scheduling efficiency
|
||||
report_efficiency(scheduledpasses, passes)
|
||||
|
||||
# Find unique objects
|
||||
satids = sorted(set([satpass['id'] for satpass in passes]))
|
||||
|
|
|
@ -3,8 +3,9 @@ from decouple import config
|
|||
# Basic settings
|
||||
DB_BASE_URL = config('DB_BASE_URL', default='https://db.satnogs.org')
|
||||
NETWORK_BASE_URL = config('NETWORK_BASE_URL', default='https://network.satnogs.org')
|
||||
CACHE_AGE = config('CACHE_AGE', default=24)
|
||||
MAX_NORAD_CAT_ID = config('CACHE_AGE', default=90000)
|
||||
CACHE_AGE = config('CACHE_AGE', default=24) # In hours
|
||||
MAX_NORAD_CAT_ID = config('MAX_NORAD_CAT_ID', default=90000)
|
||||
MIN_PASS_DURATION = config('MIN_PASS_DURATION', default=2) # In minutes
|
||||
|
||||
# Credentials
|
||||
NETWORK_USERNAME = config('NETWORK_USERNAME', default='')
|
||||
|
|
74
utils.py
74
utils.py
|
@ -150,20 +150,24 @@ def overlap(satpass, scheduledpasses, wait_time_seconds):
|
|||
# Loop over scheduled passes
|
||||
for scheduledpass in scheduledpasses:
|
||||
# Test pass falls within scheduled pass
|
||||
if tr >= scheduledpass['tr'] and ts < scheduledpass['ts'] + timedelta(seconds=wait_time_seconds):
|
||||
if tr >= scheduledpass['tr'] and ts < scheduledpass['ts'] + timedelta(
|
||||
seconds=wait_time_seconds):
|
||||
overlap = True
|
||||
# Scheduled pass falls within test pass
|
||||
elif scheduledpass['tr'] >= tr and scheduledpass['ts'] + timedelta(seconds=wait_time_seconds) < ts:
|
||||
elif scheduledpass['tr'] >= tr and scheduledpass['ts'] + timedelta(
|
||||
seconds=wait_time_seconds) < ts:
|
||||
overlap = True
|
||||
# Pass start falls within pass
|
||||
elif tr >= scheduledpass['tr'] and tr < scheduledpass['ts'] + timedelta(seconds=wait_time_seconds):
|
||||
elif tr >= scheduledpass['tr'] and tr < scheduledpass['ts'] + timedelta(
|
||||
seconds=wait_time_seconds):
|
||||
overlap = True
|
||||
# Pass end falls within end
|
||||
elif ts >= scheduledpass['tr'] and ts < scheduledpass['ts'] + timedelta(seconds=wait_time_seconds):
|
||||
elif ts >= scheduledpass['tr'] and ts < scheduledpass['ts'] + timedelta(
|
||||
seconds=wait_time_seconds):
|
||||
overlap = True
|
||||
if overlap:
|
||||
break
|
||||
|
||||
|
||||
return overlap
|
||||
|
||||
|
||||
|
@ -186,29 +190,34 @@ def random_scheduler(passes, scheduledpasses, wait_time_seconds):
|
|||
return ordered_scheduler(passes, scheduledpasses, wait_time_seconds)
|
||||
|
||||
|
||||
def efficiency(passes):
|
||||
|
||||
# Loop over passes
|
||||
start = False
|
||||
for satpass in passes:
|
||||
if not start:
|
||||
dt = satpass['ts'] - satpass['tr']
|
||||
tmin = satpass['tr']
|
||||
tmax = satpass['ts']
|
||||
start = True
|
||||
else:
|
||||
dt += satpass['ts'] - satpass['tr']
|
||||
if satpass['tr'] < tmin:
|
||||
def report_efficiency(scheduledpasses, passes):
|
||||
if scheduledpasses:
|
||||
# Loop over passes
|
||||
start = False
|
||||
for satpass in scheduledpasses:
|
||||
if not start:
|
||||
dt = satpass['ts'] - satpass['tr']
|
||||
tmin = satpass['tr']
|
||||
if satpass['ts'] > tmax:
|
||||
tmax = satpass['ts']
|
||||
# Total time covered
|
||||
dttot = tmax - tmin
|
||||
start = True
|
||||
else:
|
||||
dt += satpass['ts'] - satpass['tr']
|
||||
if satpass['tr'] < tmin:
|
||||
tmin = satpass['tr']
|
||||
if satpass['ts'] > tmax:
|
||||
tmax = satpass['ts']
|
||||
# Total time covered
|
||||
dttot = tmax - tmin
|
||||
|
||||
return dt.total_seconds(), dttot.total_seconds(), dt.total_seconds() / dttot.total_seconds()
|
||||
logging.info("%d passes selected out of %d, %.0f s out of %.0f s at %.3f%% efficiency" %
|
||||
(len(scheduledpasses), len(passes), dt.total_seconds(), dttot.total_seconds(),
|
||||
100 * dt.total_seconds() / dttot.total_seconds()))
|
||||
|
||||
else:
|
||||
logging.info("No appropriate passes found for scheduling.")
|
||||
|
||||
|
||||
def find_passes(satellites, observer, tmin, tmax, minimum_altitude):
|
||||
def find_passes(satellites, observer, tmin, tmax, minimum_altitude, min_pass_duration):
|
||||
# Loop over satellites
|
||||
passes = []
|
||||
passid = 0
|
||||
|
@ -226,6 +235,7 @@ def find_passes(satellites, observer, tmin, tmax, minimum_altitude):
|
|||
# Loop over passes
|
||||
keep_digging = True
|
||||
while keep_digging:
|
||||
sat_ephem.compute(observer)
|
||||
try:
|
||||
tr, azr, tt, altt, ts, azs = observer.next_pass(sat_ephem)
|
||||
except ValueError:
|
||||
|
@ -248,13 +258,21 @@ def find_passes(satellites, observer, tmin, tmax, minimum_altitude):
|
|||
break
|
||||
passid += 1
|
||||
|
||||
# show only if >= configured horizon and in next 6 hours,
|
||||
pass_duration = (ts.datetime() - tr.datetime()) / timedelta(minutes=1)
|
||||
|
||||
# show only if >= configured horizon and till tmax,
|
||||
# and not directly overhead (tr < ts see issue 199)
|
||||
|
||||
if tr < ephem.date(tmax):
|
||||
if (float(elevation) >= minimum_altitude and tr < ts):
|
||||
if (float(elevation) >= minimum_altitude and tr < ts and
|
||||
pass_duration > min_pass_duration):
|
||||
valid = True
|
||||
|
||||
# invalidate passes that start too soon
|
||||
if tr < ephem.Date(datetime.now() + timedelta(minutes=5)):
|
||||
valid = False
|
||||
|
||||
# get pass information
|
||||
satpass = {
|
||||
'passid': passid,
|
||||
'mytime': str(observer.date),
|
||||
|
@ -312,8 +330,8 @@ def get_groundstation_info(ground_station_id):
|
|||
logging.info("Requesting information for ground station %d" % ground_station_id)
|
||||
|
||||
# Loop
|
||||
found = False
|
||||
r = requests.get("{}/api/stations/?id={:d}".format(settings.NETWORK_BASE_URL, ground_station_id))
|
||||
r = requests.get("{}/api/stations/?id={:d}".format(settings.NETWORK_BASE_URL,
|
||||
ground_station_id))
|
||||
|
||||
selected_stations = list(filter(lambda s: s['id'] == ground_station_id, r.json()))
|
||||
|
||||
|
@ -328,7 +346,7 @@ def get_groundstation_info(ground_station_id):
|
|||
if station['status'] == 'Online' or station['status'] == 'Testing':
|
||||
return station
|
||||
else:
|
||||
logging.info("Ground station {} neither in 'online' nor in 'testing' mode, " \
|
||||
logging.info("Ground station {} neither in 'online' nor in 'testing' mode, "
|
||||
"can't schedule!".format(ground_station_id))
|
||||
return {}
|
||||
|
||||
|
|
Loading…
Reference in New Issue