Merge branch 'master' into 'master'

Azimuth window option

See merge request librespacefoundation/satnogs/satnogs-auto-scheduler!42
merge-requests/42/merge
Dr. Pedro E. Colla 2019-10-07 16:51:08 +00:00
commit de45371e0f
6 changed files with 208 additions and 14 deletions

View File

@ -57,6 +57,17 @@ Add a line like this - execute the scheduling script on each full hour:
Omit the `-f` option to also fill in the gaps, but be aware if using a rotator setup! This will wear-out your rotator very quickly!
Add `-w 60` for a delay if you want to give your rotator a bit of time (60 s) to reset or home.
## Azimut window filtering
This experimental feature allows to improve the quality of the passes taken by making a given azimuth window blind to the schedulling
process, this might help to avoid a natural or man-made visibility obstacle or to accomodate for a given antenna receiving pattern.
option --azmin xxx --azmax yyy where xxx and yyy are the minimum and maximum azimuth windows in degrees.
* specifying 345-015 would only schedule passes rising or setting at Az between 345 and 015
* specifying 015-360 will skip all passes rising or setting between 000 and 015
* specifying 180-045 will avoid all passes rising or setting between 045 and 180
* ... and so on
## Usage

49
planSatNOGS.sh 100755
View File

@ -0,0 +1,49 @@
#!/bin/sh
#*--------------------------------------------------------------------
#* planSatNOGS.sh
#*
#* Script to load SatNOGS observations automatically
#*
#*--------------------------------------------------------------------
ID=499
TIME=24.0
PRIORITY="priorities_$ID.txt"
TRANSMITTERS="/tmp/cache/transmitters_$ID.txt"
OPS=" -f -l INFO"
MODES="CW"
NORAD=" 20442 "
EXCLUIDO="43466 39430 43591"
AZMIN=" --azmin 335 "
AZMAX=" --azmax 25 "
ELMIN=" --elmin 20 "
echo "*********************"
echo "* Set priorities *"
echo "*********************"
rm -r $PRIORITY
#*---- Include satellites by mode
for mode in $MODES; do
echo "Selecting priority for Mode($mode)"
awk '{if ($3>=80) print $0 }' $TRANSMITTERS | grep -e $mode | awk '{printf("%s 1.0 %s\n",$1,$2)}' | tee -a $PRIORITY
done
#*---- Include satellites despite of the mode by NORAD Id
for norad in $NORAD; do
echo "Selecting priority for Satellite($NORAD)"
awk '{if ($3>=80) print $0 }' $TRANSMITTERS | grep -e $norad | awk '{printf("%s 1.0 %s\n",$1,$2)}' | tee -a $PRIORITY
done
#*---- Remove unwanted satellites
for excl in $EXCLUIDO; do
echo "Excluding satellite $excl"
awk '!/$excl/' priorities_499.txt > temp && mv temp priorities_499.txt
done
echo "$(date) planSatNOGS: $(cat $PRIORITY | wc -l) satellites prioritized" | logger -i -t "$ID"
echo "$(date) planSatNOGS: Parameters ID($ID) Time($TIME) Prio($PRIORITY) Az($AZMIN-$AZMAX) El($ELMIN) Ops($OPS)"
echo "*********************"
echo "* Scheduling passes *"
echo "*********************"
python /home/pi/satnogs-auto-scheduler/schedule_single_station.py -s $ID -d $TIME -P $PRIORITY $AZMIN $AZMAX $ELMIN $OPS
exit 0

23
priorities_499.txt 100644
View File

@ -0,0 +1,23 @@
27848 1.0 aBHGFxMopeCscUYRyiYdXC
42792 1.0 AoDzLwqzB8jt4sFQmmBxRo
41340 1.0 BRs3oJkUeAmQbLsJFaUuBP
41340 1.0 c2yGXJPJH5jXjQ3dcyhWXH
44329 1.0 fB7B6jkc7fUcMhYrP3xJU8
41460 1.0 gEDKtJFX6d7kM6xUAM4MJ8
42790 1.0 LVJfPNYASyQ3PUBvcpxLwn
33493 1.0 MLBshLfC6cFP4AsoaR2MWh
27844 1.0 mqQF9JxmD4KB6MqTVXqQBQ
33499 1.0 MquDcKUEW6mR3VP3M2vAdQ
44331 1.0 mwLCtnmHojERWGKTnMT6Kj
32791 1.0 N7SGiqMhkHpjfjeGh42wvX
43591 1.0 NwfFCEAaoAnX3DhjdzS4qg
44330 1.0 osebQczQC5X852ueXKBXjH
43466 1.0 qPdK6RfA6UPT8CWogypiz4
42775 1.0 rAtiFkr9f4e7PnGAxcWxkF
33493 1.0 rmv9kRFrXDtQ8H7wucWwbm
32785 1.0 SqKWM4e6CfqZ9JryAZcJTf
39430 1.0 ULXxBCypZh4f2qPnJeg6WH
43677 1.0 w7P94GHjtdfjHnYG9RrkHJ
43937 1.0 w9atysxgD3MMHnX2Rv3svC
35935 1.0 WjSuDmnkX32dASG7NqajhU
20442 1.0 ZAKErADdWKpMiDjvKKhmmB

View File

@ -0,0 +1,19 @@
27848 1.0 aBHGFxMopeCscUYRyiYdXC
42792 1.0 AoDzLwqzB8jt4sFQmmBxRo
41340 1.0 BRs3oJkUeAmQbLsJFaUuBP
41340 1.0 c2yGXJPJH5jXjQ3dcyhWXH
41460 1.0 gEDKtJFX6d7kM6xUAM4MJ8
42790 1.0 LVJfPNYASyQ3PUBvcpxLwn
33493 1.0 MLBshLfC6cFP4AsoaR2MWh
27844 1.0 mqQF9JxmD4KB6MqTVXqQBQ
33499 1.0 MquDcKUEW6mR3VP3M2vAdQ
32791 1.0 N7SGiqMhkHpjfjeGh42wvX
43591 1.0 NwfFCEAaoAnX3DhjdzS4qg
43466 1.0 qPdK6RfA6UPT8CWogypiz4
42775 1.0 rAtiFkr9f4e7PnGAxcWxkF
33493 1.0 rmv9kRFrXDtQ8H7wucWwbm
32785 1.0 SqKWM4e6CfqZ9JryAZcJTf
43677 1.0 w7P94GHjtdfjHnYG9RrkHJ
43937 1.0 w9atysxgD3MMHnX2Rv3svC
35935 1.0 WjSuDmnkX32dASG7NqajhU
20442 1.0 ZAKErADdWKpMiDjvKKhmmB

View File

@ -72,8 +72,28 @@ def _log_level_string_to_int(log_level_string):
return log_level_int
#*-----------------------------------------------------------------------------------
#* checkAz
#* Function to compute if Az is within a given Azimuth window
#*-----------------------------------------------------------------------------------
def checkAz(Az,Azmin,Azmax):
if Az == 0:
return True
if Azmin>Azmax:
if(Az>=Azmin) or (Az<=Azmax):
return True
else:
return False
else:
if (Az>=Azmin) and (Az<=Azmax):
return True
else:
return False
#*-------------------------------------------------------------------------------
def main():
# Parse arguments
parser = argparse.ArgumentParser(
description="Automatically schedule observations on a SatNOGS station.")
@ -97,6 +117,25 @@ def main():
help="Minimum rise/set elevation [degrees; ground station default, minimum: 0, maximum: 90]",
type=float,
default=None)
#*-------------------------------------------------------------------------------------------------
#* define two new arguments to specify Az (min,max) window
#*-------------------------------------------------------------------------------------------------
parser.add_argument("-e",
"--elmin",
help="Minimum pass elevation admitted [degrees; ground station default=0,maximum: 90]",
type=float,
default=None)
parser.add_argument("-a",
"--azmin",
help="Minimum Az window [degrees; ground station default=0,maximum: 359]",
type=float,
default=None)
parser.add_argument("-A",
"--azmax",
help="Maximum Az window [degrees; ground station default=0,maximum: 359]",
type=float,
default=None)
#*--------------------------------------------------------------------------------------------------
parser.add_argument("-z",
"--horizon",
help="Force rise/set elevation to 0 degrees (overrided -r).",
@ -157,6 +196,7 @@ def main():
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# Settings
ground_station_id = args.station
if args.duration > 0.0:
length_hours = args.duration
@ -174,6 +214,23 @@ def main():
min_priority = 1.0
else:
min_priority = args.min_priority
if (args.elmin >=0) and (args.elmin <=90):
elmin=args.elmin
else:
elmin=0
if (args.azmin >= 0) and (args.azmin <= 360):
azmin=args.azmin
else:
azmin=0
if (args.azmax>=0) and (args.azmax<=360):
azmax=args.azmax
else:
azmax=365
cache_dir = "/tmp/cache"
schedule = not args.dryrun
only_priority = args.only_priority
@ -193,6 +250,9 @@ def main():
if not os.path.isdir(cache_dir):
os.mkdir(cache_dir)
# Printing Az window
logging.info('Pass window set as Az Min(%3.0f) Max(%3.0f) and El Min(%3.0f)' % (azmin,azmax,elmin))
# Update logic
update = update_needed(tnow, ground_station_id, cache_dir)
@ -322,6 +382,7 @@ def main():
# Priority scheduler
prioritypasses = sorted(prioritypasses, key=lambda satpass: -satpass['priority'])
scheduledpasses = ordered_scheduler(prioritypasses, scheduledpasses, wait_time_seconds)
for satpass in passes:
logging.debug(satpass)
@ -337,15 +398,20 @@ def main():
schedule_needed = False
logging.info("GS | Sch | NORAD | Start time | End time | El | " +
"Priority | Transmitter UUID | Mode | Satellite name ")
#*----- Modify to add AzR and AzS
logging.info("GS | Sch | NORAD | Start time | End time | El | AzR | AzS | Priority | Transmitter UUID | Mode | Satellite name ")
for satpass in sorted(scheduledpasses, key=lambda satpass: satpass['tr']):
logging.info(
"%3d | %3.d | %05d | %s | %s | %3.0f | %4.6f | %s | %-10s | %s" %
(ground_station_id, satpass['scheduled'], int(
satpass['id']), satpass['tr'].strftime("%Y-%m-%dT%H:%M:%S"),
satpass['ts'].strftime("%Y-%m-%dT%H:%M:%S"), float(satpass['altt']) if satpass['altt']
else 0., satpass['priority'], satpass['uuid'], satpass['mode'], satpass['name'].rstrip()))
#*----- Modify to add AzR and AzS
logging.info("%3d | %3.d | %05d | %s | %s | %3.0f | %3.0f | %3.0f | %4.6f | %s | %-10s | %s" %
(ground_station_id, satpass['scheduled'], int(satpass['id']), satpass['tr'].strftime("%Y-%m-%dT%H:%M:%S"),
satpass['ts'].strftime("%Y-%m-%dT%H:%M:%S"), float(satpass['altt']),float(satpass['azr']),float(satpass['azs']),
float(satpass['priority']), satpass['uuid'], satpass['mode'], satpass['name'].rstrip()))
#Aqui es la intervencion para evitar scheduling, se le pasa schedule_needed=False y a otra cosa
if not satpass['scheduled']:
schedule_needed = True
@ -379,15 +445,38 @@ def main():
logging.info('Checking and scheduling passes as needed.')
for satpass in tqdm(scheduledpasses_sorted):
if not satpass['scheduled']:
logging.debug("Scheduling %05d %s %s %3.0f %4.3f %s %s" %
(int(satpass['id']), satpass['tr'].strftime("%Y-%m-%dT%H:%M:%S"),
satpass['ts'].strftime("%Y-%m-%dT%H:%M:%S"), float(satpass['altt']),
satpass['priority'], satpass['uuid'], satpass['name'].rstrip()))
schedule_observation(session, int(satpass['id']), satpass['uuid'],
#logging.debug("Scheduling %05d %s %s %3.0f %4.3f %s %s" %
#logging.info("Scheduling %05d %s %s %3.0f %4.3f %s %s" %
# (int(satpass['id']), satpass['tr'].strftime("%Y-%m-%dT%H:%M:%S"),
# satpass['ts'].strftime("%Y-%m-%dT%H:%M:%S"), float(satpass['altt']),
# satpass['priority'], satpass['uuid'], satpass['name'].rstrip()))
#*------ Filter passes based on Az Window
if ((checkAz(float(satpass['azr']),azmin,azmax)) or (checkAz(float(satpass['azs']),azmin,azmax))) and (float(satpass['altt'])>=elmin):
logging.info("\n")
logging.info("scheduling Sat(%d) UUID(%s) Rise(%s) Set(%s) El(%3.0f)" % (int(satpass['id']),satpass['uuid'],
satpass['tr'].strftime("%Y-%m-%d %H:%M:%S") + ".000",
satpass['ts'].strftime("%Y-%m-%d %H:%M:%S") + ".000",float(satpass['altt'])))
schedule_observation(session, int(satpass['id']), satpass['uuid'],
ground_station_id,
satpass['tr'].strftime("%Y-%m-%d %H:%M:%S") + ".000",
satpass['ts'].strftime("%Y-%m-%d %H:%M:%S") + ".000")
logging.info("\n")
else:
logging.info("\n")
logging.info("rejecting Sat(%d) UUID(%s) Rise(%s) Set(%s) El(%3.0f)" % (int(satpass['id']),satpass['uuid'],
satpass['tr'].strftime("%Y-%m-%d %H:%M:%S") + ".000",
satpass['ts'].strftime("%Y-%m-%d %H:%M:%S") + ".000",float(satpass['altt'])))
logging.info("\n")
#*------------------------------------------------------------------------------------------------------------------------
logging.info("All passes are scheduled. Exiting!")

View File

@ -116,6 +116,7 @@ def get_scheduled_passes_from_network(ground_station, tmin, tmax):
break
# r.json() is a list of dicts/observations
# added empty azr and azs keys in order to properly merge later with values from computed pass and be able to filter based on az window
for o in r.json():
satpass = {
"id": o['norad_cat_id'],
@ -126,7 +127,9 @@ def get_scheduled_passes_from_network(ground_station, tmin, tmax):
"priority": 1,
"uuid": o['transmitter'],
"name": '',
"mode": ''
"mode": '',
"azr":0,
"azs":0
}
if satpass['ts'] > tmin and satpass['tr'] < tmax: