mirror of
https://github.com/rt-bishop/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Removed all java dependencies from domain.predict package
This commit is contained in:
1 parent
8ef0d103e4
commit
88c7bb6bca
5 files changed
+67
-77
No files matched your search
@@ -116,7 +116,7 @@ class MapViewModel @Inject constructor(
|
|||||||
val currentTrack = mutableListOf<GeoPos>()
|
val currentTrack = mutableListOf<GeoPos>()
|
||||||
val endDate = Date(date.time + (satellite.orbitalPeriod * 2.4 * 60000L).toLong())
|
val endDate = Date(date.time + (satellite.orbitalPeriod * 2.4 * 60000L).toLong())
|
||||||
var oldLongitude = 0.0
|
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 osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||||
val currentPosition = GeoPos(osmLat, osmLon)
|
val currentPosition = GeoPos(osmLat, osmLon)
|
||||||
@@ -143,7 +143,7 @@ class MapViewModel @Inject constructor(
|
|||||||
private suspend fun getPositions(satellites: List<Satellite>, pos: GeoPos, date: Date) {
|
private suspend fun getPositions(satellites: List<Satellite>, pos: GeoPos, date: Date) {
|
||||||
val positions = mutableMapOf<Satellite, GeoPos>()
|
val positions = mutableMapOf<Satellite, GeoPos>()
|
||||||
satellites.forEach { satellite ->
|
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 osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||||
positions[satellite] = GeoPos(osmLat, osmLon)
|
positions[satellite] = GeoPos(osmLat, osmLon)
|
||||||
@@ -152,7 +152,7 @@ class MapViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getSatFootprint(satellite: Satellite, pos: GeoPos, date: Date) {
|
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 satFootprint = satPos.getRangeCircle().map { rangePos ->
|
||||||
val osmLat = clipLat(rangePos.latitude)
|
val osmLat = clipLat(rangePos.latitude)
|
||||||
val osmLon = clipLon(rangePos.longitude)
|
val osmLon = clipLon(rangePos.longitude)
|
||||||
@@ -162,7 +162,7 @@ class MapViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getSatData(satellite: Satellite, pos: GeoPos, date: Date) {
|
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 osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||||
val osmPos = GeoPos(osmLat, osmLon)
|
val osmPos = GeoPos(osmLat, osmLon)
|
||||||
|
|||||||
+5
-5
@@ -49,12 +49,12 @@ class PassesViewModel @Inject constructor(
|
|||||||
if (preferences.isSetupDone()) {
|
if (preferences.isSetupDone()) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_passes.postValue(DataState.Loading)
|
_passes.postValue(DataState.Loading)
|
||||||
val dateNow = Date()
|
val timeNow = System.currentTimeMillis()
|
||||||
val satellites = dataRepository.getSelectedSatellites()
|
val satellites = dataRepository.getSelectedSatellites()
|
||||||
val stationPos = preferences.loadStationPosition()
|
val stationPos = preferences.loadStationPosition()
|
||||||
val hoursAhead = preferences.getHoursAhead()
|
val hoursAhead = preferences.getHoursAhead()
|
||||||
val minElev = preferences.getMinElevation()
|
val minElev = preferences.getMinElevation()
|
||||||
predictor.triggerCalculation(satellites, stationPos, dateNow, hoursAhead, minElev)
|
predictor.triggerCalculation(satellites, stationPos, timeNow, hoursAhead, minElev)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_isFirstLaunchDone.value = false
|
_isFirstLaunchDone.value = false
|
||||||
@@ -77,7 +77,7 @@ class PassesViewModel @Inject constructor(
|
|||||||
val minElev = preferences.getMinElevation()
|
val minElev = preferences.getMinElevation()
|
||||||
dataRepository.updateDataFromWeb()
|
dataRepository.updateDataFromWeb()
|
||||||
dataRepository.updateSelection(isSelected = true)
|
dataRepository.updateSelection(isSelected = true)
|
||||||
predictor.forceCalculation(satellites, stationPos, Date(), hoursAhead, minElev)
|
predictor.forceCalculation(satellites, stationPos, Date().time, hoursAhead, minElev)
|
||||||
preferences.setSetupDone()
|
preferences.setSetupDone()
|
||||||
_isFirstLaunchDone.value = true
|
_isFirstLaunchDone.value = true
|
||||||
}
|
}
|
||||||
@@ -87,12 +87,12 @@ class PassesViewModel @Inject constructor(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_passes.postValue(DataState.Loading)
|
_passes.postValue(DataState.Loading)
|
||||||
passesProcessing?.cancelAndJoin()
|
passesProcessing?.cancelAndJoin()
|
||||||
val dateNow = Date()
|
val timeNow = System.currentTimeMillis()
|
||||||
val satellites = dataRepository.getSelectedSatellites()
|
val satellites = dataRepository.getSelectedSatellites()
|
||||||
val stationPos = preferences.loadStationPosition()
|
val stationPos = preferences.loadStationPosition()
|
||||||
val hoursAhead = preferences.getHoursAhead()
|
val hoursAhead = preferences.getHoursAhead()
|
||||||
val minElev = preferences.getMinElevation()
|
val minElev = preferences.getMinElevation()
|
||||||
predictor.forceCalculation(satellites, stationPos, dateNow, hoursAhead, minElev)
|
predictor.forceCalculation(satellites, stationPos, timeNow, hoursAhead, minElev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,12 +79,12 @@ class RadarViewModel @Inject constructor(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
var satTrack: List<SatPos> = emptyList()
|
var satTrack: List<SatPos> = emptyList()
|
||||||
if (!satPass.isDeepSpace) {
|
if (!satPass.isDeepSpace) {
|
||||||
val startDate = Date(satPass.aosTime)
|
val startDate = satPass.aosTime
|
||||||
val endDate = Date(satPass.losTime)
|
val endDate = satPass.losTime
|
||||||
satTrack = predictor.getSatTrack(satPass.satellite, stationPos, startDate, endDate)
|
satTrack = predictor.getSatTrack(satPass.satellite, stationPos, startDate, endDate)
|
||||||
}
|
}
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date())
|
val satPos = predictor.getSatPos(satPass.satellite, stationPos, Date().time)
|
||||||
if (preferences.isRotatorEnabled()) {
|
if (preferences.isRotatorEnabled()) {
|
||||||
val server = preferences.getRotatorServer().first
|
val server = preferences.getRotatorServer().first
|
||||||
val port = preferences.getRotatorServer().second
|
val port = preferences.getRotatorServer().second
|
||||||
@@ -102,7 +102,7 @@ class RadarViewModel @Inject constructor(
|
|||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val transmitters = dataRepository.getTransmitters(satPass.catNum)
|
val transmitters = dataRepository.getTransmitters(satPass.catNum)
|
||||||
while (isActive) {
|
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() }
|
val copiedList = transmitters.map { it.copy() }
|
||||||
copiedList.forEach { transmitter ->
|
copiedList.forEach { transmitter ->
|
||||||
transmitter.downlink?.let {
|
transmitter.downlink?.let {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import kotlinx.coroutines.CoroutineDispatcher
|
|||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
||||||
|
|
||||||
@@ -29,26 +28,26 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
private var selectedSatIds = emptyList<Int>()
|
private var selectedSatIds = emptyList<Int>()
|
||||||
val passes: SharedFlow<List<SatPass>> = _passes
|
val passes: SharedFlow<List<SatPass>> = _passes
|
||||||
|
|
||||||
suspend fun getSatPos(sat: Satellite, pos: GeoPos, date: Date): SatPos =
|
suspend fun getSatPos(sat: Satellite, pos: GeoPos, time: Long): SatPos {
|
||||||
withContext(predictorDispatcher) {
|
return withContext(predictorDispatcher) { sat.getPosition(pos, time) }
|
||||||
return@withContext sat.getPosition(pos, date.time)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getSatTrack(sat: Satellite, pos: GeoPos, start: Date, end: Date): List<SatPos> =
|
suspend fun getSatTrack(sat: Satellite, pos: GeoPos, start: Long, end: Long): List<SatPos> {
|
||||||
withContext(predictorDispatcher) {
|
return withContext(predictorDispatcher) {
|
||||||
val positions = mutableListOf<SatPos>()
|
val positions = mutableListOf<SatPos>()
|
||||||
var currentTime = start.time
|
var currentTime = start
|
||||||
while (currentTime < end.time) {
|
while (currentTime < end) {
|
||||||
positions.add(sat.getPosition(pos, currentTime))
|
positions.add(sat.getPosition(pos, currentTime))
|
||||||
currentTime += 15000
|
currentTime += 15000
|
||||||
}
|
}
|
||||||
return@withContext positions
|
positions
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun triggerCalculation(
|
suspend fun triggerCalculation(
|
||||||
satellites: List<Satellite>,
|
satellites: List<Satellite>,
|
||||||
pos: GeoPos,
|
pos: GeoPos,
|
||||||
date: Date = Date(),
|
time: Long,
|
||||||
hoursAhead: Int = 8,
|
hoursAhead: Int = 8,
|
||||||
minElevation: Double = 16.0
|
minElevation: Double = 16.0
|
||||||
) {
|
) {
|
||||||
@@ -57,7 +56,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
} else {
|
} else {
|
||||||
val newCatNums = satellites.map { it.params.catnum }
|
val newCatNums = satellites.map { it.params.catnum }
|
||||||
if (selectedSatIds != newCatNums) {
|
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(
|
suspend fun forceCalculation(
|
||||||
satellites: List<Satellite>,
|
satellites: List<Satellite>,
|
||||||
pos: GeoPos,
|
pos: GeoPos,
|
||||||
date: Date = Date(),
|
time: Long,
|
||||||
hoursAhead: Int = 8,
|
hoursAhead: Int = 8,
|
||||||
minElevation: Double = 16.0
|
minElevation: Double = 16.0
|
||||||
) {
|
) {
|
||||||
@@ -76,31 +75,31 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
val allPasses = mutableListOf<SatPass>()
|
val allPasses = mutableListOf<SatPass>()
|
||||||
selectedSatIds = satellites.map { it.params.catnum }
|
selectedSatIds = satellites.map { it.params.catnum }
|
||||||
satellites.forEach { satellite ->
|
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 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()
|
val quarterOrbitMin = (this.orbitalPeriod / 4.0).toInt()
|
||||||
var startDate = date
|
var startDate = time
|
||||||
var shouldRewind = true
|
var shouldRewind = true
|
||||||
var lastAosDate: Date
|
var lastAosDate: Long
|
||||||
var count = 0
|
var count = 0
|
||||||
if (this.willBeSeen(pos)) {
|
if (this.willBeSeen(pos)) {
|
||||||
if (this.params.isDeepspace) {
|
if (this.params.isDeepspace) {
|
||||||
passes.add(getGeoPass(this, pos, date))
|
passes.add(getGeoPass(this, pos, time))
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
if (count > 0) shouldRewind = false
|
if (count > 0) shouldRewind = false
|
||||||
val pass = getLeoPass(this, pos, startDate, shouldRewind)
|
val pass = getLeoPass(this, pos, startDate, shouldRewind)
|
||||||
lastAosDate = Date(pass.aosTime)
|
lastAosDate = pass.aosTime
|
||||||
passes.add(pass)
|
passes.add(pass)
|
||||||
startDate = Date(pass.losTime + (quarterOrbitMin * 3) * 60L * 1000L)
|
startDate = pass.losTime + (quarterOrbitMin * 3) * 60L * 1000L
|
||||||
count++
|
count++
|
||||||
} while (lastAosDate < endDate)
|
} while (lastAosDate < endDate)
|
||||||
}
|
}
|
||||||
@@ -108,53 +107,50 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
return passes
|
return passes
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<SatPass>.filter(date: Date, hoursAhead: Int, minElev: Double): List<SatPass> {
|
private fun List<SatPass>.filter(time: Long, hoursAhead: Int, minElev: Double): List<SatPass> {
|
||||||
val timeFuture = date.time + (hoursAhead * 60L * 60L * 1000L)
|
val timeFuture = time + (hoursAhead * 60L * 60L * 1000L)
|
||||||
return this.filter { it.losTime > date.time }
|
return this.filter { it.losTime > time }
|
||||||
.filter { it.aosTime < timeFuture }
|
.filter { it.aosTime < timeFuture }
|
||||||
.filter { it.maxElevation > minElev }
|
.filter { it.maxElevation > minElev }
|
||||||
.sortedBy { it.aosTime }
|
.sortedBy { it.aosTime }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGeoPass(sat: Satellite, pos: GeoPos, date: Date): SatPass {
|
private fun getGeoPass(sat: Satellite, pos: GeoPos, time: Long): SatPass {
|
||||||
val satPos = sat.getPosition(pos, date.time)
|
val satPos = sat.getPosition(pos, time)
|
||||||
val aos = Date(date.time - 24 * 60L * 60L * 1000L).time
|
val aos = time - 24 * 60L * 60L * 1000L
|
||||||
val los = Date(date.time + 24 * 60L * 60L * 1000L).time
|
val los = time + 24 * 60L * 60L * 1000L
|
||||||
val tca = Date((aos + los) / 2).time
|
val tca = (aos + los) / 2
|
||||||
val az = Math.toDegrees(satPos.azimuth)
|
val az = Math.toDegrees(satPos.azimuth)
|
||||||
val elev = Math.toDegrees(satPos.elevation)
|
val elev = Math.toDegrees(satPos.elevation)
|
||||||
val alt = satPos.altitude
|
val alt = satPos.altitude
|
||||||
return SatPass(aos, az, los, az, tca, az, alt, elev, sat)
|
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 quarterOrbitMin = (sat.orbitalPeriod / 4.0).toInt()
|
||||||
val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
|
var calendarTimeMillis = time
|
||||||
clear()
|
|
||||||
timeInMillis = date.time
|
|
||||||
}
|
|
||||||
var elevation: Double
|
var elevation: Double
|
||||||
var maxElevation = 0.0
|
var maxElevation = 0.0
|
||||||
var alt = 0.0
|
var alt = 0.0
|
||||||
var tcaAz = 0.0
|
var tcaAz = 0.0
|
||||||
// rewind 1/4 of an orbit
|
// 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) {
|
if (satPos.elevation > 0.0) {
|
||||||
// move forward in 30 second intervals until the sat goes below the horizon
|
// move forward in 30 second intervals until the sat goes below the horizon
|
||||||
do {
|
do {
|
||||||
calendar.add(Calendar.SECOND, 30)
|
calendarTimeMillis += 30 * 1000L
|
||||||
satPos = sat.getPosition(pos, calendar.time.time)
|
satPos = sat.getPosition(pos, calendarTimeMillis)
|
||||||
} while (satPos.elevation > 0.0)
|
} while (satPos.elevation > 0.0)
|
||||||
// move forward 3/4 of an orbit
|
// 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
|
// find the next time sat comes above the horizon
|
||||||
do {
|
do {
|
||||||
calendar.add(Calendar.SECOND, 60)
|
calendarTimeMillis += 60L * 1000L
|
||||||
satPos = sat.getPosition(pos, calendar.time.time)
|
satPos = sat.getPosition(pos, calendarTimeMillis)
|
||||||
elevation = satPos.elevation
|
elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
maxElevation = elevation
|
||||||
@@ -164,10 +160,10 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
} while (satPos.elevation < 0.0)
|
} while (satPos.elevation < 0.0)
|
||||||
|
|
||||||
// refine to 3 seconds
|
// refine to 3 seconds
|
||||||
calendar.add(Calendar.SECOND, -60)
|
calendarTimeMillis += -60L * 1000L
|
||||||
do {
|
do {
|
||||||
calendar.add(Calendar.SECOND, 3)
|
calendarTimeMillis += 3L * 1000L
|
||||||
satPos = sat.getPosition(pos, calendar.time.time)
|
satPos = sat.getPosition(pos, calendarTimeMillis)
|
||||||
elevation = satPos.elevation
|
elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
maxElevation = elevation
|
||||||
@@ -181,8 +177,8 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
|
|
||||||
// find when sat goes below
|
// find when sat goes below
|
||||||
do {
|
do {
|
||||||
calendar.add(Calendar.SECOND, 30)
|
calendarTimeMillis += 30L * 1000L
|
||||||
satPos = sat.getPosition(pos, calendar.time.time)
|
satPos = sat.getPosition(pos, calendarTimeMillis)
|
||||||
elevation = satPos.elevation
|
elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
maxElevation = elevation
|
||||||
@@ -192,10 +188,10 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
} while (satPos.elevation > 0.0)
|
} while (satPos.elevation > 0.0)
|
||||||
|
|
||||||
// refine to 3 seconds
|
// refine to 3 seconds
|
||||||
calendar.add(Calendar.SECOND, -30)
|
calendarTimeMillis += -30L * 1000L
|
||||||
do {
|
do {
|
||||||
calendar.add(Calendar.SECOND, 3)
|
calendarTimeMillis += 3L * 1000L
|
||||||
satPos = sat.getPosition(pos, calendar.time.time)
|
satPos = sat.getPosition(pos, calendarTimeMillis)
|
||||||
elevation = satPos.elevation
|
elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
maxElevation = elevation
|
||||||
@@ -206,7 +202,7 @@ class Predictor(private val predictorDispatcher: CoroutineDispatcher) {
|
|||||||
|
|
||||||
val los = satPos.time
|
val los = satPos.time
|
||||||
val losAz = Math.toDegrees(satPos.azimuth)
|
val losAz = Math.toDegrees(satPos.azimuth)
|
||||||
val tca = Date((aos + los) / 2).time
|
val tca = (aos + los) / 2
|
||||||
val elev = Math.toDegrees(maxElevation)
|
val elev = Math.toDegrees(maxElevation)
|
||||||
return SatPass(aos, aosAz, los, losAz, tca, tcaAz, alt, elev, sat)
|
return SatPass(aos, aosAz, los, losAz, tca, tcaAz, alt, elev, sat)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.domain.predict
|
package com.rtbishop.look4sat.domain.predict
|
||||||
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
abstract class Satellite(val params: TLE) {
|
abstract class Satellite(val params: TLE) {
|
||||||
@@ -30,6 +28,7 @@ abstract class Satellite(val params: TLE) {
|
|||||||
private val epsilon = 1.0E-12
|
private val epsilon = 1.0E-12
|
||||||
private val position = Vector4()
|
private val position = Vector4()
|
||||||
private val velocity = Vector4()
|
private val velocity = Vector4()
|
||||||
|
private var gsPosTheta = 0.0
|
||||||
private var perigee = 0.0
|
private var perigee = 0.0
|
||||||
val orbitalPeriod = 24 * 60 / params.meanmo
|
val orbitalPeriod = 24 * 60 / params.meanmo
|
||||||
val earthRadius = 6378.137
|
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)
|
// Read the system clock and return the number of days since 31Dec79 00:00:00 UTC (daynum 0)
|
||||||
private fun calcCurrentDaynum(now: Long): Double {
|
private fun calcCurrentDaynum(now: Long): Double {
|
||||||
val sgp4Epoch = Calendar.getInstance(TimeZone.getTimeZone("UTC:UTC"))
|
val then = 315446400000 // time in millis on 31Dec79 00:00:00 UTC (daynum 0)
|
||||||
sgp4Epoch.clear()
|
|
||||||
sgp4Epoch[1979, 11, 31, 0, 0] = 0
|
|
||||||
val then = sgp4Epoch.timeInMillis
|
|
||||||
val millis = now - then
|
val millis = now - then
|
||||||
return millis / 1000.0 / 60.0 / 60.0 / 24.0
|
return millis / 1000.0 / 60.0 / 60.0 / 24.0
|
||||||
}
|
}
|
||||||
@@ -124,8 +120,7 @@ abstract class Satellite(val params: TLE) {
|
|||||||
val obsVel = Vector4()
|
val obsVel = Vector4()
|
||||||
val range = Vector4()
|
val range = Vector4()
|
||||||
val rgvel = Vector4()
|
val rgvel = Vector4()
|
||||||
val gsPosTheta = AtomicReference<Double>()
|
calculateUserPosVel(julianUTC, gsPos, obsPos, obsVel)
|
||||||
calculateUserPosVel(julianUTC, gsPos, gsPosTheta, obsPos, obsVel)
|
|
||||||
range.setXYZ(
|
range.setXYZ(
|
||||||
positionVector.x - obsPos.x,
|
positionVector.x - obsPos.x,
|
||||||
positionVector.y - obsPos.y,
|
positionVector.y - obsPos.y,
|
||||||
@@ -141,8 +136,8 @@ abstract class Satellite(val params: TLE) {
|
|||||||
magnitude(range)
|
magnitude(range)
|
||||||
val sinLat = sin(deg2Rad * gsPos.latitude)
|
val sinLat = sin(deg2Rad * gsPos.latitude)
|
||||||
val cosLat = cos(deg2Rad * gsPos.latitude)
|
val cosLat = cos(deg2Rad * gsPos.latitude)
|
||||||
val sinTheta = sin(gsPosTheta.get())
|
val sinTheta = sin(gsPosTheta)
|
||||||
val cosTheta = cos(gsPosTheta.get())
|
val cosTheta = cos(gsPosTheta)
|
||||||
val topS = sinLat * cosTheta * range.x + sinLat * sinTheta * range.y - cosLat * range.z
|
val topS = sinLat * cosTheta * range.x + sinLat * sinTheta * range.y - cosLat * range.z
|
||||||
val topE = -sinTheta * range.x + cosTheta * range.y
|
val topE = -sinTheta * range.x + cosTheta * range.y
|
||||||
val topZ = cosLat * cosTheta * range.x + cosLat * sinTheta * range.y + sinLat * range.z
|
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(
|
private fun calculateUserPosVel(
|
||||||
time: Double,
|
time: Double,
|
||||||
gsPos: GeoPos,
|
gsPos: GeoPos,
|
||||||
gsPosTheta: AtomicReference<Double>,
|
|
||||||
obsPos: Vector4,
|
obsPos: Vector4,
|
||||||
obsVel: Vector4
|
obsVel: Vector4
|
||||||
) {
|
) {
|
||||||
val mFactor = 7.292115E-5
|
val mFactor = 7.292115E-5
|
||||||
gsPosTheta.set(mod2PI(thetaGJD(time) + deg2Rad * gsPos.longitude))
|
gsPosTheta = mod2PI(thetaGJD(time) + deg2Rad * gsPos.longitude)
|
||||||
val c =
|
val c =
|
||||||
invert(sqrt(1.0 + flatFactor * (flatFactor - 2) * sqr(sin(deg2Rad * gsPos.latitude))))
|
invert(sqrt(1.0 + flatFactor * (flatFactor - 2) * sqr(sin(deg2Rad * gsPos.latitude))))
|
||||||
val sq = sqr(1.0 - flatFactor) * c
|
val sq = sqr(1.0 - flatFactor) * c
|
||||||
val achcp = (earthRadius * c) * cos(deg2Rad * gsPos.latitude)
|
val achcp = (earthRadius * c) * cos(deg2Rad * gsPos.latitude)
|
||||||
obsPos.setXYZ(
|
obsPos.setXYZ(
|
||||||
achcp * cos(gsPosTheta.get()), achcp * sin(gsPosTheta.get()),
|
achcp * cos(gsPosTheta), achcp * sin(gsPosTheta),
|
||||||
(earthRadius * sq) * sin(deg2Rad * gsPos.latitude)
|
(earthRadius * sq) * sin(deg2Rad * gsPos.latitude)
|
||||||
)
|
)
|
||||||
obsVel.setXYZ(-mFactor * obsPos.y, mFactor * obsPos.x, 0.0)
|
obsVel.setXYZ(-mFactor * obsPos.y, mFactor * obsPos.x, 0.0)
|
||||||
|
|||||||
Reference in new issue
Block a user