SDK Question Distance - closer or further away

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
580
Reaction score
40
Points
43
Location
Happy Wherever
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.
 

Notebook

Addon Developer
Addon Developer
News Reporter
Donator
Joined
Nov 20, 2007
Messages
11,699
Reaction score
564
Points
188

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
36,879
Reaction score
1,537
Points
203
Location
Langendernbach
In Royal Navy lingo, does the term "rate along" tell you some hint? :hmm:
 

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
580
Reaction score
40
Points
43
Location
Happy Wherever
Er, knot really as I was never in the Navy.........:shifty:
 

Notebook

Addon Developer
Addon Developer
News Reporter
Donator
Joined
Nov 20, 2007
Messages
11,699
Reaction score
564
Points
188
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.:)
 

JMW

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
580
Reaction score
40
Points
43
Location
Happy Wherever
Aha!
Let me work on that (don't hold your breath though!)
Thanks Urwumpe
 

Urwumpe

Not funny anymore
Addon Developer
Donator
Joined
Feb 6, 2008
Messages
36,879
Reaction score
1,537
Points
203
Location
Langendernbach
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:
 

paddy

Addon Developer
Addon Developer
Joined
Jul 14, 2012
Messages
80
Reaction score
0
Points
0
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
Joined
Mar 31, 2008
Messages
2,407
Reaction score
341
Points
83
Website
orbit.medphys.ucl.ac.uk
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
Addon Developer
Joined
Mar 19, 2008
Messages
10,304
Reaction score
1,500
Points
203
Location
between the planets
The approach for the mathematically lazy: Measure distance, store it, next frame see if distance increased or not... :shifty:
 

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
1,843
Reaction score
360
Points
83
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

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
580
Reaction score
40
Points
43
Location
Happy Wherever
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

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
580
Reaction score
40
Points
43
Location
Happy Wherever
I knew I gave the same answer before, in response to a question by ... you! Any progress between then and now?

Apologies martins, I'd forgotten about this thread.
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
Joined
Mar 31, 2008
Messages
2,407
Reaction score
341
Points
83
Website
orbit.medphys.ucl.ac.uk
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

Aspiring Addon Developer
Joined
Aug 5, 2008
Messages
580
Reaction score
40
Points
43
Location
Happy Wherever
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;}
			oapiCameraSetAperture (zoom*RAD);
			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);
						GetEquPos (longitude, latitude, radius);
						dis = sin((latitude)*RAD) * sin(lat*RAD) + cos((latitude)*RAD) * cos((lat)*RAD) * cos((longitude-lng)*RAD);
						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->SetTextAlign (oapi::Sketchpad::LEFT, oapi::Sketchpad::TOP);
			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->SetTextAlign (oapi::Sketchpad::LEFT, oapi::Sketchpad::TOP);
				skp->Text(30,((line-175) +linespacing), buf,  len);
				skp->SetTextAlign (oapi::Sketchpad::RIGHT, oapi::Sketchpad::TOP);

	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->SetTextAlign (oapi::Sketchpad::LEFT, oapi::Sketchpad::TOP);
				skp->Text(220,((line-375) +linespacing), buf,  len);
				skp->SetTextAlign (oapi::Sketchpad::RIGHT, oapi::Sketchpad::TOP);

	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
    Bases.png
    302.6 KB · Views: 14
Last edited:

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,407
Reaction score
341
Points
83
Website
orbit.medphys.ucl.ac.uk
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
Addon Developer
Joined
Mar 19, 2008
Messages
10,304
Reaction score
1,500
Points
203
Location
between the planets
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
Joined
Mar 31, 2008
Messages
2,407
Reaction score
341
Points
83
Website
orbit.medphys.ucl.ac.uk
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.
 
Top