# SDK QuestionVessel-local relative velocity and acceleration

#### RisingFury

##### OBSP developer
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

Global2Local ?

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

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
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

Webmaster
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

I just tried what I posted above, and it shows funky answers. Does anyone mind telling me why that doesn't work ?

edit: nvm xD

#### RisingFury

##### OBSP developer
Code:
lr_vel = Global2Local(gr_vel + g_mypos);

Yup, that worked! Thanks!

#### Zatnikitelman

Instead of making a whole new topic, I'm hijacking this one
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 ) 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
Instead of making a whole new topic, I'm hijacking this one
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 ) 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
35.8 KB · Views: 37

#### Zatnikitelman

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
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
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

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
Donator
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
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);