Local horizon coordinate system

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
I was looking for local horizon reference frame in long time. I now found a paper about local horizon coordinates.

Local Horizon Coordinates

I now noticed that formula is very similar like local 2 horizon formula in Camera.cpp but uses right-handed rule instead.

In orbiter code:

| cos(theta)sin(phi) cos(theta)cos(phi) - sin(theta) |
R = | -cos(phi) sin(ph) 0 |
| sin(theta)sin(phi) sin(theta)cos(phi) cos(theta) |

I tried that formula from Orbiter but negated Z values (sinth = -sin(go.lng)) for right-handed rule in my OpenGL program. It worked at default zero heading but did not align for orientation control and points east to screen. At equator, it rotates vertically but I tried to rotate it habitationally. At mid-latitude, it rotates diagonally... At 90-degree latitude, it rotates horizontally. I think that formula is not compatible with right-handed rule - worked best for left-handed rule.

I will try right-handed version from that paper that I was looking for and found soon and see what happens... It use ENU coordinate to convert.

In that paper:

| cos(phi)cos(theta) cos(phi)sin(theta) sin(phi) |
R = | - sin(theta) cos(theta) 0 |
| -sin(phi)cos(theta) -sin(phi)sin(theta) cos(phi) |


What is any difference between two different formulas?

Tim
 

Boxx

Mars Addict
Addon Developer
Donator
Joined
Nov 15, 2009
Messages
183
Reaction score
125
Points
58
Location
Paris Area
I would be happy if I could help you. But I'm not sure I can diagnose your bug. It would be useful to copy/paste the exact code of yours, within tags CODE (or </>). E.g., R = | -cos(phi) sin(ph) 0 | seems weird...

Code:
copy/paste sth
 

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
37,617
Reaction score
2,337
Points
203
Location
Wolfsburg
Preferred Pronouns
Sire
Or use the
Code:
[math]...[/math]
tag for setting regular mathematical formulas. It uses Latex syntax, which makes it easy for academics, maybe less so for mortal beings.
 

Boxx

Mars Addict
Addon Developer
Donator
Joined
Nov 15, 2009
Messages
183
Reaction score
125
Points
58
Location
Paris Area
Yes, for instance:
Code:
[math]
R = \left[ \begin{array}{l} \cos\phi \cos\theta & \cos\phi \sin\theta & \sin\phi \\
 -\sin\theta & \cos\theta & 0 \\ -\sin\phi \cos\theta & -\sin\phi \sin\theta & \cos\phi \end{array} \right]
[/math]

yields
[math] R = \left[ \begin{array}{c} \cos\phi \cos\theta & \cos\phi \sin\theta & \sin\phi \\ -\sin\theta & \cos\theta & 0 \\ -\sin\phi \cos\theta & -\sin\phi \sin\theta & \cos\phi \end{array} \right] [/math](fun... first time I use LaTeX here...)

but the code in C++ is needed, probably
 

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
Ok, I tried < code ... /code > and it worked for me. Thanks!!

I found typo in my code and corrected it by changed to clng from slng. It causes line drawing instead of picture during rendering. I will try that and see if it works.

Code:
    // Set rotation matrix for local horizon frame (right-handed rule)
    double clat = cos(go.lat), slat = sin(go.lat);
    double clng = cos(go.lng), slng = sin(go.lng);
    go.R = { clat*clng,   clat*slng,  slat,
             -slng,       clng,       0,
             -slat*clng, -slat*slng,  clat };
 

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
Well I tried that but displayed land left side instead of bottom side at (0, 0) coordinate.

I tried reordering that doc explained about.

Code:
    // Set rotation matrix for local horizon frame
    // for right-handed rule (OpenGL)
    double clat = cos(go.lat), slat = sin(go.lat);
    double clng = cos(go.lng), slng = sin(go.lng);
    go.R = { -slng,       clng,       0,
             -slat*clng, -slat*slng,  clat,
             clat*clng,   clat*slng,  slat };
   go.Q = go.R;

It now display horizon level alignment (bottom side) but points south (-Y axis). It does not follow orientation that I tried to rotate around.
However, it did not work anywhere except (0, 0) coordinate (latitude/longitude). View still follow global frame.

Code:
    // Set rotation matrix for local horizon frame
    // for right-handed rule (OpenGL)
    double clat = cos(go.lat), slat = sin(go.lat);
    double clng = cos(go.lng), slng = sin(go.lng);
    go.R = { slat*clng,  clat*clng, slng,
            -clat,       slat,      0,
            -slat*slng, -clat*slng, clng };
   go.Q = go.R;

I quoted that code from Orbiter and converted to right-hand rule. It worked anywhere (view aligned with horizon reference frame) and points to east (-Z axis) but do not follow orientation that still follow global frame. At (90, 0) coordinate (north pole area), it correctly rotates around at horizon level. At (45, 0) coordinate (mid-latitude), it rotates diagonally. At (0, 0) coordinate (equator), it rotates vertically instead of horizon level.

Code:
  glm::dvec3 wv = go.av * 0.5;
  glm::dquat dr = glm::dquat(1.0, wv.x, wv.y, wv.z) * cam.rqrot;
  cam.rqrot = glm::normalize(cam.rqrot + dr);
  cam.rrot = glm::mat3_cast(cam.rqrot);
  cam.rpos -= glm::conjugate(cam.rqrot) * tv;
     
  grot = go.R * cam.rrot;
  gqrot = grot;

That code is in updating each frame. I tried to rotate (go.av - ground observer: angular velocity) around but it does not follow local horizon frame but only global frame. I am figuring out...

I was looking for Euler rotation matrix information through my textbooks but they do not have any Eular rotation matrix to teach. Only document (Local horizon coordinates) explains about Euler rotation.
 

Boxx

Mars Addict
Addon Developer
Donator
Joined
Nov 15, 2009
Messages
183
Reaction score
125
Points
58
Location
Paris Area
Not sure if it helps, but I see a lot of risks of misunderstanding... just to make sure we talk the same (mathematical) language, I stress out that:
1°) your matrix R allows to compute the equatorial coordinates of a local vector (horizon frame, with Z = zenith or anti-nadir):
[math] \overrightarrow u_\text{ecliptic} = R. \overrightarrow u_\text{local} [/math]assuming that your "1-x-9 vector" R is interpreted later in your code as a "3-x-3 matrix" with columns then rows as you wrote (and not rows then columns).
2°) in Orbiter, the (left-handed) coordinate system of a landed vessel is:
[math] \begin{matrix} \overrightarrow z &= \text{thrust vector} \\ \overrightarrow y &= \text{top} \\ \overrightarrow x &= \text{right wing}\\ \end{matrix} [/math]3°) Orbiter does not play with local/horizon frame (as far as I know, maybe I'm wrong), instead it uses lat/lng cylindrical coorrdinates or equatorial inertial rectangular coordinates, maybe to avoid confusion and because it was useless to express rectangular horizon coordinates.

If your point is to convert "standard"(long/lat?) surface coordinates into left-handed local frame, you'd better go to a "vessel frame" as a horizon frame, wouldn't you?
 
Last edited:

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
Ok, now got it. Orbiter code does not have enough comments to trying to understand.

[math] \begin{matrix} \overrightarrow z &= \text{thrust vector} \\ \overrightarrow y &= \text{top} \\ \overrightarrow x &= \text{right wing}\\ \end{matrix} [/math]
How about right-handed coordinate system for 3x3 matrix?

Tim
 

Boxx

Mars Addict
Addon Developer
Donator
Joined
Nov 15, 2009
Messages
183
Reaction score
125
Points
58
Location
Paris Area
How about right-handed coordinate system for 3x3 matrix?
[math] \begin{matrix} \overrightarrow z &= \text{thrust vector} \\ \overrightarrow y &= \text{top} \\ \overrightarrow x &= \text{left wing}\\ \end{matrix} [/math]
for instance, or

[math] \begin{matrix} \overrightarrow z &= \text{thrust vector} \\ \overrightarrow y &= \text{bottom} \\ \overrightarrow x &= \text{right wing}\\ \end{matrix} [/math]
 

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
Ok, I saw other L2H matrix in Vessel.cpp to convert local planet coords to local horizon.

Code:
    // rotation from planet local coords to local horizon
    L2H.Set (-slng, 0, clng,
             clat*clng, slat, clat*slng,
             -slat*clng, clat, -slat*slng);

Code:
    go.R.Set ( clng*slat, clng*clat, -slng,   // rotate from local
              -clat,      slat,       0,      // observer to local
               slng*slat, slng*clat,  clng);  // planet coords

What are difference between two matrices? Is top matrix transposed? Is local observer in vessel frame? Same as local horizon frame?

I saw many code uses that L2H for local horizon frame. Yes, Orbiter uses local horizon frame for conversion from global frame/local planet coords to local horizon frame on surface.
 

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
Well, I figured them how to rotate camera view when I studied matrix rotations on Wikipedia and LearnOpenGL website I decided to try simple Z-axis and Y-axis rotation to rotate camera view (vessel frame).

Code:
// rotation matrices for right-handed rule
template <typename T>
inline glm::dmat3 xRotate(T radians)
{
    double sang = sin(radians), cang = cos(radians);
    return glm::dmat3(
        { 1.0,   0.0,   0.0  },
        { 0.0,   cang, -sang },
        { 0.0,   sang,  cang }
    );
}
template <typename T>
inline glm::dmat3 yRotate(T radians)
{
    double sang = sin(radians), cang = cos(radians);
    return glm::dmat3(
        { cang,  0.0,   sang  },
        { 0.0,   1.0,   0.0   },
        {-sang,  0.0,   cang  }
    );
}
template <typename T>
inline glm::dmat3 zRotate(T radians)
{
    double sang = sin(radians), cang = cos(radians);
    return glm::dmat3(
        { cang, -sang,  0.0   },
        { sang,  cang,  0.0   },
        { 0.0 ,  0.0,   1.0   }
    );
}

Code:
go.R = zRotate(go.lat) * yRotate(go.lng);

I tested (0, 0), (40, 0) and (40, 40) coordinates. It worked but it tilted at 90 degrees counter-clockwise from horizon level at all coordinates and still follows global frame (not horizon frame) when I rotate view around. I am now figuring how to display at horizon level and follow horizon frame when I rotate view around. That is supposed to rotate view rotation to horizon frame/level.
 
Last edited:

Sword7

Member
Joined
Mar 23, 2008
Messages
140
Reaction score
16
Points
18
Location
Gaithersburg, MD
Well, I finally recognized that I ended up in global frame when I tried to rotate camera around. I had to swap two rotations and all problems went away.
Because it uses GLM library, that is opposite of Orbiter code that use its own vector math package.

<global> = <local> * <reference frame>

Code:
grot = cam.rrot * go.R;

Update: I corrected this code because I noticed that it was mistyped. I wonder if who wrote this terrible code?! lol

Code:
// Set rotation matrix for local horizon frame
// for right-handed rule (OpenGL). Points
// to east as origin at (0, 0).
//
//     |  slat  clat   0  | |  clng   0   slng |
// R = | -clat  slat   0  | |   0     1    0   |
//     |   0     0     1  | | -slng   0   clng |
//
double clat = cos(go.lat), slat = sin(go.lat);
double clng = cos(go.lng), slng = sin(go.lng);
go.R = { slat*clng,  clat*clng, slng,
        -clat,       slat,      0,
        -slat*slng, -clat*slng, clng };

I analyzed that complex matrix and was able break it into two simple matrices. I learned how to write latex code.

[math] R = \left[ \begin{array}{l} \sin\phi & \cos\phi & 0 \\ -\cos\phi & \sin\phi & 0 \\ 0 & 0 & 1 \end{array} \right] \left[ \begin{array}{l} \cos\theta & 0 & \sin\theta \\ 0 & 1 & 0 \\ -\sin\theta & 0 & \cos\theta \end{array} \right] [/math]
I tried different coordinates, and everything worked now. I am now rotating camera around at horizon level.
 
Last edited:
Top