mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-05 12:07:25 +00:00
Moved TLE import and Satellite creation to TLE companion object
This commit is contained in:
1 parent
ae21e9e5ca
commit
60a67f86b6
7 files changed
+281
-314
No files matched your search
@@ -20,6 +20,7 @@ package com.rtbishop.look4sat.framework.db
|
|||||||
import androidx.room.TypeConverter
|
import androidx.room.TypeConverter
|
||||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||||
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
||||||
|
import com.rtbishop.look4sat.domain.predict4kotlin.createSat
|
||||||
import com.squareup.moshi.JsonAdapter
|
import com.squareup.moshi.JsonAdapter
|
||||||
import com.squareup.moshi.Moshi
|
import com.squareup.moshi.Moshi
|
||||||
|
|
||||||
@@ -46,6 +47,6 @@ object RoomConverters {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun satFromString(string: String): Satellite? {
|
fun satFromString(string: String): Satellite? {
|
||||||
return Satellite.createSat(tleAdapter.fromJson(string))
|
return tleAdapter.fromJson(string)?.createSat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ import com.rtbishop.look4sat.domain.model.SatEntry
|
|||||||
import com.rtbishop.look4sat.domain.model.SatItem
|
import com.rtbishop.look4sat.domain.model.SatItem
|
||||||
import com.rtbishop.look4sat.domain.model.SatTrans
|
import com.rtbishop.look4sat.domain.model.SatTrans
|
||||||
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
import com.rtbishop.look4sat.domain.predict4kotlin.Satellite
|
||||||
|
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -90,6 +91,6 @@ class SatDataRepository(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun importSatEntries(stream: InputStream): List<SatEntry> {
|
private fun importSatEntries(stream: InputStream): List<SatEntry> {
|
||||||
return Satellite.importElements(stream).map { tle -> SatEntry(tle) }
|
return TLE.importElements(stream).map { tle -> SatEntry(tle) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,200 +2,200 @@ package com.rtbishop.look4sat.domain.predict4kotlin
|
|||||||
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
//
|
||||||
const val speedOfLight = 2.99792458E8
|
//const val speedOfLight = 2.99792458E8
|
||||||
const val earthRadiusKm = 6378.16
|
//const val earthRadiusKm = 6378.16
|
||||||
|
//
|
||||||
fun Satellite.getQuarterOrbitMin(): Int {
|
//fun Satellite.getQuarterOrbitMin(): Int {
|
||||||
return (24.0 * 60.0 / this.tle.meanmo / 4.0).toInt()
|
// return (24.0 * 60.0 / this.tle.meanmo / 4.0).toInt()
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun SatPos.getRangeCircle(): List<Position> {
|
//fun SatPos.getRangeCircle(): List<Position> {
|
||||||
val positions = mutableListOf<Position>()
|
// val positions = mutableListOf<Position>()
|
||||||
val lat = this.latitude
|
// val lat = this.latitude
|
||||||
val lon = this.longitude
|
// val lon = this.longitude
|
||||||
// rangeCircleRadiusKm
|
// // rangeCircleRadiusKm
|
||||||
// earthRadiusKm * acos(earthRadiusKm / (earthRadiusKm + satPos.altitude))
|
// // earthRadiusKm * acos(earthRadiusKm / (earthRadiusKm + satPos.altitude))
|
||||||
val beta = acos(earthRadiusKm / (earthRadiusKm + this.altitude))
|
// val beta = acos(earthRadiusKm / (earthRadiusKm + this.altitude))
|
||||||
var tempAzimuth = 0
|
// var tempAzimuth = 0
|
||||||
while (tempAzimuth < 360) {
|
// while (tempAzimuth < 360) {
|
||||||
val azimuth = tempAzimuth / 360.0 * 2.0 * Math.PI
|
// val azimuth = tempAzimuth / 360.0 * 2.0 * Math.PI
|
||||||
var rangelat = asin(sin(lat) * cos(beta) + cos(azimuth) * sin(beta) * cos(lat))
|
// var rangelat = asin(sin(lat) * cos(beta) + cos(azimuth) * sin(beta) * cos(lat))
|
||||||
val num = (cos(beta) - (sin(lat) * sin(rangelat)))
|
// val num = (cos(beta) - (sin(lat) * sin(rangelat)))
|
||||||
val den = cos(lat) * cos(rangelat)
|
// val den = cos(lat) * cos(rangelat)
|
||||||
var rangelon = if (tempAzimuth == 0 && (beta > ((Math.PI / 2.0) - lat))) {
|
// var rangelon = if (tempAzimuth == 0 && (beta > ((Math.PI / 2.0) - lat))) {
|
||||||
lon + Math.PI
|
// lon + Math.PI
|
||||||
} else if (tempAzimuth == 180 && (beta > ((Math.PI / 2.0) - lat))) {
|
// } else if (tempAzimuth == 180 && (beta > ((Math.PI / 2.0) - lat))) {
|
||||||
lon + Math.PI
|
// lon + Math.PI
|
||||||
} else if (abs(num / den) > 1.0) {
|
// } else if (abs(num / den) > 1.0) {
|
||||||
lon
|
// lon
|
||||||
} else {
|
// } else {
|
||||||
if ((180 - tempAzimuth) >= 0) {
|
// if ((180 - tempAzimuth) >= 0) {
|
||||||
lon - acos(num / den)
|
// lon - acos(num / den)
|
||||||
} else {
|
// } else {
|
||||||
lon + acos(num / den)
|
// lon + acos(num / den)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
while (rangelon < 0.0) rangelon += Math.PI * 2.0
|
// while (rangelon < 0.0) rangelon += Math.PI * 2.0
|
||||||
while (rangelon > Math.PI * 2.0) rangelon -= Math.PI * 2.0
|
// while (rangelon > Math.PI * 2.0) rangelon -= Math.PI * 2.0
|
||||||
rangelat = Math.toDegrees(rangelat)
|
// rangelat = Math.toDegrees(rangelat)
|
||||||
rangelon = Math.toDegrees(rangelon)
|
// rangelon = Math.toDegrees(rangelon)
|
||||||
positions.add(Position(rangelat, rangelon))
|
// positions.add(Position(rangelat, rangelon))
|
||||||
tempAzimuth += 1
|
// tempAzimuth += 1
|
||||||
}
|
// }
|
||||||
return positions
|
// return positions
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun SatPos.getDownlinkFreq(freq: Long): Long {
|
//fun SatPos.getDownlinkFreq(freq: Long): Long {
|
||||||
return (freq.toDouble() * (speedOfLight - this.rangeRate * 1000.0) / speedOfLight).toLong()
|
// return (freq.toDouble() * (speedOfLight - this.rangeRate * 1000.0) / speedOfLight).toLong()
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun SatPos.getUplinkFreq(freq: Long): Long {
|
//fun SatPos.getUplinkFreq(freq: Long): Long {
|
||||||
return (freq.toDouble() * (speedOfLight + this.rangeRate * 1000.0) / speedOfLight).toLong()
|
// return (freq.toDouble() * (speedOfLight + this.rangeRate * 1000.0) / speedOfLight).toLong()
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun Satellite.getSatPos(date: Date): SatPos {
|
//fun Satellite.getSatPos(date: Date): SatPos {
|
||||||
return this.getPosition(stationPos, date)
|
// return this.getPosition(stationPos, date)
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun Satellite.getPositions(date: Date, stepSec: Int, minBefore: Int, orbits: Double): List<SatPos> {
|
//fun Satellite.getPositions(date: Date, stepSec: Int, minBefore: Int, orbits: Double): List<SatPos> {
|
||||||
val positions = mutableListOf<SatPos>()
|
// val positions = mutableListOf<SatPos>()
|
||||||
val orbitalPeriod = 24 * 60 / this.tle.meanmo
|
// val orbitalPeriod = 24 * 60 / this.tle.meanmo
|
||||||
val endDate = Date(date.time + (orbitalPeriod * orbits * 60L * 1000L).toLong())
|
// val endDate = Date(date.time + (orbitalPeriod * orbits * 60L * 1000L).toLong())
|
||||||
val startDate = Date(date.time - minBefore * 60L * 1000L)
|
// val startDate = Date(date.time - minBefore * 60L * 1000L)
|
||||||
var currentDate = startDate
|
// var currentDate = startDate
|
||||||
while (currentDate.before(endDate)) {
|
// while (currentDate.before(endDate)) {
|
||||||
positions.add(getSatPos(currentDate))
|
// positions.add(getSatPos(currentDate))
|
||||||
currentDate = Date(currentDate.time + stepSec * 1000)
|
// currentDate = Date(currentDate.time + stepSec * 1000)
|
||||||
}
|
// }
|
||||||
return positions
|
// return positions
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun Satellite.getPasses(refDate: Date, hoursAhead: Int, windBack: Boolean): List<SatPass> {
|
//fun Satellite.getPasses(refDate: Date, hoursAhead: Int, windBack: Boolean): List<SatPass> {
|
||||||
val passes = mutableListOf<SatPass>()
|
// val passes = mutableListOf<SatPass>()
|
||||||
val oneQuarterOrbitMin = this.getQuarterOrbitMin()
|
// val oneQuarterOrbitMin = this.getQuarterOrbitMin()
|
||||||
val endDate = Date(refDate.time + hoursAhead * 60L * 60L * 1000L)
|
// val endDate = Date(refDate.time + hoursAhead * 60L * 60L * 1000L)
|
||||||
var startDate = refDate
|
// var startDate = refDate
|
||||||
var shouldWindBack = windBack
|
// var shouldWindBack = windBack
|
||||||
var lastAosDate: Date
|
// var lastAosDate: Date
|
||||||
var count = 0
|
// var count = 0
|
||||||
if (this.willBeSeen(stationPos)) {
|
// if (this.willBeSeen(stationPos)) {
|
||||||
if (this.tle.isDeepspace) {
|
// if (this.tle.isDeepspace) {
|
||||||
passes.add(nextDeepSpacePass(refDate))
|
// passes.add(nextDeepSpacePass(refDate))
|
||||||
} else {
|
// } else {
|
||||||
do {
|
// do {
|
||||||
if (count > 0) shouldWindBack = false
|
// if (count > 0) shouldWindBack = false
|
||||||
val pass = nextNearEarthPass(startDate, shouldWindBack)
|
// val pass = nextNearEarthPass(startDate, shouldWindBack)
|
||||||
lastAosDate = pass.aosDate
|
// lastAosDate = pass.aosDate
|
||||||
passes.add(pass)
|
// passes.add(pass)
|
||||||
startDate =
|
// startDate =
|
||||||
Date(pass.losDate.time + (oneQuarterOrbitMin * 3) * 60L * 1000L)
|
// Date(pass.losDate.time + (oneQuarterOrbitMin * 3) * 60L * 1000L)
|
||||||
count++
|
// count++
|
||||||
} while (lastAosDate < endDate)
|
// } while (lastAosDate < endDate)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return passes
|
// return passes
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
private fun Satellite.nextDeepSpacePass(refDate: Date): SatPass {
|
//private fun Satellite.nextDeepSpacePass(refDate: Date): SatPass {
|
||||||
val satPos = getSatPos(refDate)
|
// val satPos = getSatPos(refDate)
|
||||||
val id = this.tle.catnum
|
// val id = this.tle.catnum
|
||||||
val name = this.tle.name
|
// val name = this.tle.name
|
||||||
val isDeep = this.tle.isDeepspace
|
// val isDeep = this.tle.isDeepspace
|
||||||
val aos = Date(refDate.time - 24 * 60L * 60L * 1000L).time
|
// val aos = Date(refDate.time - 24 * 60L * 60L * 1000L).time
|
||||||
val los = Date(refDate.time + 24 * 60L * 60L * 1000L).time
|
// val los = Date(refDate.time + 24 * 60L * 60L * 1000L).time
|
||||||
val tca = Date((aos + los) / 2).time
|
// val tca = Date((aos + los) / 2).time
|
||||||
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(id, name, isDeep, aos, az, los, az, tca, az, alt, elev, this)
|
// return SatPass(id, name, isDeep, aos, az, los, az, tca, az, alt, elev, this)
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
private fun Satellite.nextNearEarthPass(refDate: Date, windBack: Boolean = false): SatPass {
|
//private fun Satellite.nextNearEarthPass(refDate: Date, windBack: Boolean = false): SatPass {
|
||||||
val oneQuarterOrbitMin = this.getQuarterOrbitMin()
|
// val oneQuarterOrbitMin = this.getQuarterOrbitMin()
|
||||||
val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
|
// val calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")).apply {
|
||||||
clear()
|
// clear()
|
||||||
timeInMillis = refDate.time
|
// timeInMillis = refDate.time
|
||||||
}
|
// }
|
||||||
val id = this.tle.catnum
|
// val id = this.tle.catnum
|
||||||
val name = this.tle.name
|
// val name = this.tle.name
|
||||||
val isDeep = this.tle.isDeepspace
|
// val isDeep = this.tle.isDeepspace
|
||||||
|
//
|
||||||
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
|
||||||
|
//
|
||||||
// wind back time 1/4 of an orbit
|
// // wind back time 1/4 of an orbit
|
||||||
if (windBack) calendar.add(Calendar.MINUTE, -oneQuarterOrbitMin)
|
// if (windBack) calendar.add(Calendar.MINUTE, -oneQuarterOrbitMin)
|
||||||
var satPos = getSatPos(calendar.time)
|
// var satPos = getSatPos(calendar.time)
|
||||||
|
//
|
||||||
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)
|
// calendar.add(Calendar.SECOND, 30)
|
||||||
satPos = getSatPos(calendar.time)
|
// satPos = getSatPos(calendar.time)
|
||||||
} 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, oneQuarterOrbitMin * 3)
|
// calendar.add(Calendar.MINUTE, oneQuarterOrbitMin * 3)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// 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)
|
// calendar.add(Calendar.SECOND, 60)
|
||||||
satPos = getSatPos(calendar.time)
|
// satPos = getSatPos(calendar.time)
|
||||||
elevation = satPos.elevation
|
// elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
// if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
// maxElevation = elevation
|
||||||
alt = satPos.altitude
|
// alt = satPos.altitude
|
||||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
// tcaAz = Math.toDegrees(satPos.azimuth)
|
||||||
}
|
// }
|
||||||
} while (satPos.elevation < 0.0)
|
// } while (satPos.elevation < 0.0)
|
||||||
|
//
|
||||||
// refine to 3 seconds
|
// // refine to 3 seconds
|
||||||
calendar.add(Calendar.SECOND, -60)
|
// calendar.add(Calendar.SECOND, -60)
|
||||||
do {
|
// do {
|
||||||
calendar.add(Calendar.SECOND, 3)
|
// calendar.add(Calendar.SECOND, 3)
|
||||||
satPos = getSatPos(calendar.time)
|
// satPos = getSatPos(calendar.time)
|
||||||
elevation = satPos.elevation
|
// elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
// if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
// maxElevation = elevation
|
||||||
alt = satPos.altitude
|
// alt = satPos.altitude
|
||||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
// tcaAz = Math.toDegrees(satPos.azimuth)
|
||||||
}
|
// }
|
||||||
} while (satPos.elevation < 0.0)
|
// } while (satPos.elevation < 0.0)
|
||||||
|
//
|
||||||
val aos = satPos.time.time
|
// val aos = satPos.time.time
|
||||||
val aosAz = Math.toDegrees(satPos.azimuth)
|
// val aosAz = Math.toDegrees(satPos.azimuth)
|
||||||
|
//
|
||||||
// find when sat goes below
|
// // find when sat goes below
|
||||||
do {
|
// do {
|
||||||
calendar.add(Calendar.SECOND, 30)
|
// calendar.add(Calendar.SECOND, 30)
|
||||||
satPos = getSatPos(calendar.time)
|
// satPos = getSatPos(calendar.time)
|
||||||
elevation = satPos.elevation
|
// elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
// if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
// maxElevation = elevation
|
||||||
alt = satPos.altitude
|
// alt = satPos.altitude
|
||||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
// tcaAz = Math.toDegrees(satPos.azimuth)
|
||||||
}
|
// }
|
||||||
} while (satPos.elevation > 0.0)
|
// } while (satPos.elevation > 0.0)
|
||||||
|
//
|
||||||
// refine to 3 seconds
|
// // refine to 3 seconds
|
||||||
calendar.add(Calendar.SECOND, -30)
|
// calendar.add(Calendar.SECOND, -30)
|
||||||
do {
|
// do {
|
||||||
calendar.add(Calendar.SECOND, 3)
|
// calendar.add(Calendar.SECOND, 3)
|
||||||
satPos = getSatPos(calendar.time)
|
// satPos = getSatPos(calendar.time)
|
||||||
elevation = satPos.elevation
|
// elevation = satPos.elevation
|
||||||
if (elevation > maxElevation) {
|
// if (elevation > maxElevation) {
|
||||||
maxElevation = elevation
|
// maxElevation = elevation
|
||||||
alt = satPos.altitude
|
// alt = satPos.altitude
|
||||||
tcaAz = Math.toDegrees(satPos.azimuth)
|
// tcaAz = Math.toDegrees(satPos.azimuth)
|
||||||
}
|
// }
|
||||||
} while (satPos.elevation > 0.0)
|
// } while (satPos.elevation > 0.0)
|
||||||
|
//
|
||||||
val los = satPos.time.time
|
// val los = satPos.time.time
|
||||||
val losAz = Math.toDegrees(satPos.azimuth)
|
// val losAz = Math.toDegrees(satPos.azimuth)
|
||||||
val tca = Date((aos + los) / 2).time
|
// val tca = Date((aos + los) / 2).time
|
||||||
val elev = Math.toDegrees(maxElevation)
|
// val elev = Math.toDegrees(maxElevation)
|
||||||
return SatPass(id, name, isDeep, aos, aosAz, los, losAz, tca, tcaAz, alt, elev, this)
|
// return SatPass(id, name, isDeep, aos, aosAz, los, losAz, tca, tcaAz, alt, elev, this)
|
||||||
}
|
//}
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||||
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
@@ -346,52 +345,4 @@ abstract class Satellite(val tle: TLE) {
|
|||||||
gmst = modulus(gmst + secPerDay * earthRotPerSidDay * ut)
|
gmst = modulus(gmst + secPerDay * earthRotPerSidDay * ut)
|
||||||
return twoPi * gmst / secPerDay
|
return twoPi * gmst / secPerDay
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
fun createSat(tle: TLE?): Satellite? {
|
|
||||||
return when {
|
|
||||||
tle == null -> null
|
|
||||||
tle.isDeepspace -> DeepSpaceSat(tle)
|
|
||||||
else -> NearEarthSat(tle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun importElements(tleStream: InputStream): List<TLE> {
|
|
||||||
val currentTLE = arrayOf(String(), String(), String())
|
|
||||||
val importedTles = mutableListOf<TLE>()
|
|
||||||
var line = 0
|
|
||||||
tleStream.bufferedReader().forEachLine {
|
|
||||||
if (line != 2) {
|
|
||||||
currentTLE[line] = it
|
|
||||||
line++
|
|
||||||
} else {
|
|
||||||
currentTLE[line] = it
|
|
||||||
parseElement(currentTLE)?.let { tle -> importedTles.add(tle) }
|
|
||||||
line = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return importedTles
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseElement(tle: Array<String>): TLE? {
|
|
||||||
if (tle.size != 3) return null
|
|
||||||
try {
|
|
||||||
val name: String = tle[0].trim()
|
|
||||||
val epoch: Double = tle[1].substring(18, 32).toDouble()
|
|
||||||
val meanmo: Double = tle[2].substring(52, 63).toDouble()
|
|
||||||
val eccn: Double = 1.0e-07 * tle[2].substring(26, 33).toDouble()
|
|
||||||
val incl: Double = tle[2].substring(8, 16).toDouble()
|
|
||||||
val raan: Double = tle[2].substring(17, 25).toDouble()
|
|
||||||
val argper: Double = tle[2].substring(34, 42).toDouble()
|
|
||||||
val meanan: Double = tle[2].substring(43, 51).toDouble()
|
|
||||||
val catnum: Int = tle[1].substring(2, 7).trim().toInt()
|
|
||||||
val bstar: Double = 1.0e-5 * tle[1].substring(53, 59).toDouble() /
|
|
||||||
10.0.pow(tle[1].substring(60, 61).toDouble())
|
|
||||||
return TLE(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar)
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
|
||||||
|
|
||||||
import java.io.InputStream
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
object SatelliteFactory {
|
|
||||||
|
|
||||||
fun createSat(tle: TLE?): Satellite? {
|
|
||||||
return when {
|
|
||||||
tle == null -> null
|
|
||||||
tle.isDeepspace -> DeepSpaceSat(tle)
|
|
||||||
else -> NearEarthSat(tle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createSat(array: Array<String>): Satellite? {
|
|
||||||
val importedElement = importElement(array)
|
|
||||||
return createSat(importedElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createDummySat(): Satellite? {
|
|
||||||
val elementArray = arrayOf(
|
|
||||||
"ISS (ZARYA)",
|
|
||||||
"1 25544U 98067A 21242.56000419 .00070558 00000-0 12956-2 0 9996",
|
|
||||||
"2 25544 51.6433 334.9559 0003020 334.9496 106.9882 15.48593918300128"
|
|
||||||
)
|
|
||||||
return createSat(importElement(elementArray))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun importElement(array: Array<String>): TLE? {
|
|
||||||
if (array.size != 3) return null
|
|
||||||
try {
|
|
||||||
val name: String = array[0].trim()
|
|
||||||
val epoch: Double = array[1].substring(18, 32).toDouble()
|
|
||||||
val meanmo: Double = array[2].substring(52, 63).toDouble()
|
|
||||||
val eccn: Double = 1.0e-07 * array[2].substring(26, 33).toDouble()
|
|
||||||
val incl: Double = array[2].substring(8, 16).toDouble()
|
|
||||||
val raan: Double = array[2].substring(17, 25).toDouble()
|
|
||||||
val argper: Double = array[2].substring(34, 42).toDouble()
|
|
||||||
val meanan: Double = array[2].substring(43, 51).toDouble()
|
|
||||||
val catnum: Int = array[1].substring(2, 7).trim().toInt()
|
|
||||||
val bstar: Double = 1.0e-5 * array[1].substring(53, 59).toDouble() /
|
|
||||||
10.0.pow(array[1].substring(60, 61).toDouble())
|
|
||||||
return TLE(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar)
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun importElements(stream: InputStream): List<TLE> {
|
|
||||||
val elementArray = arrayOf(String(), String(), String())
|
|
||||||
val importedElements = mutableListOf<TLE>()
|
|
||||||
var line = 0
|
|
||||||
stream.bufferedReader().forEachLine {
|
|
||||||
if (line != 2) {
|
|
||||||
elementArray[line] = it
|
|
||||||
line++
|
|
||||||
} else {
|
|
||||||
elementArray[line] = it
|
|
||||||
importElement(elementArray)?.let { tle -> importedElements.add(tle) }
|
|
||||||
line = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return importedElements
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.domain.predict4kotlin
|
package com.rtbishop.look4sat.domain.predict4kotlin
|
||||||
|
|
||||||
|
import java.io.InputStream
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
data class TLE(
|
data class TLE(
|
||||||
val name: String,
|
val name: String,
|
||||||
val epoch: Double,
|
val epoch: Double,
|
||||||
@@ -35,4 +38,55 @@ data class TLE(
|
|||||||
val xmo: Double = Math.toRadians(meanan)
|
val xmo: Double = Math.toRadians(meanan)
|
||||||
val xno: Double = meanmo * Math.PI * 2.0 / 1440
|
val xno: Double = meanmo * Math.PI * 2.0 / 1440
|
||||||
val isDeepspace: Boolean = meanmo < 6.4
|
val isDeepspace: Boolean = meanmo < 6.4
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun createSat(array: Array<String>): Satellite? {
|
||||||
|
return importElement(array)?.createSat()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun importElement(array: Array<String>): TLE? {
|
||||||
|
if (array.size != 3) return null
|
||||||
|
try {
|
||||||
|
val name: String = array[0].trim()
|
||||||
|
val epoch: Double = array[1].substring(18, 32).toDouble()
|
||||||
|
val meanmo: Double = array[2].substring(52, 63).toDouble()
|
||||||
|
val eccn: Double = 1.0e-07 * array[2].substring(26, 33).toDouble()
|
||||||
|
val incl: Double = array[2].substring(8, 16).toDouble()
|
||||||
|
val raan: Double = array[2].substring(17, 25).toDouble()
|
||||||
|
val argper: Double = array[2].substring(34, 42).toDouble()
|
||||||
|
val meanan: Double = array[2].substring(43, 51).toDouble()
|
||||||
|
val catnum: Int = array[1].substring(2, 7).trim().toInt()
|
||||||
|
val bstar: Double = 1.0e-5 * array[1].substring(53, 59).toDouble() /
|
||||||
|
10.0.pow(array[1].substring(60, 61).toDouble())
|
||||||
|
return TLE(name, epoch, meanmo, eccn, incl, raan, argper, meanan, catnum, bstar)
|
||||||
|
} catch (exception: Exception) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun importElements(stream: InputStream): List<TLE> {
|
||||||
|
val elementArray = arrayOf(String(), String(), String())
|
||||||
|
val importedElements = mutableListOf<TLE>()
|
||||||
|
var line = 0
|
||||||
|
stream.bufferedReader().forEachLine {
|
||||||
|
if (line != 2) {
|
||||||
|
elementArray[line] = it
|
||||||
|
line++
|
||||||
|
} else {
|
||||||
|
elementArray[line] = it
|
||||||
|
importElement(elementArray)?.let { tle -> importedElements.add(tle) }
|
||||||
|
line = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return importedElements
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TLE.createSat(): Satellite {
|
||||||
|
return when {
|
||||||
|
this.isDeepspace -> DeepSpaceSat(this)
|
||||||
|
else -> NearEarthSat(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.rtbishop.look4sat
|
||||||
|
|
||||||
|
import com.rtbishop.look4sat.domain.predict4kotlin.TLE
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class Look4SatTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Given correct TLE array returns Satellite`() {
|
||||||
|
val elementArray = arrayOf(
|
||||||
|
"ISS (ZARYA)",
|
||||||
|
"1 25544U 98067A 21242.56000419 .00070558 00000-0 12956-2 0 9996",
|
||||||
|
"2 25544 51.6433 334.9559 0003020 334.9496 106.9882 15.48593918300128"
|
||||||
|
)
|
||||||
|
assert(TLE.createSat(elementArray) != null)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Given incorrect TLE array returns null`() {
|
||||||
|
val elementArray = arrayOf(
|
||||||
|
"1 25544U 98067A 21242.56000419 .00070558 00000-0 12956-2 0 9996",
|
||||||
|
"2 25544 51.6433 334.9559 0003020 334.9496 106.9882 15.48593918300128"
|
||||||
|
)
|
||||||
|
assert(TLE.createSat(elementArray) == null)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user