Gondos
Well-known member
This is not strictly an SDK question since I'm working in the core but here it is anyway :
I'd like to compute the right ascension/declination of a radio signal received during a timestep, with sub timestep accuracy.
I have something that seems to work for Az/El, but I tried a couple of things for RA/Dec and cannot land anywhere close to the values shown in the Info dialog for planets.
It could be a reference frame issue or something like that, it also doesn't help that most formulas I found are not using the same model as Orbiter for planetary rotation.
It would be nice to have something that works on any planet if possible.
Here is what I've got for Az/El :
The goal is to be able to compute observables that could then potentially be fed into an orbit determination program (I also have 2-way range/range rate available), to check the consistency of a radio propagation model.
Thanks
I'd like to compute the right ascension/declination of a radio signal received during a timestep, with sub timestep accuracy.
I have something that seems to work for Az/El, but I tried a couple of things for RA/Dec and cannot land anywhere close to the values shown in the Info dialog for planets.
It could be a reference frame issue or something like that, it also doesn't help that most formulas I found are not using the same model as Orbiter for planetary rotation.
It would be nice to have something that works on any planet if possible.
Here is what I've got for Az/El :
Code:
static Vector AddAberration(const Vector& n, const Vector& observerVel)
{
Vector beta = observerVel / C0;
double b2 = dotp(beta, beta);
if (b2 < 1e-16)
return n;
DoubleDouble gamma = 1.0 / (dd_one - b2).sqrt();
double ndotb = dotp(n, beta);
Vector result = (n / (double)gamma + beta * (double)(1.0 + ((gamma - 1.0) / b2) * ndotb)) / (1.0 + ndotb);
return result.unit();
}
struct AzEl {
double azimuth;
double elevation;
};
static AzEl GetAzimuthElevation(const RadioEvent *evt, const LightTimeSolution &sol, const CelestialBody *planet)
{
AzEl azel;
Vector photonDir = (sol.recvPos - evt->emitPos).unit();
Vector apparentLOS = AddAberration(-photonDir, sol.recvVel);
StateVectors sv = planet->InterpolateState(sol.u);
Vector up = (sol.recvPos - sv.pos).unit();
Vector pole = {sv.R.m12, sv.R.m22, sv.R.m32}; // planet rotation axis in global frame
Vector east = crossp(up, pole).unit();
Vector north = crossp(east, up).unit(); // left-handed
double z = std::clamp(dotp(apparentLOS, up), -1.0, 1.0);
azel.elevation = asin(z);
Vector horiz = apparentLOS - up * dotp(apparentLOS, up);
double hlen = horiz.length();
if (hlen < 1e-12) {
azel.azimuth = 0.0;
return azel;
}
horiz /= hlen;
azel.azimuth = atan2(dotp(horiz, east), dotp(horiz, north));
if (azel.azimuth < 0)
azel.azimuth += PI2;
return azel;
}
Thanks