# SDK QuestionHow to keep vessels landed for good in Orbiter 2016 [walkthrough]

#### N_Molson

Donator
Many newcomers to Orbiter 2016 have issue keeping vessels landed on the ground, especially when using time warp and designing addons. It was seen as a bug, as the "infamous bouncing dance", and probably kept a lot of people away from O2016. Those days are over. Jarmonik and Face have recently discovered what was an "hidden feature", an undocumented trick used by Martins to keep vessels landed. Being myself and addon developer I think this is quite a breakthrough so that I want to share this.

It requires using a custom .dll module, but could certainly be implemented as "Parking Brake MFD" or something like that. That would be quite an useful addon.

The major difficulty is to understand how Orbiter deals with coordinates on a Planet (any celestial body in fact) surface. In the scenarios, you can enter longitude/latitude coordinates in decimal degrees ; any decent real-life map app, navigation or GPS system features that. Easy. Now this is a simplification Martins did for us, because Orbiter's core deals with Polar Coordinates. Accurate Polar Coordinates are more difficult to get because they involve Earth's rotation. But, luckily for us, Orbiter can compute celestial mechanics very well (that's the point of it !). So we'll use Orbiter to get those coordinates.

Note : those Polar Coordinates are expressed in RADIANS ; remember that Orbiter's core defines all angles in RADIANS (RAD).

So here's a little walkthrough :

1) Use a scenario file (or the Scenario Editor) to spawn a vessel exactly where you want to go. Here you enter coordinates in Decimal Degrees (DEG). Careful about the +/-, it means East/West North/South.
2) Pause, so that you'll sure the vessel won't move at all.
3) Open the Scenario Editor.
4) Select your vessel, click "Edit"
5) Click "State Vectors"
6) Switch "Frame" to "ref. equator (rotating)" (remember we have to consider Earth's rotation).
7) Switch "Coordinates" to "Polar"
8) Note the "longitude" and "latitude" values, with all the digits, this is important for something like a launchpad.
9) Convert those values from DEG to RAD. You can use a site like Wolfram Alpha (https://www.wolframalpha.com/) for that. Or a good ol' SI calculator if you have one.
10) Enter those values in RAD in the "v.surf_lng" (longitude) and "v.surf_lat" (latitude) fields of the code sample below and compile, of course.
11) Done ! Your Vessel won't move at all even at max time warp.
12) Be creative, now you can do cool stuff like complex animated surface bases made of .dll modules !

C++:
// Original code by Jarmonik

void YOURVESSEL::clbkPreStep(double simt, double simdt, double mjd)
{
OBJHANDLE h_Planet;
h_Planet = oapiGetGbodyByName("Earth"); // enter the name of the planet/moon you want
OBJHANDLE h_yourvessel = GetHandle();
VESSEL *v_yourvessel = oapiGetVesselInterface(h_yourvessel);

VESSELSTATUS2 vs;
memset(&vs, 0, sizeof(vs));
vs.version = 2;
vs.rbody = h_Planet;
vs.status = 1; // Landed
vs.arot.x = 10; // <----- Undocumented feature "magic value" to land on touchdown points !! IMPORTANT !! It has to be 10, no more, no less !
vs.surf_lng = 1.9364618; // example : Wenchang Satellite Center, PRC
vs.surf_lat = 0.3423356;
vs.surf_hdg = 0.0;
v_yourvessel->DefSetStateEx(&vs);
}

Last edited:

#### gattispilot

I am going to try it on my Artemis Lander

#### gattispilot

Ok it works.
 { OBJHANDLE h_Planet; h_Planet = oapiGetGbodyByName("Moon"); // enter the name of the planet/moon you want OBJHANDLE h_yourvessel = GetHandle(); VESSEL* v_yourvessel = oapiGetVesselInterface(h_yourvessel); VESSELSTATUS2 vs; memset(&vs, 0, sizeof(vs)); vs.version = 2; vs.rbody = h_Planet; vs.status = 1; // Landed vs.arot.x = 10; // <----- Undocumented feature "magic value" to land on touchdown points !! IMPORTANT !! It has to be 10, no more, no less ! vs.surf_lng = -0.9697;// radians // example : Wenchang Satellite Center, PRC vs.surf_lat = 0.2486; vs.surf_hdg = 0.0; v_yourvessel->DefSetStateEx(&vs); } 

But it needs a on/off switch so you can lift off. Easy to add.

BUt how to tell it different locations?

#### N_Molson

Donator
Ok it works.

I hope so ! ?

BUt how to tell it different locations?

You mean how to find your coordinates when you land, in Polar Coordinates, with the Equator as reference and taking into account the planet/moon rotation (oh and the whole thing in RAD) ? This is the one hundred dollars question. The Scenario Editor which is a plugin module (not part of Orbiter's core) does it, so it is certainly possible. The VESSELSTATUS2 thing holds that information. The trick is to extract it, my code knowledge is very limited but I'd say its more a class than a function. I'd search into the SDK forum history, or maybe someone still active knows that and wants to share.

Edit : I just checked and in OrbiterSDK you have the full ScenarioEditor code sample. So it should be there.

Last edited:

#### N_Molson

Donator
Martins did the landing part there :

C++:
void EditorTab_Landed::Apply ()
{
char cbuf[256];
GetWindowText (GetDlgItem (hTab, IDC_REF), cbuf, 256);
VESSEL *vessel = oapiGetVesselInterface (ed->hVessel);
OBJHANDLE hRef = oapiGetGbodyByName (cbuf);
if (!hRef) return;
VESSELSTATUS2 vs;
memset (&vs, 0, sizeof(vs));
vs.version = 2;
vs.rbody = hRef;
vs.status = 1; // landed
vs.arot.x = 10; // use default touchdown orientation
GetWindowText (GetDlgItem (hTab, IDC_EDIT1), cbuf, 256);
sscanf (cbuf, "%lf", &vs.surf_lng); vs.surf_lng *= RAD;
GetWindowText (GetDlgItem (hTab, IDC_EDIT2), cbuf, 256);
sscanf (cbuf, "%lf", &vs.surf_lat); vs.surf_lat *= RAD;
GetWindowText (GetDlgItem (hTab, IDC_EDIT3), cbuf, 256);
sscanf (cbuf, "%lf", &vs.surf_hdg); vs.surf_hdg *= RAD;
vessel->DefSetStateEx (&vs);
}

And for getting the coordinates he did it there, I think "calculate ground position" seems very promising, especially the "Crt2Pol" thing :

C++:
VESSELSTATUS2 vs;
memset (&vs, 0, sizeof(vs)); vs.version = 2;
vessel->GetStatusEx (&vs);
if (vs.rbody == hRef) {
sprintf (lngstr, "%lf", vs.surf_lng * DEG);
sprintf (latstr, "%lf", vs.surf_lat * DEG);
ed->SelectBase (hTab, IDC_BASE, hRef, vs.base);
} else {
// calculate ground position
VECTOR3 pos;
MATRIX3 rot;
oapiGetRelativePos (ed->hVessel, hRef, &pos);
oapiGetRotationMatrix (hRef, &rot);
pos = tmul (rot, pos);
Crt2Pol (pos, _V(0,0,0));
sprintf (lngstr, "%lf", pos.data[1] * DEG);
sprintf (latstr, "%lf", pos.data[2] * DEG);
}

#### gattispilot

Thanks. Hope you add it all together. So one could press a key and engage par brake. ready for lift off disengage park brake and apply thrust and away you go

#### N_Molson

Donator
Hope you add it all together.

No, I have a rocket project (or rather, two) I want to finish first. So I'd really appreciate someone else to do it. I mean, I've an average-ish IQ of 110, did very little math at school (or rather gave very little attention to the math classes), and in life I'm a philosophy teacher, which has very little to do with computer science. So really anyone else can do it.

#### ChrisRowland

##### Member
Well, we know where to go to for help with the sort of problem where our rocket is plummeting towards five people who will be killed, or we could divert it so that they are saved but one other person will be killed. (smiley removed, it didn't seem appropriate)

Philosophy teaches clear thinking and logic, useful for computer science.

Replies
2
Views
486
SDK Question Altitude in VS2
Replies
57
Views
7K
SDK Question Vessel orientation
Replies
5
Views
1K
Replies
22
Views
3K