API Question Cancelling out a vessel's surface-relative motion using DefSetStateEx?

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
9,216
Reaction score
1,562
Points
203
Location
VA
Website
alteaaerospace.com
Preferred Pronouns
he/him
I've been digging into adding a hack to the XR vessels to work around this Orbiter core bug, but I'm seeing some odd behavior with DefSetStateEx, and now I'm wondering if I can even use that method to do what I want.

My goal with this hack is to cancel out any vessel motion relative to the surface of the body on which it's landed, but I can't even get that far. Right now I have added this code as a test to my ParkingBrakePreStep, which should not change the ship's velocity at all, but invoking DefSetStateEx even without changing any fields in it causes the vessel to spin wildly while landed:

Code:
VESSELSTATUS2 status;
// Initialize entire structure to zero before invoking the read from the core since the core does not initialize all the fields in GetStatusEx, which can crash DefSetStateEx
memset(&status, 0, sizeof(status));
status.version = 2;   // retrieve version 2 = VESSELSTATUS2
GetXR1().GetStatusEx(&status);
// PROBLEM: invoking DefSetStateEx even with no changes causes the vessel to spin wildly while landed
GetXR1().DefSetStateEx(&status);

I also looked into using VESSEL::SetElements, but that won't work because the docs say:

VESSEL::SetElements said:
Calling SetElements will always put a vessel in freeflight mode, even if it had been landed before.

I am already successfully using VESSEL::DefSetState to spawn or move cargo vessels, but it seems that when I use it on a landed vessel, chaos ensues. Any advice would be much appreciated -- I'm stuck on this one.
 

fred18

Addon Developer
Addon Developer
Donator
Joined
Feb 2, 2012
Messages
1,667
Reaction score
104
Points
78
Hi,

there is an issue with the default orbiter2016 distribution (which should be solved in the svn version) because GetStateEx and DefSetState had issues about rotation of landed vessels.

I solved it in the following way:

Get the status of the vessels you want to be landed, impose the status =1, save it to a ghost scenario file, recall it with clbkloadstateex and that works.

Here's the code snippet I used in MS2015:
Code:
VESSELSTATUS2 vs2;
	memset(&vs2,0,sizeof(vs2));
	vs2.version=2;
	GetStatusEx(&vs2);
        vs2.status=1;

	if(oapiGetOrbiterVersion()<160903)
		{
		FILEHANDLE fh=oapiOpenFile("\\Multistage2015\\__Crawl",FILE_OUT,CONFIG);
		oapiWriteScenario_string(fh,"STATUS","Landed Earth");
		oapiWriteScenario_float(fh,"HEADING",vs2.surf_hdg*DEG);
		char position[256];
		sprintf(position,"%.20f %.20f",vs2.surf_lng*DEG,vs2.surf_lat*DEG);
		oapiWriteScenario_string(fh,"POS",position);
		oapiCloseFile(fh,FILE_OUT);
		fh=oapiOpenFile("\\Multistage2015\\__Crawl",FILE_IN,CONFIG);
		clbkLoadStateEx(fh,&vs2);
		oapiCloseFile(fh,FILE_IN);	
		}
		DefSetStateEx(&vs2);
 

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
9,216
Reaction score
1,562
Points
203
Location
VA
Website
alteaaerospace.com
Preferred Pronouns
he/him
Thanks for the info about the Orbiter core bug with DefSetStateEx. I'll have to see if I can get your hack working in my ParkingBrakePreStep (hopefully it will perform well enough since I only need to do it if the ship is not already landed and the parking brakes have engaged).

I have to say, that's probably the ugliest (and cleverest) hack I've seen in a long time, and now I will have to implement a hack in order to implement another hack. :lol: I'm glad the DefSetStateEx core bug is fixed in the latest Orbiter beta -- hopefully the 'restless spacecraft' bug that I am trying to hack around will also get fixed soon.
 

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
9,216
Reaction score
1,562
Points
203
Location
VA
Website
alteaaerospace.com
Preferred Pronouns
he/him
Well, I got the hack working! I also had to save the ship's landing gear status and retrieve the name of the planet it is landed on when constructing the temporary scenario file, but it appears to work! Now why do I feel so dirty? :lol:
 

fred18

Addon Developer
Addon Developer
Donator
Joined
Feb 2, 2012
Messages
1,667
Reaction score
104
Points
78
well I needed just a few parameters with the crawler of multistage, maybe you can call the entire savestate by clbkSaveState(...) with the handle of your file, I don't know if it works that way. It's really a dirty hack, I know, but with the official 2016 is the only way I found to overcome the issue
 

fred18

Addon Developer
Addon Developer
Donator
Joined
Feb 2, 2012
Messages
1,667
Reaction score
104
Points
78
Since the one I used above was just a dirti hack and in the meantime I came up with a clean solution in the general vehicle module, before people start to use the solution above as a "good" one, here's below the correct solution to this:



Code:
        VESSELSTATUS2 vs2;
        memset(&vs2, 0, sizeof(vs2));
	vs2.version = 2;
	GetStatusEx(&vs2);

	double lng, lat, hdg;
	lng = vs2.surf_lng;
	lat = vs2.surf_lat;
	hdg = vs2.surf_hdg;

////OR MAKE SURE THAT LATITUDE, LONGITUDE AND HEADING ARE THE ONE YOU WANT!


                MATRIX3 rot1 = RotationMatrix(_V(0 * RAD, (90 * RAD - lng), 0 * RAD), TRUE);
		MATRIX3 rot2 = RotationMatrix(_V(-lat + 0 * RAD, 0, 0 * RAD), TRUE);
		MATRIX3 rot3 = RotationMatrix(_V(0, 0, 180 * RAD + hdg), TRUE);
		MATRIX3 rot4 = RotationMatrix(_V(90*RAD, 0, 0), TRUE);


	
		MATRIX3 RotMatrix_Def = mul(rot1, mul(rot2, mul(rot3, rot4)));


		vs2.arot.x = atan2(RotMatrix_Def.m23, RotMatrix_Def.m33);
		vs2.arot.y = -asin(RotMatrix_Def.m13);
		vs2.arot.z = atan2(RotMatrix_Def.m12, RotMatrix_Def.m11);
		vs2.vrot.x = Height_From_Ground ;
		
		DefSetStateEx(&vs2);

Where the rotation matrix function is:
Code:
MATRIX3 GeneralVehicle::RotationMatrix(VECTOR3 angles, bool xyz = FALSE)
{
	MATRIX3 m;
	MATRIX3 RM_X, RM_Y, RM_Z;
	RM_X = _M(1, 0, 0, 0, cos(angles.x), -sin(angles.x), 0, sin(angles.x), cos(angles.x));
	RM_Y = _M(cos(angles.y), 0, sin(angles.y), 0, 1, 0, -sin(angles.y), 0, cos(angles.y));
	RM_Z = _M(cos(angles.z), -sin(angles.z), 0, sin(angles.z), cos(angles.z), 0, 0, 0, 1);
	if (!xyz) {
		m = mul(RM_Z, mul(RM_Y, RM_X));
	}
	else {
		m = mul(RM_X, mul(RM_Y, RM_Z));
	}
	return m;
}
 
Top