# SDK QuestionDistance - closer or further away

#### JMW

Hi
Can anyone help with a simple function to determine whether a vessel is getting closer or further away from a base...........
(Must work even if out of range of base signal)
Thankee.

News Reporter
Donator

N.

#### JMW

Is that a hint....?:lol:

#### Urwumpe

##### Not funny anymore
Donator
In Royal Navy lingo, does the term "rate along" tell you some hint? :hmm:

#### JMW

Er, knot really as I was never in the Navy.........:shifty:

#### Notebook

News Reporter
Donator
Is that a hint....?:lol:

Not in the slightest, I wouldn't know where to start with your question. Just this came to mind...

N.

#### Urwumpe

##### Not funny anymore
Donator
Er, knot really as I was never in the Navy.........:shifty:

Range rate? Rate of change of range over time?

#### JMW

Aha!
Let me work on that (don't hold your breath though!)
Thanks Urwumpe

#### Urwumpe

##### Not funny anymore
Donator
Aha!
Let me work on that (don't hold your breath though!)
Thanks Urwumpe

Remember, what you use for calculating great circle distance can also be used for calculating great circle range rate. :thumbup:

The map in my craft works, so i would just switch on that "function" and it would tell me the distance !!!! (...... I'll get my coat)

#### martins

##### Orbiter Founder
Orbiter Founder
Hi
Can anyone help with a simple function to determine whether a vessel is getting closer or further away from a base...........
(Must work even if out of range of base signal)
Thankee.

For a simple calculation between two points in space this is trivial:
• get the relative velocity between ship and target (there is an API function for that)
• project the relative velocity vector onto the line connecting ship and target
• Check if the projected velocity points towards or away from the target
For navigation across the surface of a sphere, things like computation of heading towards a target are more complicated. To calculate the closing velocity, you would need to calculate the great circle connecting ship and target and then project the relative velocity onto the tangent of that great circle at the current ship position. However, for answering your binary question the simple cartesian version should still be valid.

#### jedidia

##### shoemaker without legs
The approach for the mathematically lazy: Measure distance, store it, next frame see if distance increased or not... :shifty:

#### kuddel

##### Donator
Donator
Hihi, even in Lua it's easy
See here
...if the RangeRate is negative, you are getting closer, if it is positive, you are ging away.
Or was it the other way around?

Last edited:

#### JMW

The approach for the mathematically lazy: Measure distance, store it, next frame see if distance increased or not... :shifty:

Can you believe I'm still struggling with this !

What's the best way to do it?
My problem (so far) is how to store without being overwritten by following frame........:blush:

#### JMW

I knew I gave the same answer before, in response to a question by ... you! Any progress between then and now?

That brain of yours is why you've got to where you are today, instructing others to understand the logic of computer programming!
My 'method' is keep bashing away at something, trying to gather info - but then get to a point where I give up frustrated, and go on to something else.
Eventually something works n it gives me the encouragement to continue.
Obviously that's not the best, but else I would have given up completely long ago.

My brick wall in this thread was
My problem (so far) is how to store without being overwritten by following frame........

Tried to research but didn't get to a conclusion.....

#### martins

##### Orbiter Founder
Orbiter Founder
No problems ...:thumbup:
My problem (so far) is how to store without being overwritten by following frame........
This is easy - you want to overwrite the stored value, just not before you have done your calculation. So the structure looks like this:
Code:
VECTOR3 p;
oapiGetRelativePos(...,&p);
VECTOR3 dp = p-last_p;
last_p = p;
// now use dp for whatever calcuation you need ...
where last_p is the stored position from the last frame (presumably a member of your class)
The only thing to take care of then is not to use last_p before it is initialised.

#### JMW

I've tried to implement but am getting seemingly random results with the colours.
Some right, ie: red when increasing distance, others wrong.
In first row, bases 5,7,11,14 & 16 are wrong.
As seen from debug "dp" registers zero ?
"Too many bases" is just there as a test.

code now: (don't forget to paste it into a compiler if it helps and have a good laugh :tiphat

Thanks in anticipation.

Code:
if(HUD2 == 1 && oapiGetHUDMode() == HUD_DOCKING &&oapiCockpitMode() == COCKPIT_VIRTUAL)  // ---------- Display Bases and Distances --------------
{

if(zoom < 100) { zoom -= 0.25;}
if(zoom < 16) zoom = 16;

double  line = 70;
double linespacing =0;//= 0;
oapi::Font *font = oapiCreateFont (15, false, "MyFont", FONT_NORMAL);
skp->SetFont(font);
char buf[256];
int len = 84;
int len2 = 4;
int ib;
double dis4;
double dis3;
int distance ;
double lat4, lng4;
char basename[84];
VECTOR3 last_p = {0,0,0};
OBJHANDLE hPlanet = oapiGetGbodyByName("Earth");
int nBase=oapiGetBaseCount(hPlanet);

for (ib=0; ib <nBase; ib++) {

linespacing = linespacing + 11;

OBJHANDLE Base = oapiGetBaseByIndex(hPlanet, ib);
oapiGetObjectName(Base, basename, len);
oapiGetBaseEquPos (Base, &lng, &lat);
dis = acos(dis);
dis = (dis)*DEG;
distance = dis * 6371;
if(units == 0) distance = distance *0.539957;

OBJHANDLE hBase = oapiGetBaseByIndex(hPlanet, ib);
OBJHANDLE hRef = oapiGetVesselByName("J-F-35B");
VECTOR3 p;
oapiGetRelativePos(hBase,hRef,&p);
VECTOR3 dp = p-last_p;
last_p = p;
// now use dp for whatever calcuation you need ...

if (ib < 48)
{

if (ib <16)
{
skp->SetTextColor( 0xffffff);
line = 313;
len = sprintf_s(buf,"                    %s",  basename);
skp->Text(-140,((line) +linespacing), buf,  len);

if(units == 0)
{
skp->Text(190, 70, "Nautical Miles", 14);
}
else
{
skp->Text(200, 70, "Kilometers", 10);
}

if (dp.z > 0 &&hspd >10)
{
skp->SetTextColor( 0x0000ff);} //red}
else skp->SetTextColor( 0xffffff);
{
len2 = sprintf_s(buf,"     %i", distance);
skp->Text(85,((line)+linespacing), buf,  len2);
}

}

else if(ib <32)
{
skp->SetTextColor( 0xffffff);
line = 311;
len = sprintf_s(buf,"                    %s",  basename);
skp->Text(30,((line-175) +linespacing), buf,  len);

if (dp.z > 0 &&hspd >10)
{
skp->SetTextColor( 0x0000ff); //red
}

else
{
skp->SetTextColor( 0xffffff); //white
}
len2 = sprintf_s(buf,"     %i", distance);
skp->Text(340,((line-175)+linespacing), buf,  len2);

}

else
{
skp->SetTextColor( 0xffffff); //white
line = 334;
len = sprintf_s(buf,"                    %s",  basename);
skp->Text(220,((line-375) +linespacing), buf,  len);

if (dp.z > 0 &&hspd >10)
{
skp->SetTextColor( 0x0000ff); //red}
}

else
{
skp->SetTextColor( 0xffffff); //white
}
len2 = sprintf_s(buf,"     %i", distance);
skp->Text(510,((line-375)+linespacing), buf,  len2);

}

sprintf(oapiDebugString(),"lng %1.8f :lat %1.8f :dp.z %1.8f :timer4 %1.8f", longitude, latitude, dp.z, timer4);
}

else
if (timer4 > 18)
{
skp->SetTextColor( 0x0000ff); //red
skp->Text(340, 165, "T O O  M A N Y   B A S E S !",28);
}
}
oapiReleaseFont (font);
timer4 = timer4 += 1;
if(timer4>35)
{
timer4 = 0;
}
}

#### Attachments

• Bases.png
302.6 KB · Views: 14
Last edited:

#### martins

##### Orbiter Founder
Orbiter Founder
The way you have written it, dp is not the position difference from a given base between current and last time step, but the difference between the previous and current base in the list, which is meaningless in this context.

• You have to store last_p outside the function body, so it persists between frames. You are defining it as an automatic variable inside the function, which means it is re-initialised at each frame, losing its stored value. Don't use a static variable; that's just asking for trouble.
• You need a separate last_p for every base in the list.
The second point is a bit tricky, because you can't just store all last_p values in an array. The order in which Orbiter returns the bases is not guaranteed to be the same each time (even if in practice it may be), so you need to store the basis name or handle with the value, and search for it in your loop to pick the correct saved value.

That makes this algorithm a bit inelegant and inefficient. My preferred choice here would be not to calculate the closing speed from the position difference, but directly from the relative velocity.

In general: what happens if the base we are interested in is not among the first 48 returned by Orbiter? What if the user has installed a thousand bases? Will you provide a method to page through the entire list? I would suggest sorting the list in ascending order of distance from the current vessel position, since the closest ones are likely to be more relevant.

A few remarks on the code:
• The code between "for (ib = 0; ib <nBase; ib++) {" and "if (ib < 48)" is evaluated for every base, but only used for the ones displayed, so it should be moved inside the if clause.
• The "kilometer" and "nautical miles" indicator is overwritten 16 times for no reason. It should be moved out of the loop.
• After that, the difference between the three columns is just in the output position, so the 3 code blocks could be merged by just computing the row and column from the linear index:
Code:
const int numRows = 16;
int row = ib % numRows;
int col = ib / numRows;
int x = colOffset + col * colSpacing;
int y = rowOffset + row * rowSpacing;

#### jedidia

##### shoemaker without legs
The second point is a bit tricky, because you can't just store all last_p values in an array.

You could store them in a map, with the OBJHANDLE as key.

#### martins

##### Orbiter Founder
Orbiter Founder
And another thing:

Before getting into the business of fixing the entire list, you might want to make sure that the algorithm itself is sound, by testing it on just one base. So for debugging purposes, set nBase = 1 and check if it works as expected.

I suspect it won't (even after fixing the problem with the non-persistent last_p), because as far as I can tell you are using dp.z > 0 as the selection criterion. But dp is just the relative speed (in units of m/frame) in the global frame. You have to project it onto the base's relative position vector (p) and check if the projection points towards or away from the base. So instead of dp.z, use dotp(p, dp) as the criterion. See e.g. here for details.

Replies
5
Views
580
Replies
6
Views
651
Replies
13
Views
1K
Replies
1
Views
205
Replies
7
Views
372