SDK Question Vessel-local relative velocity and acceleration

RisingFury

OBSP developer
Addon Developer
Joined
Aug 15, 2008
Messages
6,427
Reaction score
492
Points
173
Location
Among bits and Bytes...
I have a bit of a problem. I'm working on something and need relative position, relative velocity and relative acceleration in vessel-local coordinates.

I managed getting the vessel-local relative position, but I'm having problems with velocity and acceleration.

The SDK gives you the ability to get global relative velocity and acceleration, but I haven't found a way to turn them to vessel-local relative coordinates.

VESSEL::GlobalRot is able to turn a vessel-local vector into a global vector. According to API reference, it's defined as:

r-global = R * r-local + p-vessel

where r-global is the global vector, R is the rotation matrix, r-local is the vessel-local vector and p-vessel is global vessel position. So the next thing that came to mind was this:

r-local = (r-global - p-vessel) / R

The problem with this formula is that it's somewhat undefined, because even if you're able to get the inverse of the rotation matrix, you still do not know if it's supposed to be

r-local = (r-global - p-vesse)*R^-1
or
r-local = R^-1 * (r-global - p-vessel)

I also tried using Local2Global and Global2Local to get the target's vessel-local velocity into global and then into current vessel's local system, but that didn't work. It seems to have a component of location. I tried subtracting the vessel-local relative position, which got almost correct results, but it seemed to be wrong overall.

So, anyone have any idea on how to turn a global vector into a vessel-local vector?
 

computerex

Addon Developer
Addon Developer
Joined
Oct 16, 2007
Messages
1,282
Reaction score
17
Points
0
Location
Florida
Global2Local ?

edit: oops, didn't notice that you already tried using that. Sorry :D

But I don't understand your question...Relative velocity, relative position, and relative acceleration are relative to you, so they are already in local vessel coordinates...

So:

Code:
oapiGetGlobalVel(target, &vel);
Global2Local(vel, vel);

Should give the velocity of the target in the local reference frame.
 

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,580
Reaction score
2
Points
0
I also tried using Local2Global and Global2Local to get the target's vessel-local velocity into global and then into current vessel's local system, but that didn't work. It seems to have a component of location. I tried subtracting the vessel-local relative position, which got almost correct results, but it seemed to be wrong overall.

So, anyone have any idea on how to turn a global vector into a vessel-local vector?
Your last option is almost correct. To obtain relative velocity in the local frame, you need to know the current vessel's position in the global frame.

Let gr_vel be the relative velocity vector of the target in the global frame, g_mypos be the position vector of the current vessel (not the target vessel!) in the global frame. Then, to find relative velocity in the local frame:

Code:
lr_vel = Global2Local(gr_vel + g_mypos);

Think about what this code is doing and you'll see why it works (draw a diagram, maybe). If you're still having trouble figuring it out, ask here and I'll help you figure it out.
 

tblaxland

O-F Administrator
Administrator
Addon Developer
Webmaster
Joined
Jan 1, 2008
Messages
7,320
Reaction score
25
Points
113
Location
Sydney, Australia
GlobalRot is best for use with position vectors. For other vectors, I find it better to do the coordinate transformation/rotation yourself.

Let v-global be the relative velocity vector in global ecliptic coordinates.

v-global = R * v-local
v-local = R^-1 * v-global

The inverse of R (ie, R^-1) is just the transpose of R, since rotation matrices are orthogonal. To make it easy, the Orbiter SDK even has tmul function defined which does the transpose for you. In C++ syntax:

vLocal = tmul(R,vGlobal);

To get R, the VESSEL API has a GetRotationMatrix function.
 
Last edited:

computerex

Addon Developer
Addon Developer
Joined
Oct 16, 2007
Messages
1,282
Reaction score
17
Points
0
Location
Florida
I just tried what I posted above, and it shows funky answers. Does anyone mind telling me why that doesn't work :D ?

edit: nvm xD
 

Zatnikitelman

Addon Developer
Addon Developer
Joined
Jan 13, 2008
Messages
2,302
Reaction score
6
Points
38
Location
Atlanta, GA, USA, North America
Instead of making a whole new topic, I'm hijacking this one :p
Ok, from what I understand of the above, you're talking about velocity in the global frame of Orbiter. Does this process also work for the relative-body frame to make VESSELSTATUS2 happy? (yes Hielor, this is for my failship that put two DGs on the sun yesterday :p) Or is it easiest to transform the global velocity to local, then to relative-body velocity? I've tried using Local2Rel, but that seems to only work for position to the r-body.
 

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,580
Reaction score
2
Points
0
Instead of making a whole new topic, I'm hijacking this one :p
Ok, from what I understand of the above, you're talking about velocity in the global frame of Orbiter. Does this process also work for the relative-body frame to make VESSELSTATUS2 happy? (yes Hielor, this is for my failship that put two DGs on the sun yesterday :p) Or is it easiest to transform the global velocity to local, then to relative-body velocity? I've tried using Local2Rel, but that seems to only work for position to the r-body.
It's the same conversion process for getting velocity into a position API as it was for the Global2Local.

Let lr_vel be the local relative velocity you want to convert to the reference-body frame, let rr_pos be the relative poistion of the current vessel in the reference-body frame. Then, rr_vel (the relative velocity vector in the reference-body frame) would be:

Code:
rr_vel = Local2Rel(lr_vel) - rr_pos;

Seeing the pattern?

See the attached image for a graphical representation. Sorry about the colorfulness--if anyone's colorblind and unable to make heads or tails, I can make a more readable version, let me know.
 

Attachments

  • vectors.png
    vectors.png
    35.8 KB · Views: 37

Zatnikitelman

Addon Developer
Addon Developer
Joined
Jan 13, 2008
Messages
2,302
Reaction score
6
Points
38
Location
Atlanta, GA, USA, North America
Ok, I'm still getting some wacky results. Let me just run through the steps here:

Take the Local2Rel(_V,output) where _V is the velocity relative to the mothership.
Subtract the mothership's position from output.
Set the rvel of each ship equal to the new output.
Here's the specific code:
Code:
    Local2Rel(_V(10,0,-0.1),rvel);
    rvel.x-=PromStatus.rpos.x;
    rvel.y-=PromStatus.rpos.y;
    rvel.z-=PromStatus.rpos.z;
    LCCS1.rvel = rvel;
When actually ran in Orbiter, it appears the LCCS1 (and RCCS1) vessels fly off along the X-axis of Earth instead of the mothership.
 
Last edited:

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,448
Reaction score
462
Points
83
Website
orbit.medphys.ucl.ac.uk
You might be better off just multiplying the local velocity vector with the global rotation matrix (see VESSEL::GetRotationMatrix or oapiGetRotationMatrix), as tblaxland suggested. The (potential) problem with your method is a loss of accuracy, because you are subtracting two large, similar vectors. Not sure if this is really the problem here, though.
 

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,580
Reaction score
2
Points
0
Ok, I'm still getting some wacky results. Let me just run through the steps here:

Take the Local2Rel(_V,output) where _V is the velocity relative to the mothership.
Subtract the mothership's position from output.
Set the rvel of each ship equal to the new output.
Here's the specific code:
Code:
    Local2Rel(_V(10,0,-0.1),rvel);
    rvel.x-=PromStatus.rpos.x;
    rvel.y-=PromStatus.rpos.y;
    rvel.z-=PromStatus.rpos.z;
    LCCS1.rvel = rvel;
When actually ran in Orbiter, it appears the LCCS1 (and RCCS1) vessels fly off along the X-axis of Earth instead of the mothership.
Can you output the results to oapiDebugString and see what the values are? Or step through it in the debugger and see what sort of values it's getting?
 

Zatnikitelman

Addon Developer
Addon Developer
Joined
Jan 13, 2008
Messages
2,302
Reaction score
6
Points
38
Location
Atlanta, GA, USA, North America
Sorry to dig this old topic up, but I still can't get the newly spawned vessels to fly off the way I want them too. Regardless of what I try, they either end up in deep space, on the surface of the sun, or flying off along the planet's axes instead of vessel-local. As you can see from the code for this section below, I've tried several ways, all of which yield the results I state above. As for the non-commented code, right now, it spawns the vessels where I want them, but without any relative velocity.
Code:
VESSELSTATUS2 LCCS1;
    VESSELSTATUS2 RCCS1;
    VESSELSTATUS2 PromStatus;
    VECTOR3 rpos = _V(0,0,0);

    memset (&LCCS1, 0, sizeof(LCCS1));
    memset (&RCCS1, 0, sizeof(RCCS1));
    memset (&PromStatus, 0, sizeof(PromStatus));

    LCCS1.version = 2;
    RCCS1.version = 2;
    PromStatus.version = 2;
    LCCS1.status = 0;
    RCCS1.status = 0;

    GetStatusEx(&PromStatus);

    LCCS1.rbody = PromStatus.rbody;
    RCCS1.rbody = PromStatus.rbody;

    Local2Rel(_V(0,0,0),LCCS1.rpos);
    Local2Rel(_V(0,0,0),RCCS1.rpos);

    LCCS1.arot = PromStatus.arot;
    RCCS1.arot = PromStatus.arot;

    LCCS1.rvel = PromStatus.rvel;
    RCCS1.rvel = PromStatus.rvel;

    /*Local2Rel(_V(10,0,-0.1),rpos);
    rpos.x-=PromStatus.rpos.x;
    rpos.y-=PromStatus.rpos.y;
    rpos.z-=PromStatus.rpos.z;*/

    /*MATRIX3 R;
    GetRotationMatrix(R);
    rpos.x =(10*R.m11 + 0*R.m21 + -0.1*R.m31);
    rpos.y =(10*R.m12 + 0*R.m22 + -0.1*R.m32);
    rpos.z =(10*R.m13 + 0*R.m23 + -0.1*R.m33);
    LCCS1.rvel = rpos;
    rpos.x =(-10*R.m11 + 0*R.m21 + -0.1*R.m31);
    rpos.y =(-10*R.m12 + 0*R.m22 + -0.1*R.m32);
    rpos.z =(-10*R.m13 + 0*R.m23 + -0.1*R.m33);
    RCCS1.rvel = rpos;*/
    
    /*Local2Rel(_V(10,0,-0.1),rpos);
    rpos.x-=PromStatus.rpos.x;
    rpos.y-=PromStatus.rpos.y;
    rpos.z-=PromStatus.rpos.z;*/
    //RCCS1.rvel = rpos;

    LCCS1V = oapiCreateVesselEx("LCCS1","Prometheus10/LCCS1",&LCCS1);
    RCCS1V = oapiCreateVesselEx("RCCS1","Prometheus10/RCCS1",&RCCS1);
I've tried not only setting the vessel to use planet-relative coordinates, but also global coordinates with varying results.
Thanks again for any help!
Zat
 

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
37,605
Reaction score
2,327
Points
203
Location
Wolfsburg
Preferred Pronouns
Sire
If you have multiple conversions from global to local, try creating your own "inverse matrix" by transforming the three unit vectors of your spacecraft (x, y, z) to global coordinates (by multiplication with the global rotation matrix)
 

Hielor

Defender of Truth
Donator
Beta Tester
Joined
May 30, 2008
Messages
5,580
Reaction score
2
Points
0
You are still not loading the LCCS1 and RCCS1 correctly, as I mentioned in the IRC. Rather than copying the elements over individually, start from a known good state and then modify it.

Replace what you have with this (comments removed):
Code:
    VESSELSTATUS2 LCCS1;
    VESSELSTATUS2 RCCS1;
    VESSELSTATUS2 PromStatus;
    VECTOR3 rpos = _V(0,0,0);
 
    memset (&PromStatus, 0, sizeof(PromStatus));
 
    PromStatus.version = 2;
    GetStatusEx(&PromStatus);
    memcpy(&LCCS1, &PromStatus, sizeof(PromStatus));
    memcpy(&RCCS1, &PromStatus, sizeof(PromStatus));
 
    LCCS1V = oapiCreateVesselEx("LCCS1","Prometheus10/LCCS1",&LCCS1);
    RCCS1V = oapiCreateVesselEx("RCCS1","Prometheus10/RCCS1",&RCCS1);

That first block of comments...I'm not sure what you're doing there, since that first block would set the location to the center of the reference body if you applied it, unless "rpos" should be "rvel" (correct variable names are important!)

The second block of comments, I don't know why you're mucking with the rotation matrix.

The third block of comments, again with the setting it to the center of the reference body.

The uncommented code currently spawns the new vessels at the center of the main vessel, is that what you want?

---------- Post added at 01:02 PM ---------- Previous post was at 12:05 PM ----------

Also, if the first and third commented-out blocks are intended to set the relative velocity of LCCS1 to 10,0,-1 and RCCS1 to -10,0,-1, there's a couple problems:
-You're not including the relative velocity of the parent ship w.r.t. the reference body.
-In the Orbiter coordinate system, right is positive x (opposite of Wings3D).

With that in mind, try this:
Code:
    VESSELSTATUS2 LCCS1;
    VESSELSTATUS2 RCCS1;
    VESSELSTATUS2 PromStatus;
    VECTOR3 rpos = _V(0,0,0);
    VECTOR3 rvel = _V(0,0,0);
 
    memset (&PromStatus, 0, sizeof(PromStatus));
 
    // Set up the structures
    PromStatus.version = 2;
    GetStatusEx(&PromStatus);
    memcpy(&LCCS1, &PromStatus, sizeof(PromStatus));
    memcpy(&RCCS1, &PromStatus, sizeof(PromStatus));
 
    // Offset the starting locations of the LCCS and RCCS here
    //
 
    // Velocity of RCCS1
    Local2Rel(_V(10,0,-0.1),rvel);
    rvel -= RCCS1.rpos;
    RCCS1.rvel += rvel;
 
    // Velocity of LCCS1
    Local2Rel(_V(-10,0,-0.1),rvel);
    rvel -= LCCS1.rpos;
    LCCS1.rvel += rvel;
 
    // Create the vessels
    LCCS1V = oapiCreateVesselEx("LCCS1","Prometheus10/LCCS1",&LCCS1);
    RCCS1V = oapiCreateVesselEx("RCCS1","Prometheus10/RCCS1",&RCCS1);
 
Top