Расчет витков по TLE
This commit is contained in:
+5
-1
@@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.RestController
|
||||
import space.nstart.pcp.pcp_request_service.service.TLEService
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TLEDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TlePointRequestDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TleRevolutionsRequestDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TleRvaRequestDTO
|
||||
|
||||
@RestController
|
||||
@@ -28,4 +29,7 @@ class TLEController {
|
||||
@PostMapping("/rva")
|
||||
fun rva(@RequestBody req : TleRvaRequestDTO) = tleService.rva(req)
|
||||
|
||||
}
|
||||
@PostMapping("/revolutions")
|
||||
fun revolutions(@RequestBody req: TleRevolutionsRequestDTO) = tleService.revolutions(req)
|
||||
|
||||
}
|
||||
|
||||
+62
-1
@@ -4,7 +4,9 @@ import ballistics.Ballistics
|
||||
import ballistics.orbitalPoints.timeStepper.TLEStepper
|
||||
import ballistics.types.BallisticsError
|
||||
import ballistics.types.EarthType
|
||||
import ballistics.types.KeplerParams
|
||||
import ballistics.types.PPI
|
||||
import ballistics.types.RevolutionParameter
|
||||
import ballistics.types.TLE
|
||||
import ballistics.types.TLEParams
|
||||
import ballistics.types.VisibilityParametersZRV
|
||||
@@ -14,17 +16,25 @@ import ballistics.utils.toDateTime
|
||||
import org.springframework.stereotype.Service
|
||||
import space.nstart.pcp.pcp_request_service.configuration.CustomErrorException
|
||||
import space.nstart.pcp.pcp_request_service.configuration.CustomValidationException
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.AscNodeDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.KeplersDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.OrbPointDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.RadioVisibilityAreaDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TLEDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TlePointRequestDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TleRevolutionsRequestDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TargetPositionDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TleRvaRequestDTO
|
||||
import java.time.LocalDateTime
|
||||
import kotlin.math.PI
|
||||
|
||||
|
||||
@Service
|
||||
class TLEService() {
|
||||
private companion object {
|
||||
const val SECONDS_IN_DAY = 86_400.0
|
||||
const val PZ90_EQUATORIAL_RADIUS = 6_378_136.0
|
||||
}
|
||||
|
||||
fun mkTP(p : VisibilityParametersZRV) = TargetPositionDTO(
|
||||
toDateTime(p.t),
|
||||
@@ -117,4 +127,55 @@ class TLEService() {
|
||||
|
||||
return bal.zrv.map { mkRVA(it, tleParams.noradId) }
|
||||
}
|
||||
}
|
||||
|
||||
fun revolutions(req: TleRevolutionsRequestDTO): List<AscNodeDTO> {
|
||||
if (!req.days.isFinite() || req.days <= 0.0) {
|
||||
throw CustomValidationException("Интервал расчета должен быть больше 0 суток")
|
||||
}
|
||||
|
||||
val bal = Ballistics()
|
||||
val tle = TLE(req.tle.first, req.tle.second)
|
||||
try {
|
||||
bal.getTLEParams(tle, req.tle.header ?: "empty")
|
||||
} catch (ex: Exception) {
|
||||
throw CustomValidationException("Ошибка формата TLE : ${ex.message}")
|
||||
}
|
||||
|
||||
val result = bal.calculateOrbPoints(tle, req.days * SECONDS_IN_DAY)
|
||||
if (result != BallisticsError.OK) {
|
||||
throw CustomErrorException("Ошибка расчета витков по TLE : $result")
|
||||
}
|
||||
|
||||
return bal.revolutions.map { mkAscNode(it, bal.calculateKeplerParams(it.vuz)) }
|
||||
}
|
||||
|
||||
private fun mkAscNode(revolution: RevolutionParameter, keps: KeplerParams) = AscNodeDTO(
|
||||
time = toDateTime(revolution.vuz.t),
|
||||
revolution = revolution.vuz.vit,
|
||||
long = revolution.lVuz * 180 / PI,
|
||||
height = revolution.hVuz,
|
||||
x = revolution.vuz.r.x,
|
||||
y = revolution.vuz.r.y,
|
||||
z = revolution.vuz.r.z,
|
||||
vx = revolution.vuz.v.x,
|
||||
vy = revolution.vuz.v.y,
|
||||
vz = revolution.vuz.v.z,
|
||||
keps = KeplersDTO(
|
||||
(keps.ael - PZ90_EQUATORIAL_RADIUS) / 1000.0,
|
||||
keps.e,
|
||||
keps.nakl * 180 / PI,
|
||||
keps.omegab * 180 / PI,
|
||||
keps.omegam * 180 / PI
|
||||
),
|
||||
localMeanTime = tmest(toDateTime(revolution.vuz.t), revolution.lVuz)
|
||||
)
|
||||
|
||||
private fun tmest(t: LocalDateTime, longitudeRad: Double): LocalDateTime {
|
||||
var longitude = longitudeRad
|
||||
if (longitude > PI) {
|
||||
longitude -= 2 * PI
|
||||
}
|
||||
return t.plusSeconds(-60 * 60 * 3)
|
||||
.plusNanos((longitude / 2.0 / PI * SECONDS_IN_DAY * 1e9).toLong())
|
||||
}
|
||||
}
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package space.nstart.pcp.pcp_request_service.service
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import space.nstart.pcp.pcp_request_service.configuration.CustomValidationException
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TLEDTO
|
||||
import space.nstart.pcp.pcp_types_lib.dto.ballistics.TleRevolutionsRequestDTO
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class TLEServiceTest {
|
||||
|
||||
@Test
|
||||
fun `revolutions calculates ascending nodes from tle epoch`() {
|
||||
val service = TLEService()
|
||||
|
||||
val revolutions = service.revolutions(
|
||||
TleRevolutionsRequestDTO(
|
||||
tle = issTle,
|
||||
days = 1.0
|
||||
)
|
||||
)
|
||||
|
||||
val epoch = service.parseTLE(issTle).time
|
||||
assertTrue(revolutions.isNotEmpty())
|
||||
assertTrue(revolutions.zipWithNext().all { (previous, next) -> previous.time < next.time })
|
||||
assertTrue(revolutions.zipWithNext().all { (previous, next) -> previous.revolution < next.revolution })
|
||||
assertTrue(revolutions.all { it.time >= epoch })
|
||||
assertTrue(revolutions.all { it.localMeanTime != null })
|
||||
assertTrue(revolutions.all { it.keps != null })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `revolutions rejects non-positive duration`() {
|
||||
val service = TLEService()
|
||||
|
||||
assertFailsWith<CustomValidationException> {
|
||||
service.revolutions(
|
||||
TleRevolutionsRequestDTO(
|
||||
tle = issTle,
|
||||
days = 0.0
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val issTle = TLEDTO(
|
||||
header = "ISS",
|
||||
first = "1 25994U 99068A 26167.13049375 .00000315 00000-0 73126-4 0 9997",
|
||||
second = "2 25994 97.9457 216.7186 0001501 193.3628 244.8059 14.61102329409455"
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user