ЗРВ по реальным станциям приёма

Баллистика теперь сама берёт каталог станций у pcp-stations-service
(новый StationCatalogClient, settings.stations-service, GET /api/stations)
и строит ЗРВ по каждой реальной станции: PPI с ppiId == station.number,
поэтому RadioVisibilityAreaDTO.stationId совпадает с номером станции.
Раньше getRVA использовал одну захардкоженную фейковую станцию.

Заодно исправляет автоматический расчёт сбросов (calculateDrops),
который ходит в getRVA, и заполняет duration зоны.
This commit is contained in:
Дмитрий Соловьев
2026-06-01 22:17:01 +03:00
parent 2bdc9ad64f
commit fafaeed418
3 changed files with 68 additions and 7 deletions
+2
View File
@@ -78,6 +78,7 @@ app:
settings: settings:
calculation-interval: 7 calculation-interval: 7
stations-service: ${pcp.services.stations}
server: server:
port: 8080 port: 8080
@@ -127,6 +128,7 @@ app:
settings: settings:
calculation-interval: 28 calculation-interval: 28
ic-service: http://${pcp.network.host}:9080 ic-service: http://${pcp.network.host}:9080
stations-service: ${pcp.services.stations}
server: server:
port: 7003 port: 7003
@@ -102,6 +102,9 @@ class SatelliteService {
@Autowired @Autowired
private lateinit var earthCellViewRepository: EarthCellViewRepository private lateinit var earthCellViewRepository: EarthCellViewRepository
@Autowired
private lateinit var stationCatalogClient: StationCatalogClient
val astro = AstronomerJ2000(EarthType.PZ90d02) val astro = AstronomerJ2000(EarthType.PZ90d02)
@@ -800,17 +803,32 @@ class SatelliteService {
bal.rollMin = 0.0 bal.rollMin = 0.0
bal.rollMax = 45.0 / 180 * PI bal.rollMax = 45.0 / 180 * PI
// ЗРВ считаем по реальным станциям приёма — каталог берём у pcp-stations-service.
// Идентификатор PPI = station.number, поэтому RadioVisibilityAreaDTO.stationId
// совпадает с номером станции (клиент сопоставляет название по своему списку станций).
val stations = stationCatalogClient.allStations()
if (stations.isEmpty()) {
logger.warn("Нет зарегистрированных станций — ЗРВ для КА {} не рассчитываются", id)
return emptyList()
}
val r = bal.calculateZRV( val ppis = stations.map { station ->
listOf(PPI(1,1,0.35, 0.45, 100.0, 0.0, PI/2)), PPI(
tstart, station.number, 1,
tstop station.position.lat * PI / 180,
station.position.long * PI / 180,
station.position.height,
station.elevationMin * PI / 180,
station.elevationMax * PI / 180
) )
}
val r = bal.calculateZRV(ppis, tstart, tstop)
if (r != BallisticsError.OK) { if (r != BallisticsError.OK) {
logger.error("Ошибка при расчете параметров ЗРВ : $r") logger.error("Ошибка при расчете параметров ЗРВ : $r")
return listOf() return listOf()
} else } else
return bal.zrv.map { mkRVA(it, id)} return bal.zrv.map { mkRVA(it, id) }.sortedBy { it.onStart.time }
} }
@@ -820,7 +838,8 @@ class SatelliteService {
revolution = p.vit.toLong(), revolution = p.vit.toLong(),
onStart = mkTP(p.zoneIn), onStart = mkTP(p.zoneIn),
onMaximum = mkTP(p.zoneMax), onMaximum = mkTP(p.zoneMax),
onStop = mkTP(p.zoneOut) onStop = mkTP(p.zoneOut),
duration = (p.zoneOut.t - p.zoneIn.t)
) )
fun mkTP(p : VisibilityParametersZRV) = TargetPositionDTO( fun mkTP(p : VisibilityParametersZRV) = TargetPositionDTO(
toDateTime(p.t), toDateTime(p.t),
@@ -0,0 +1,40 @@
package space.nstart.pcp.pcp_request_service.service
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.ObjectProvider
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.web.reactive.function.client.WebClient
import space.nstart.pcp.pcp_types_lib.dto.ballistics.StationDTO
/**
* Клиент к pcp-stations-service: получение списка наземных станций приёма.
*
* Расчёт зон радиовидимости (ЗРВ) ведётся по реальным станциям, поэтому баллистика
* сама забирает их каталог у сервиса станций (а не получает с фронта).
*/
@Service
class StationCatalogClient(webClientBuilderProvider: ObjectProvider<WebClient.Builder>) {
private val webClientBuilder: WebClient.Builder = webClientBuilderProvider.ifAvailable ?: WebClient.builder()
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
@Value("\${settings.stations-service:stations-service}")
val url = ""
/** Возвращает все зарегистрированные станции; при ошибке — пустой список (ЗРВ тогда не строится). */
fun allStations(): List<StationDTO> =
runCatching {
webClientBuilder.build()
.get()
.uri("$url/api/stations")
.retrieve()
.bodyToFlux(StationDTO::class.java)
.collectList()
.block()
?: emptyList()
}.getOrElse { e ->
logger.error("Не удалось получить список станций из $url/api/stations: ${e.message}")
emptyList()
}
}