Add checks and argument for ground station horizon

Signed-off-by: Pierros Papadeas <pierros@papadeas.gr>
merge-requests/24/head
Pierros Papadeas 2019-05-11 23:55:14 +03:00
parent 5c2cca6dc8
commit 6869ce2635
No known key found for this signature in database
GPG Key ID: 8DB97129D9982991
3 changed files with 65 additions and 41 deletions

View File

@ -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]))

View File

@ -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='')

View File

@ -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 {}