Merge branch 'master' into 'master'
Azimuth window option See merge request librespacefoundation/satnogs/satnogs-auto-scheduler!42merge-requests/42/merge
commit
de45371e0f
11
README.md
11
README.md
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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!")
|
||||
|
||||
|
||||
|
|
5
utils.py
5
utils.py
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue