Removed all java dependencies from domain.predict package

pull/87/head
Arty Bishop 2021-10-28 19:32:21 +01:00
rodzic 8ef0d103e4
commit 88c7bb6bca
5 zmienionych plików z 67 dodań i 77 usunięć

Wyświetl plik

@ -116,7 +116,7 @@ class MapViewModel @Inject constructor(
val currentTrack = mutableListOf<GeoPos>()
val endDate = Date(date.time + (satellite.orbitalPeriod * 2.4 * 60000L).toLong())
var oldLongitude = 0.0
predictor.getSatTrack(satellite, pos, date, endDate).forEach { satPos ->
predictor.getSatTrack(satellite, pos, date.time, endDate.time).forEach { satPos ->
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
val currentPosition = GeoPos(osmLat, osmLon)
@ -143,7 +143,7 @@ class MapViewModel @Inject constructor(
private suspend fun getPositions(satellites: List<Satellite>, pos: GeoPos, date: Date) {
val positions = mutableMapOf<Satellite, GeoPos>()
satellites.forEach { satellite ->
val satPos = predictor.getSatPos(satellite, pos, date)
val satPos = predictor.getSatPos(satellite, pos, date.time)
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
positions[satellite] = GeoPos(osmLat, osmLon)
@ -152,7 +152,7 @@ class MapViewModel @Inject constructor(
}
private suspend fun getSatFootprint(satellite: Satellite, pos: GeoPos, date: Date) {
val satPos = predictor.getSatPos(satellite, pos, date)
val satPos = predictor.getSatPos(satellite, pos, date.time)
val satFootprint = satPos.getRangeCircle().map { rangePos ->
val osmLat = clipLat(rangePos.latitude)
val osmLon = clipLon(rangePos.longitude)
@ -162,7 +162,7 @@ class MapViewModel @Inject constructor(
}
private suspend fun getSatData(satellite: Satellite, pos: GeoPos, date: Date) {
val satPos = predictor.getSatPos(satellite, pos, date)
val satPos = predictor.getSatPos(satellite, pos, date.time)
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
val osmPos = GeoPos(osmLat, osmLon)

Wyświetl plik

@ -49,12 +49,12 @@ class PassesViewModel @Inject constructor(
if (preferences.isSetupDone()) {
viewModelScope.launch {
_passes.postValue(DataState.Loading)
val dateNow = Date()
val timeNow = System.currentTimeMillis()
val satellites = dataRepository.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
val hoursAhead = preferences.getHoursAhead()
val minElev = preferences.getMinElevation()
predictor.triggerCalculation(satellites, stationPos, dateNow, hoursAhead, minElev)
predictor.triggerCalculation(satellites, stationPos, timeNow, hoursAhead, minElev)
}
} else {
_isFirstLaunchDone.value = false
@ -77,7 +77,7 @@ class PassesViewModel @Inject constructor(
val minElev = preferences.getMinElevation()
dataRepository.updateDataFromWeb()
dataRepository.updateSelection(isSelected = true)
predictor.forceCalculation(satellites, stationPos, Date(), hoursAhead, minElev)
predictor.forceCalculation(satellites, stationPos, Date().time, hoursAhead, minElev)
preferences.setSetupDone()
_isFirstLaunchDone.value = true
}
@ -87,12 +87,12 @@ class PassesViewModel @Inject constructor(
viewModelScope.launch {
_passes.postValue(DataState.Loading)
passesProcessing?.cancelAndJoin()
val dateNow = Date()
val timeNow = System.currentTimeMillis()
val satellites = dataRepository.getSelectedSatellites()
val stationPos = preferences.loadStationPosition()
val hoursAhead = preferences.getHoursAhead()
val minElev = preferences.getMinElevation()
predictor.forceCalculation(satellites, stationPos, dateNow, hoursAhead, minElev)
predictor.forceCalculation(satellites, stationPos, timeNow, hoursAhead, minElev)
}
}

Wyświetl plik

@ -79,12 +79,12 @@ class RadarViewModel @Inject constructor(
viewModelScope.launch {
var satTrack: List<SatPos> = emptyList()
if (!satPass.isDeepSpace) {
val startDate = Date(satPass.aosTime)
val endDate = Date(satPass.losTime)
val startDate = satPass.aosTime
val endDate = satPass.losTime
satTrack = predictor.getSatTrack(satPass.satellite, stationPos, startDate, endDate)
}
while (isActive) {
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date())
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date().time)
if (preferences.isRotatorEnabled()) {
val server = preferences.getRotatorServer().first
val port = preferences.getRotatorServer().second
@ -102,7 +102,7 @@ class RadarViewModel @Inject constructor(
viewModelScope.launch {
val transmitters = dataRepository.getTransmitters(satPass.catNum)
while (isActive) {
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date())
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date().time)
val copiedList = transmitters.map { it.copy() }
copiedList.forEach { transmitter ->
transmitter.downlink?.let {

Wyświetl plik

@ -21,7 +21,6 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.withContext
import java.util.*
class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
@ -29,26 +28,26 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
private var selectedSatIds = emptyList<Int>()
val passes: SharedFlow<List<SatPass>> = _passes
suspend fun getSatPos(sat: Satellite, pos: GeoPos, date: Date): SatPos =
withContext(predictorDispatcher) {
return@withContext sat.getPosition(pos, date.time)
}
suspend fun getSatPos(sat: Satellite, pos: GeoPos, time: Long): SatPos {
return withContext(predictorDispatcher) { sat.getPosition(pos, time) }
}
suspend fun getSatTrack(sat: Satellite, pos: GeoPos, start: Date, end: Date): List<SatPos> =
withContext(predictorDispatcher) {
suspend fun getSatTrack(sat: Satellite, pos: GeoPos, start: Long, end: Long): List<SatPos> {
return withContext(predictorDispatcher) {
val positions = mutableListOf<SatPos>()
var currentTime = start.time
while (currentTime < end.time) {
var currentTime = start
while (currentTime < end) {
positions.add(sat.getPosition(pos, currentTime))
currentTime += 15000
}
return@withContext positions
positions
}
}
suspend fun triggerCalculation(
satellites: List<Satellite>,
pos: GeoPos,
date: Date = Date(),
time: Long,
hoursAhead: Int = 8,
minElevation: Double = 16.0
) {
@ -57,7 +56,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
} else {
val newCatNums = satellites.map { it.params.catnum }
if (selectedSatIds != newCatNums) {
forceCalculation(satellites, pos, date, hoursAhead, minElevation)
forceCalculation(satellites, pos, time, hoursAhead, minElevation)
}
}
}
@ -65,7 +64,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
suspend fun forceCalculation(
satellites: List<Satellite>,
pos: GeoPos,
date: Date = Date(),
time: Long,
hoursAhead: Int = 8,
minElevation: Double = 16.0
) {
@ -76,31 +75,31 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
val allPasses = mutableListOf<SatPass>()
selectedSatIds = satellites.map { it.params.catnum }
satellites.forEach { satellite ->
allPasses.addAll(satellite.getPasses(pos, date, hoursAhead))
allPasses.addAll(satellite.getPasses(pos, time, hoursAhead))
}
_passes.emit(allPasses.filter(date, hoursAhead, minElevation))
_passes.emit(allPasses.filter(time, hoursAhead, minElevation))
}
}
}
private fun Satellite.getPasses(pos: GeoPos, date: Date, hours: Int): List<SatPass> {
private fun Satellite.getPasses(pos: GeoPos, time: Long, hours: Int): List<SatPass> {
val passes = mutableListOf<SatPass>()
val endDate = Date(date.time + hours * 60L * 60L * 1000L)
val endDate = time + hours * 60L * 60L * 1000L
val quarterOrbitMin = (this.orbitalPeriod / 4.0).toInt()
var startDate = date
var startDate = time
var shouldRewind = true
var lastAosDate: Date
var lastAosDate: Long
var count = 0
if (this.willBeSeen(pos)) {
if (this.params.isDeepspace) {
passes.add(getGeoPass(this, pos, date))
passes.add(getGeoPass(this, pos, time))
} else {
do {
if (count > 0) shouldRewind = false
val pass = getLeoPass(this, pos, startDate, shouldRewind)
lastAosDate = Date(pass.aosTime)
lastAosDate = pass.aosTime
passes.add(pass)
startDate = Date(pass.losTime + (quarterOrbitMin * 3) * 60L * 1000L)
startDate = pass.losTime + (quarterOrbitMin * 3) * 60L * 1000L
count++
} while (lastAosDate < endDate)
}
@ -108,53 +107,50 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
return passes
}
private fun List<SatPass>.filter(date: Date, hoursAhead: Int, minElev: Double): List<SatPass> {
val timeFuture = date.time + (hoursAhead * 60L * 60L * 1000L)
return this.filter { it.losTime > date.time }
private fun List<SatPass>.filter(time: Long, hoursAhead: Int, minElev: Double): List<SatPass> {
val timeFuture = time + (hoursAhead * 60L * 60L * 1000L)
return this.filter { it.losTime > time }
.filter { it.aosTime < timeFuture }
.filter { it.maxElevation > minElev }
.sortedBy { it.aosTime }
}
private fun getGeoPass(sat: Satellite, pos: GeoPos, date: Date): SatPass {
val satPos = sat.getPosition(pos, date.time)
val aos = Date(date.time - 24 * 60L * 60L * 1000L).time
val los = Date(date.time + 24 * 60L * 60L * 1000L).time
val tca = Date((aos + los) / 2).time
private fun getGeoPass(sat: Satellite, pos: GeoPos, time: Long): SatPass {
val satPos = sat.getPosition(pos, time)
val aos = time - 24 * 60L * 60L * 1000L
val los = time + 24 * 60L * 60L * 1000L
val tca = (aos + los) / 2
val az = Math.toDegrees(satPos.azimuth)
val elev = Math.toDegrees(satPos.elevation)
val alt = satPos.altitude
return SatPass(aos, az, los, az, tca, az, alt, elev, sat)
}
private fun getLeoPass(sat: Satellite, pos: GeoPos, date: Date, rewind: Boolean): SatPass {
private fun getLeoPass(sat: Satellite, pos: GeoPos, time: Long, rewind: Boolean): SatPass {
val quarterOrbitMin = (sat.orbitalPeriod / 4.0).toInt()
val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
clear()
timeInMillis = date.time
}
var calendarTimeMillis = time
var elevation: Double
var maxElevation = 0.0
var alt = 0.0
var tcaAz = 0.0
// rewind 1/4 of an orbit
if (rewind) calendar.add(Calendar.MINUTE, -quarterOrbitMin)
if (rewind) calendarTimeMillis += -quarterOrbitMin * 60L * 1000L
var satPos = sat.getPosition(pos, calendar.time.time)
var satPos = sat.getPosition(pos, calendarTimeMillis)
if (satPos.elevation > 0.0) {
// move forward in 30 second intervals until the sat goes below the horizon
do {
calendar.add(Calendar.SECOND, 30)
satPos = sat.getPosition(pos, calendar.time.time)
calendarTimeMillis += 30 * 1000L
satPos = sat.getPosition(pos, calendarTimeMillis)
} while (satPos.elevation > 0.0)
// move forward 3/4 of an orbit
calendar.add(Calendar.MINUTE, quarterOrbitMin * 3)
calendarTimeMillis += quarterOrbitMin * 3 * 60L * 1000L
}
// find the next time sat comes above the horizon
do {
calendar.add(Calendar.SECOND, 60)
satPos = sat.getPosition(pos, calendar.time.time)
calendarTimeMillis += 60L * 1000L
satPos = sat.getPosition(pos, calendarTimeMillis)
elevation = satPos.elevation
if (elevation > maxElevation) {
maxElevation = elevation
@ -164,10 +160,10 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
} while (satPos.elevation < 0.0)
// refine to 3 seconds
calendar.add(Calendar.SECOND, -60)
calendarTimeMillis += -60L * 1000L
do {
calendar.add(Calendar.SECOND, 3)
satPos = sat.getPosition(pos, calendar.time.time)
calendarTimeMillis += 3L * 1000L
satPos = sat.getPosition(pos, calendarTimeMillis)
elevation = satPos.elevation
if (elevation > maxElevation) {
maxElevation = elevation
@ -181,8 +177,8 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
// find when sat goes below
do {
calendar.add(Calendar.SECOND, 30)
satPos = sat.getPosition(pos, calendar.time.time)
calendarTimeMillis += 30L * 1000L
satPos = sat.getPosition(pos, calendarTimeMillis)
elevation = satPos.elevation
if (elevation > maxElevation) {
maxElevation = elevation
@ -192,10 +188,10 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
} while (satPos.elevation > 0.0)
// refine to 3 seconds
calendar.add(Calendar.SECOND, -30)
calendarTimeMillis += -30L * 1000L
do {
calendar.add(Calendar.SECOND, 3)
satPos = sat.getPosition(pos, calendar.time.time)
calendarTimeMillis += 3L * 1000L
satPos = sat.getPosition(pos, calendarTimeMillis)
elevation = satPos.elevation
if (elevation > maxElevation) {
maxElevation = elevation
@ -206,7 +202,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
val los = satPos.time
val losAz = Math.toDegrees(satPos.azimuth)
val tca = Date((aos + los) / 2).time
val tca = (aos + los) / 2
val elev = Math.toDegrees(maxElevation)
return SatPass(aos, aosAz, los, losAz, tca, tcaAz, alt, elev, sat)
}

Wyświetl plik

@ -17,8 +17,6 @@
*/
package com.rtbishop.look4sat.domain.predict
import java.util.*
import java.util.concurrent.atomic.AtomicReference
import kotlin.math.*
abstract class Satellite(val params: TLE) {
@ -30,6 +28,7 @@ abstract class Satellite(val params: TLE) {
private val epsilon = 1.0E-12
private val position = Vector4()
private val velocity = Vector4()
private var gsPosTheta = 0.0
private var perigee = 0.0
val orbitalPeriod = 24 * 60 / params.meanmo
val earthRadius = 6378.137
@ -74,10 +73,7 @@ abstract class Satellite(val params: TLE) {
// Read the system clock and return the number of days since 31Dec79 00:00:00 UTC (daynum 0)
private fun calcCurrentDaynum(now: Long): Double {
val sgp4Epoch = Calendar.getInstance(TimeZone.getTimeZone("UTC:UTC"))
sgp4Epoch.clear()
sgp4Epoch[1979, 11, 31, 0, 0] = 0
val then = sgp4Epoch.timeInMillis
val then = 315446400000 // time in millis on 31Dec79 00:00:00 UTC (daynum 0)
val millis = now - then
return millis / 1000.0 / 60.0 / 60.0 / 24.0
}
@ -124,8 +120,7 @@ abstract class Satellite(val params: TLE) {
val obsVel = Vector4()
val range = Vector4()
val rgvel = Vector4()
val gsPosTheta = AtomicReference<Double>()
calculateUserPosVel(julianUTC, gsPos, gsPosTheta, obsPos, obsVel)
calculateUserPosVel(julianUTC, gsPos, obsPos, obsVel)
range.setXYZ(
positionVector.x - obsPos.x,
positionVector.y - obsPos.y,
@ -141,8 +136,8 @@ abstract class Satellite(val params: TLE) {
magnitude(range)
val sinLat = sin(deg2Rad * gsPos.latitude)
val cosLat = cos(deg2Rad * gsPos.latitude)
val sinTheta = sin(gsPosTheta.get())
val cosTheta = cos(gsPosTheta.get())
val sinTheta = sin(gsPosTheta)
val cosTheta = cos(gsPosTheta)
val topS = sinLat * cosTheta * range.x + sinLat * sinTheta * range.y - cosLat * range.z
val topE = -sinTheta * range.x + cosTheta * range.y
val topZ = cosLat * cosTheta * range.x + cosLat * sinTheta * range.y + sinLat * range.z
@ -159,18 +154,17 @@ abstract class Satellite(val params: TLE) {
private fun calculateUserPosVel(
time: Double,
gsPos: GeoPos,
gsPosTheta: AtomicReference<Double>,
obsPos: Vector4,
obsVel: Vector4
) {
val mFactor = 7.292115E-5
gsPosTheta.set(mod2PI(thetaGJD(time) + deg2Rad * gsPos.longitude))
gsPosTheta = mod2PI(thetaGJD(time) + deg2Rad * gsPos.longitude)
val c =
invert(sqrt(1.0 + flatFactor * (flatFactor - 2) * sqr(sin(deg2Rad * gsPos.latitude))))
val sq = sqr(1.0 - flatFactor) * c
val achcp = (earthRadius * c) * cos(deg2Rad * gsPos.latitude)
obsPos.setXYZ(
achcp * cos(gsPosTheta.get()), achcp * sin(gsPosTheta.get()),
achcp * cos(gsPosTheta), achcp * sin(gsPosTheta),
(earthRadius * sq) * sin(deg2Rad * gsPos.latitude)
)
obsVel.setXYZ(-mFactor * obsPos.y, mFactor * obsPos.x, 0.0)