wxrx/predict_passes.sh

184 lines
4.8 KiB
Bash
Raw Permalink Normal View History

2022-07-06 16:57:31 -07:00
#!/usr/bin/env bash
2022-01-27 16:33:13 -08:00
## Predict future passes
##
## Usage: __PROG__ [options]
##
2022-01-28 16:59:08 -08:00
## Reports tab delimited passes in the form:
## [starttime] [duration] [satellite]
2022-01-27 16:33:13 -08:00
##
prog="$0"
2022-02-02 07:27:26 -08:00
me=${HELP:-`basename "$prog"`}
2022-02-02 09:22:29 -08:00
root_dir=$(dirname $(realpath $0))
source ${root_dir}/lib/utils.sh
2022-01-27 16:33:13 -08:00
# default values
tlefile=${tlefile:=satellites.tle}
2022-01-28 07:34:57 -08:00
min_duration=${min_duration:=0}
min_elevation=${min_elevation:=45}
2022-01-28 16:59:08 -08:00
max_aos=$(expr 86400 + $(date +%s))
2022-07-04 12:57:42 -07:00
date_format='+%F %T'
2022-01-27 16:33:13 -08:00
## Options:
while (( "$#" ));
do
## --help, -h Help message
case "${1}" in
'--help' | '-h')
usage
exit
;;
# --bar [baz] Optional value
'--bar')
if [[ -z $2 ]] || [[ $2 == -* ]] ; then
bar="default"
else
bar=$2
shift
fi
;;
2022-01-28 16:59:08 -08:00
## --all, -a Don't exclude any passes
'--all' | '-a')
min_duration=0
min_elevation=0
;;
2022-07-04 12:57:42 -07:00
## --date-format <string> Specify a date format string
'--date-format')
if [[ $# -lt 2 ]] || [[ $2 == -* ]] ; then
logerr "Option ${1} requires an argument"
usage
exit 1
fi
date_format=${2}
shift
;;
2022-01-28 07:34:57 -08:00
## --min-duration <seconds> Minimum duration to include in report (default 0)
2022-01-27 16:33:13 -08:00
'--min-duration')
# check that $2 exists and is not another flag
if [[ $# -lt 2 ]] || [[ $2 == -* ]] ; then
logerr "Option ${1} requires an argument"
usage
exit 1
fi
# integers only
if ! [[ "$2" =~ ^[0-9]+$ ]]; then
logerr "Option ${1} must have an integer argument"
usage
exit 1
fi
min_duration=${2}
shift
;;
2022-01-28 16:59:08 -08:00
## --min-elevation <degrees> Satellite must rise above this elevation (default 45)
2022-01-28 07:34:57 -08:00
'--min-elevation')
# check that $2 exists and is not another flag
if [[ $# -lt 2 ]] || [[ $2 == -* ]] ; then
2022-01-28 16:59:08 -08:00
logerr "option ${1} requires an argument"
2022-01-28 07:34:57 -08:00
usage
exit 1
fi
# integers only
if ! [[ "$2" =~ ^[0-9]+$ ]]; then
2022-01-28 16:59:08 -08:00
logerr "option ${1} must have an integer argument"
2022-01-28 07:34:57 -08:00
usage
exit 1
fi
min_elevation=${2}
shift
;;
2022-01-28 16:59:08 -08:00
## --look-ahead <hours> Hours in advance to predict (default: 24)
'--look-ahead')
# check that $2 exists and is not another flag
if [[ $# -lt 2 ]] || [[ $2 == -* ]] ; then
logerr "option ${1} requires an argument"
usage
exit 1
fi
# integers only
if ! [[ "$2" =~ ^[0-9]+$ ]]; then
logerr "option ${1} must have an integer argument"
usage
exit 1
fi
max_aos=$(expr $(expr "$2" \* 3600) + $(date +%s))
shift
;;
2022-01-27 16:33:13 -08:00
*)
logerr "Unknown option %s" ${1}
usage
exit 1
;;
esac
shift
done
# Check `predict` command exists
if ! command -v 'predict' &> /dev/null
then
logerr "Missing dependency 'predict'. Get it from 'https://www.qsl.net/kd2bd/predict.html'"
exit 3
fi
# Check tle file exists
if [ ! -e ${tlefile} ]; then
logerr "Missing satellite telemetry file ${tlefile}"
exit 2
fi
2022-01-28 16:59:08 -08:00
# Produces a single line prediction
# @param satellite name (ex: 'NOAA-15')
# @param unix timestamp (default: now)
# @output writes to stdout '<aos timestamp> <duration seconds> <elevation> <sat name>'
2022-01-27 16:33:13 -08:00
function prediction() {
2022-01-28 16:59:08 -08:00
sat_name=${1:-'NOAA-15'}
timestamp=${2}
pass=$(predict -t satellites.tle -p "${sat_name}" "${timestamp}")
2022-01-27 16:33:13 -08:00
aos=$(printf "%s\n" "$pass" | head -n 1 | cut -d ' ' -f 1)
los=$(printf "%s\n" "$pass" | tail -n 1 | cut -d ' ' -f 1)
2022-01-28 07:34:57 -08:00
ele=$(printf "%s\n" "$pass" | awk 'BEGIN{a=0}{if ($5>0+a) a=$5} END{print a}')
2022-01-27 16:33:13 -08:00
duration=$(expr ${los} - ${aos})
2022-01-28 16:59:08 -08:00
printf "%s\t%s\t%s\t%s\n" "${aos}" "${duration}" "${ele}" "${sat_name}"
}
2022-01-28 07:34:57 -08:00
2022-01-28 16:59:08 -08:00
#
# Predicts all passes of a satellite until $max_aos
# satisfying max_duration and max_elevation
# @param satellite name
# @global min_duration
# @global min_elevation
# @global max_aos
2022-07-04 12:57:42 -07:00
# @global date_format (default '+%F %T')
2022-01-28 16:59:08 -08:00
# @output '<human-timestamp> <seconds duration> <sat_name>'
function predict_all() {
sat_name=${1:-'NOAA 15'}
last_aos=$(date +%s)
while [ $last_aos -lt $max_aos ]; do
pass=$(prediction "${sat_name}" "${last_aos}")
aos=$(printf "%s" "$pass" | cut -f 1)
duration=$(printf "%s" "$pass" | cut -f 2)
ele=$(printf "%s" "$pass" | cut -f 3)
2022-07-04 12:57:42 -07:00
starttime=$(date -d @${aos} "${date_format:-'+%F %T'}")
2022-01-28 16:59:08 -08:00
last_aos=$(expr 90 + $(expr ${aos} + ${duration}))
# if min_duration and min_elevation satisfied, print
if [ ${min_duration:-0} -lt ${duration} ] && [ ${min_elevation:-0} -lt ${ele} ] ; then
printf "%s\t%s\t%s\n" "${starttime}" "${duration}" "${sat_name}"
fi
done
2022-01-27 16:33:13 -08:00
}
2022-01-28 16:59:08 -08:00
2022-01-27 16:33:13 -08:00
predictions=$(for satellite in 'NOAA 15' 'NOAA 18' 'NOAA 19'; do
2022-01-28 16:59:08 -08:00
predict_all "${satellite}"
2022-01-27 16:33:13 -08:00
done | sort)
printf "%s\n" "${predictions}"
exit # normal exit