diff --git a/executables/nr-ue.c b/executables/nr-ue.c index f57b663f1e..a1d7ef2888 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -732,15 +732,32 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM + ntn_config_params->epoch_hfn * 10240; const int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch; - const double omega = ntn_config_params->omega; - const double cos_wt = cos(omega * ms_since_epoch); - const double sin_wt = sin(omega * ms_since_epoch); - const position_t pos_sat_0 = ntn_config_params->pos_sat_0; - const position_t pos_sat_90 = ntn_config_params->pos_sat_90; - const position_t pos_sat = {pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt, - pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt, - pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt}; + const position_t vel_sat_0 = ntn_config_params->vel_sat_0; + + position_t pos_sat; + position_t vel_sat; + + const double omega = ntn_config_params->omega; + if (omega) { + const double cos_wt = cos(omega * ms_since_epoch); + const double sin_wt = sin(omega * ms_since_epoch); + + const position_t pos_sat_90 = ntn_config_params->pos_sat_90; + pos_sat = (position_t){pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt, + pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt, + pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt}; + + const position_t vel_sat_90 = ntn_config_params->vel_sat_90; + vel_sat = (position_t){vel_sat_0.X * cos_wt + vel_sat_90.X * sin_wt, + vel_sat_0.Y * cos_wt + vel_sat_90.Y * sin_wt, + vel_sat_0.Z * cos_wt + vel_sat_90.Z * sin_wt}; + } else { + pos_sat = (position_t){pos_sat_0.X + vel_sat_0.X * ms_since_epoch / 1000, + pos_sat_0.Y + vel_sat_0.Y * ms_since_epoch / 1000, + pos_sat_0.Z + vel_sat_0.Z * ms_since_epoch / 1000}; + vel_sat = vel_sat_0; + } position_t pos_ue = {0}; get_position_coordinates(UE->Mod_id, &pos_ue); @@ -751,6 +768,9 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM // calculate distance between SAT and UE const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z); + // calculate projected velocity from SAT towards UE + const double vel_sat_ue = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance; + // calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000) const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT; @@ -764,14 +784,15 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM * fp->samples_per_subframe; LOG_D(PHY, - "N_UE_TA_adj = %f ms, N_common_ta_adj = %f ms, N_common_ta_drift = %f µs/s, N_common_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, " - "computed timing_advance_ntn = %d samples\n", + "N_UE_TA_adj = %f ms, N_common_ta_adj = %f ms, N_common_ta_drift = %f µs/s, N_common_ta_drift_variant = %f µs/s², " + "ms_since_epoch = %d ms, computed timing_advance_ntn = %d samples, satellite velocity towards UE = %f m/s\n", N_UE_TA_adj, N_common_ta_adj, N_common_ta_drift, N_common_ta_drift_variant, ms_since_epoch, - UE->timing_advance_ntn); + UE->timing_advance_ntn, + vel_sat_ue); } static inline void apply_ntn_config(PHY_VARS_NR_UE *UE, diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 37337e82d3..49752be093 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -569,10 +569,14 @@ typedef struct { // orbital angular velocity in rad/ms double omega; - // satellite position at epoch time + // satellite position vector at epoch time position_t pos_sat_0; - // satellite position at 90° orbit + // satellite position vector at 90° orbit position_t pos_sat_90; + // satellite velocity vector at epoch time + position_t vel_sat_0; + // satellite velocity vector at 90° orbit + position_t vel_sat_90; // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 5c679630f4..92a0b043e7 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -102,6 +102,8 @@ static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_comma ue->ntn_config_message->ntn_config_params.omega = ntn_params_message->omega; ue->ntn_config_message->ntn_config_params.pos_sat_0 = ntn_params_message->pos_sat_0; ue->ntn_config_message->ntn_config_params.pos_sat_90 = ntn_params_message->pos_sat_90; + ue->ntn_config_message->ntn_config_params.vel_sat_0 = ntn_params_message->vel_sat_0; + ue->ntn_config_message->ntn_config_params.vel_sat_90 = ntn_params_message->vel_sat_90; ue->ntn_config_message->ntn_config_params.N_common_ta_adj = ntn_params_message->N_common_ta_adj; ue->ntn_config_message->ntn_config_params.N_common_ta_drift = ntn_params_message->N_common_ta_drift; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index c92c8225f6..b14097a3ec 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -279,29 +279,49 @@ static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, ntn_timi const double vel_sat_2 = vel_sat.X * vel_sat.X + vel_sat.Y * vel_sat.Y + vel_sat.Z * vel_sat.Z; const double vel_mag = sqrt(vel_sat_2); - // calculate angular velocity in rad/ms - const double omega = vel_mag / (radius * 1000); + double omega; // angular velocity in rad/ms + position_t pos_sat_90; // sat position vector in 90° orbit + position_t vel_sat_90; // sat velocity vector in 90° orbit - // calculate sat position in 90° orbit - position_t pos_sat_90 = pos_sat; - if (vel_mag) { - const double scaling = radius / vel_mag; + // assuming circular orbit when satellite moves faster than 1000 m/s + // 1000 m/s are chosen because according to Wikipedia, this seems to be a reasonable minimal + // orbital velocity: https://en.wikipedia.org/wiki/Orbital_speed#Tangential_velocities_at_altitude + if (vel_mag > 1000) { + omega = vel_mag / (radius * 1000); + double scaling = radius / vel_mag; pos_sat_90 = (position_t){vel_sat.X * scaling, vel_sat.Y * scaling, vel_sat.Z * scaling}; + scaling = -vel_mag / radius; + vel_sat_90 = (position_t){pos_sat.X * scaling, pos_sat.Y * scaling, pos_sat.Z * scaling}; + } else { + omega = 0; + pos_sat_90 = pos_sat; + vel_sat_90 = vel_sat; } LOG_I(NR_MAC, - "Satellite angular velocity = %e rad/ms, sat_pos = {%f, %f, %f}, sat_pos_90 = {%f, %f, %f}\n", - omega, + "Satellite orbital radius %f m, pos_sat_0 = {%f, %f, %f}, pos_sat_90 = {%f, %f, %f}\n" + "Satellite velocity %f m/s, angular velocity = %e rad/ms, vel_sat_0 = {%f, %f, %f}, vel_sat_90 = {%f, %f, %f}\n", + radius, pos_sat.X, pos_sat.Y, pos_sat.Z, pos_sat_90.X, pos_sat_90.Y, - pos_sat_90.Z); + pos_sat_90.Z, + vel_mag, + omega, + vel_sat.X, + vel_sat.Y, + vel_sat.Z, + vel_sat_90.X, + vel_sat_90.Y, + vel_sat_90.Z); ntn_ta->omega = omega; ntn_ta->pos_sat_0 = pos_sat; ntn_ta->pos_sat_90 = pos_sat_90; + ntn_ta->vel_sat_0 = vel_sat; + ntn_ta->vel_sat_90 = vel_sat_90; } // populate ntn_ta structure from mac @@ -332,11 +352,15 @@ static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NT ntn_ta->omega = 0; ntn_ta->pos_sat_0 = (position_t){0, 0, 0}; ntn_ta->pos_sat_90 = (position_t){0, 0, 0}; + ntn_ta->vel_sat_0 = (position_t){0, 0, 0}; + ntn_ta->vel_sat_90 = (position_t){0, 0, 0}; } } else { // Need R - Release if not present ntn_ta->omega = 0; ntn_ta->pos_sat_0 = (position_t){0, 0, 0}; ntn_ta->pos_sat_90 = (position_t){0, 0, 0}; + ntn_ta->vel_sat_0 = (position_t){0, 0, 0}; + ntn_ta->vel_sat_90 = (position_t){0, 0, 0}; } // handle cellSpecificKoffset_r17 diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 7fda4a4b6c..42b616c188 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -552,10 +552,14 @@ typedef struct ntn_timing_advance_components { // orbital angular velocity in rad/ms double omega; - // satellite position at epoch time + // satellite position vector at epoch time position_t pos_sat_0; - // satellite position at 90° orbit + // satellite position vector at 90° orbit position_t pos_sat_90; + // satellite velocity vector at epoch time + position_t vel_sat_0; + // satellite velocity vector at 90° orbit + position_t vel_sat_90; // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms) double N_common_ta_adj; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index c8d40e7f11..f7a763f41a 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -2855,6 +2855,8 @@ static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, ntn_config_command_pdu->omega = mac->ntn_ta.omega; ntn_config_command_pdu->pos_sat_0 = mac->ntn_ta.pos_sat_0; ntn_config_command_pdu->pos_sat_90 = mac->ntn_ta.pos_sat_90; + ntn_config_command_pdu->vel_sat_0 = mac->ntn_ta.vel_sat_0; + ntn_config_command_pdu->vel_sat_90 = mac->ntn_ta.vel_sat_90; ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj; ntn_config_command_pdu->N_common_ta_drift = mac->ntn_ta.N_common_ta_drift;