mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
Further changes to Look4Sat Predictor.kt core class
This commit is contained in:
1 parent
bceeb01194
commit
a82915c0ca
8 files changed
+314
-496
No files matched your search
@@ -22,6 +22,7 @@ import android.content.SharedPreferences
|
||||
import android.location.LocationManager
|
||||
import androidx.room.Room
|
||||
import com.rtbishop.look4sat.data.*
|
||||
import com.rtbishop.look4sat.domain.Predictor
|
||||
import com.rtbishop.look4sat.framework.PreferencesProvider
|
||||
import com.rtbishop.look4sat.framework.api.RemoteSource
|
||||
import com.rtbishop.look4sat.framework.api.SatelliteService
|
||||
@@ -63,8 +64,8 @@ object SatelliteDataModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun providePassPredictor(@DefaultDispatcher dispatcher: CoroutineDispatcher): PassPredictor {
|
||||
return PassPredictor(dispatcher)
|
||||
fun providePredictor(@DefaultDispatcher dispatcher: CoroutineDispatcher): Predictor {
|
||||
return Predictor(dispatcher)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
||||
+74
-87
@@ -18,28 +18,22 @@
|
||||
package com.rtbishop.look4sat.presentation.satMapScreen
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import com.rtbishop.look4sat.domain.Predictor
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.data.PassPredictor
|
||||
import com.rtbishop.look4sat.domain.GeoPos
|
||||
import com.rtbishop.look4sat.domain.Satellite
|
||||
import com.rtbishop.look4sat.domain.StationPos
|
||||
import com.rtbishop.look4sat.domain.SatData
|
||||
import com.rtbishop.look4sat.injection.DefaultDispatcher
|
||||
import com.rtbishop.look4sat.domain.*
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.*
|
||||
import org.osmdroid.views.MapView
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@HiltViewModel
|
||||
class SatMapViewModel @Inject constructor(
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val passPredictor: PassPredictor,
|
||||
private val predictor: Predictor,
|
||||
private val preferences: PreferencesSource,
|
||||
@DefaultDispatcher private val defaultDispatcher: CoroutineDispatcher
|
||||
) : ViewModel() {
|
||||
|
||||
private val stationPos = preferences.loadStationPosition()
|
||||
@@ -99,100 +93,93 @@ class SatMapViewModel @Inject constructor(
|
||||
dataUpdateJob?.cancelAndJoin()
|
||||
dataUpdateJob = launch {
|
||||
val dateNow = Date()
|
||||
setSelectedSatTrack(selectedSat, stationPos, dateNow)
|
||||
getSatTrack(selectedSat, stationPos, dateNow)
|
||||
while (isActive) {
|
||||
dateNow.time = System.currentTimeMillis()
|
||||
setSatPositions(allSatList, stationPos, dateNow)
|
||||
setSelectedSatFootprint(selectedSat, stationPos, dateNow)
|
||||
setSelectedSatData(selectedSat, stationPos, dateNow)
|
||||
getPositions(allSatList, stationPos, dateNow)
|
||||
getSatFootprint(selectedSat, stationPos, dateNow)
|
||||
getSatData(selectedSat, stationPos, dateNow)
|
||||
delay(updateFreq)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setSatPositions(list: List<Satellite>, gsp: StationPos, date: Date) {
|
||||
withContext(defaultDispatcher) {
|
||||
val satPositions = mutableMapOf<Satellite, GeoPos>()
|
||||
list.forEach { satellite ->
|
||||
val satPos = satellite.getPosition(gsp, date.time)
|
||||
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||
satPositions[satellite] = GeoPos(osmLat, osmLon)
|
||||
}
|
||||
_satPositions.postValue(satPositions)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setSelectedSatTrack(sat: Satellite, gsp: StationPos, date: Date) {
|
||||
withContext(defaultDispatcher) {
|
||||
val satTracks = mutableListOf<List<GeoPos>>()
|
||||
val currentTrack = mutableListOf<GeoPos>()
|
||||
var oldLongitude = 0.0
|
||||
passPredictor.getPositions(sat, gsp, date, 15, 0, 2.4).forEach { satPos ->
|
||||
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||
val currentPosition = GeoPos(osmLat, osmLon)
|
||||
if (oldLongitude < -170.0 && currentPosition.longitude > 170.0) {
|
||||
// adding left terminal position
|
||||
currentTrack.add(GeoPos(osmLat, -180.0))
|
||||
val finishedTrack = mutableListOf<GeoPos>().apply { addAll(currentTrack) }
|
||||
satTracks.add(finishedTrack)
|
||||
currentTrack.clear()
|
||||
} else if (oldLongitude > 170.0 && currentPosition.longitude < -170.0) {
|
||||
// adding right terminal position
|
||||
currentTrack.add(GeoPos(osmLat, 180.0))
|
||||
val finishedTrack = mutableListOf<GeoPos>().apply { addAll(currentTrack) }
|
||||
satTracks.add(finishedTrack)
|
||||
currentTrack.clear()
|
||||
}
|
||||
oldLongitude = currentPosition.longitude
|
||||
currentTrack.add(currentPosition)
|
||||
}
|
||||
satTracks.add(currentTrack)
|
||||
_satTrack.postValue(satTracks)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setSelectedSatFootprint(sat: Satellite, gsp: StationPos, date: Date) {
|
||||
withContext(defaultDispatcher) {
|
||||
val satFootprint = sat.getPosition(gsp, date.time).getRangeCircle().map { rangePos ->
|
||||
val osmLat = clipLat(rangePos.latitude)
|
||||
val osmLon = clipLon(rangePos.longitude)
|
||||
GeoPos(osmLat, osmLon)
|
||||
}
|
||||
_satFootprint.postValue(satFootprint)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun setSelectedSatData(sat: Satellite, gsp: StationPos, date: Date) {
|
||||
withContext(defaultDispatcher) {
|
||||
val satPos = sat.getPosition(gsp, date.time)
|
||||
private suspend fun getSatTrack(satellite: Satellite, pos: StationPos, date: Date) {
|
||||
val satTracks = mutableListOf<List<GeoPos>>()
|
||||
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 ->
|
||||
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||
val osmPos = GeoPos(osmLat, osmLon)
|
||||
val qthLoc = preferences.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
|
||||
val velocity = getOrbitalVelocity(satPos.altitude)
|
||||
val satData = SatData(
|
||||
sat, sat.params.catnum, sat.params.name, satPos.range,
|
||||
satPos.altitude, velocity, qthLoc, osmPos
|
||||
)
|
||||
this@SatMapViewModel._satData.postValue(satData)
|
||||
val currentPosition = GeoPos(osmLat, osmLon)
|
||||
if (oldLongitude < -170.0 && currentPosition.longitude > 170.0) {
|
||||
// adding left terminal position
|
||||
currentTrack.add(GeoPos(osmLat, -180.0))
|
||||
val finishedTrack = mutableListOf<GeoPos>().apply { addAll(currentTrack) }
|
||||
satTracks.add(finishedTrack)
|
||||
currentTrack.clear()
|
||||
} else if (oldLongitude > 170.0 && currentPosition.longitude < -170.0) {
|
||||
// adding right terminal position
|
||||
currentTrack.add(GeoPos(osmLat, 180.0))
|
||||
val finishedTrack = mutableListOf<GeoPos>().apply { addAll(currentTrack) }
|
||||
satTracks.add(finishedTrack)
|
||||
currentTrack.clear()
|
||||
}
|
||||
oldLongitude = currentPosition.longitude
|
||||
currentTrack.add(currentPosition)
|
||||
}
|
||||
satTracks.add(currentTrack)
|
||||
_satTrack.postValue(satTracks)
|
||||
}
|
||||
|
||||
private suspend fun getPositions(satellites: List<Satellite>, pos: StationPos, date: Date) {
|
||||
val positions = mutableMapOf<Satellite, GeoPos>()
|
||||
satellites.forEach { satellite ->
|
||||
val satPos = predictor.getSatPos(satellite, pos, date)
|
||||
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||
positions[satellite] = GeoPos(osmLat, osmLon)
|
||||
}
|
||||
_satPositions.postValue(positions)
|
||||
}
|
||||
|
||||
private suspend fun getSatFootprint(satellite: Satellite, pos: StationPos, date: Date) {
|
||||
val satPos = predictor.getSatPos(satellite, pos, date)
|
||||
val satFootprint = satPos.getRangeCircle().map { rangePos ->
|
||||
val osmLat = clipLat(rangePos.latitude)
|
||||
val osmLon = clipLon(rangePos.longitude)
|
||||
GeoPos(osmLat, osmLon)
|
||||
}
|
||||
_satFootprint.postValue(satFootprint)
|
||||
}
|
||||
|
||||
private suspend fun getSatData(satellite: Satellite, pos: StationPos, date: Date) {
|
||||
val satPos = predictor.getSatPos(satellite, pos, date)
|
||||
val osmLat = clipLat(Math.toDegrees(satPos.latitude))
|
||||
val osmLon = clipLon(Math.toDegrees(satPos.longitude))
|
||||
val osmPos = GeoPos(osmLat, osmLon)
|
||||
val qthLoc = QthConverter.positionToQTH(osmPos.latitude, osmPos.longitude) ?: "-- --"
|
||||
val satData = SatData(
|
||||
satellite, satellite.params.catnum, satellite.params.name, satPos.range,
|
||||
satPos.altitude, satPos.getOrbitalVelocity(), qthLoc, osmPos
|
||||
)
|
||||
_satData.postValue(satData)
|
||||
}
|
||||
|
||||
private fun clipLat(latitude: Double): Double {
|
||||
return MapView.getTileSystem().cleanLatitude(latitude)
|
||||
return clip(latitude, -85.05, 85.05)
|
||||
}
|
||||
|
||||
private fun clipLon(longitude: Double): Double {
|
||||
return MapView.getTileSystem().cleanLongitude(longitude)
|
||||
var result = longitude
|
||||
while (result < -180.0) result += 360.0
|
||||
while (result > 180.0) result -= 360.0
|
||||
return clip(result, -180.0, 180.0)
|
||||
}
|
||||
|
||||
private fun getOrbitalVelocity(altitude: Double): Double {
|
||||
val earthG = 6.674 * 10.0.pow(-11)
|
||||
val earthM = 5.98 * 10.0.pow(24)
|
||||
val radius = 6.37 * 10.0.pow(6) + altitude * 10.0.pow(3)
|
||||
return sqrt(earthG * earthM / radius) / 1000
|
||||
private fun clip(currentValue: Double, minValue: Double, maxValue: Double): Double {
|
||||
return min(max(currentValue, minValue), maxValue)
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
package com.rtbishop.look4sat.presentation.satPassInfoScreen
|
||||
|
||||
import androidx.lifecycle.*
|
||||
import com.rtbishop.look4sat.data.PassPredictor
|
||||
import com.rtbishop.look4sat.domain.Predictor
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.injection.IoDispatcher
|
||||
@@ -38,7 +38,7 @@ import javax.inject.Inject
|
||||
class PassInfoViewModel @Inject constructor(
|
||||
private val orientationProvider: OrientationProvider,
|
||||
private val preferences: PreferencesSource,
|
||||
private val passPredictor: PassPredictor,
|
||||
private val predictor: Predictor,
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
@IoDispatcher private val ioDispatcher: CoroutineDispatcher
|
||||
) : ViewModel(), OrientationProvider.OrientationListener {
|
||||
@@ -50,7 +50,7 @@ class PassInfoViewModel @Inject constructor(
|
||||
val orientation: LiveData<Triple<Float, Float, Float>> = _orientation
|
||||
|
||||
fun getPass(catNum: Int, aosTime: Long) = liveData {
|
||||
passPredictor.passes.collect { passes ->
|
||||
predictor.passes.collect { passes ->
|
||||
val pass = passes.find { it.catNum == catNum && it.aosTime == aosTime }
|
||||
pass?.let { satPass ->
|
||||
processTransmitters(satPass)
|
||||
|
||||
+6
-6
@@ -23,7 +23,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.rtbishop.look4sat.data.PreferencesSource
|
||||
import com.rtbishop.look4sat.data.SatelliteRepo
|
||||
import com.rtbishop.look4sat.data.PassPredictor
|
||||
import com.rtbishop.look4sat.domain.Predictor
|
||||
import com.rtbishop.look4sat.domain.SatPass
|
||||
import com.rtbishop.look4sat.framework.model.Result
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
@@ -34,7 +34,7 @@ import javax.inject.Inject
|
||||
@HiltViewModel
|
||||
class SatPassViewModel @Inject constructor(
|
||||
private val satelliteRepo: SatelliteRepo,
|
||||
private val passPredictor: PassPredictor,
|
||||
private val predictor: Predictor,
|
||||
private val preferencesSource: PreferencesSource
|
||||
) : ViewModel() {
|
||||
|
||||
@@ -49,13 +49,13 @@ class SatPassViewModel @Inject constructor(
|
||||
viewModelScope.launch {
|
||||
_passes.postValue(Result.InProgress)
|
||||
val stationPos = preferencesSource.loadStationPosition()
|
||||
passPredictor.triggerCalculation(satelliteRepo.getSelectedSatellites(), stationPos)
|
||||
predictor.triggerCalculation(satelliteRepo.getSelectedSatellites(), stationPos)
|
||||
}
|
||||
} else {
|
||||
_isFirstLaunchDone.value = false
|
||||
}
|
||||
viewModelScope.launch {
|
||||
passPredictor.passes.collect { passes ->
|
||||
predictor.passes.collect { passes ->
|
||||
passesProcessing?.cancelAndJoin()
|
||||
passesProcessing = viewModelScope.launch { tickPasses(passes) }
|
||||
}
|
||||
@@ -70,7 +70,7 @@ class SatPassViewModel @Inject constructor(
|
||||
val stationPos = preferencesSource.loadStationPosition()
|
||||
satelliteRepo.updateEntriesFromWeb(preferencesSource.loadDefaultSources())
|
||||
satelliteRepo.updateEntriesSelection(defaultCatNums, true)
|
||||
passPredictor.forceCalculation(satelliteRepo.getSelectedSatellites(), stationPos)
|
||||
predictor.forceCalculation(satelliteRepo.getSelectedSatellites(), stationPos)
|
||||
preferencesSource.setSetupDone()
|
||||
_isFirstLaunchDone.value = true
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class SatPassViewModel @Inject constructor(
|
||||
_passes.postValue(Result.InProgress)
|
||||
passesProcessing?.cancelAndJoin()
|
||||
val stationPos = preferencesSource.loadStationPosition()
|
||||
passPredictor.forceCalculation(satelliteRepo.getSelectedSatellites(), stationPos)
|
||||
predictor.forceCalculation(satelliteRepo.getSelectedSatellites(), stationPos)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user