SDK Question Vessel orientation

Abdullah Radwan

Addon Developer
Addon Developer
Joined
Aug 20, 2017
Messages
240
Reaction score
78
Points
43
Location
Cairo
Hello,

I am developing the ground release code for UCSO. I am using this code:

Code:
	if (vessel->GetFlightStatus() & 1) {
		VESSELSTATUS2 status;
		memset(&status, 0, sizeof(status));
		status.version = 2;
		vessel->GetStatusEx(&status);

		double longitude, latitude, radius;
		vessel->GetEquPos(longitude, latitude, radius);

		double angularDistance = releaseDistance / radius;
		double trueCourse = 180 * (PI / 180);

		double releaseLatitude = asin(sin(latitude) * cos(angularDistance) + cos(latitude) * sin(angularDistance) * cos(trueCourse));

		double dLongitude = atan2(sin(trueCourse) * sin(angularDistance) * cos(latitude),
			cos(angularDistance) - sin(latitude) * sin(releaseLatitude));

		double releaseLongitude = fmod(longitude + dLongitude + PI, 2 * PI) - PI;

		status.surf_lng = releaseLongitude;
		status.surf_lat = releaseLatitude;
		
		if (vessel->DetachChild(attachsMap[pair.first], 0.0)) {
			cargo->DefSetStateEx(&status);
			if (isTotalMassGet) totalCargoMass -= cargo->GetMass();
			cargoReleased = true;
		}
		else cargoReleased = false;
	}

The orientation should be the same as the parent vessel orientation, but this isn't the case:

xq7SHmR.png


Scenario parameters:
Code:
ShuttlePB:ShuttlePB_UCSO ;Parent vessel
  STATUS Landed Earth
  POS -80.6758980 28.5227620
  HEADING 109.16
  [COLOR="Red"]ALT 1.287[/COLOR]
  [COLOR="Red"]AROT -86.168 -72.488 146.453[/COLOR]
  AFCMODE 7
  PRPLEVEL 0:1.000000
  NAVFREQ 0 0
END
ShuttlePB1:ShuttlePB_UCSO ;Cargo
  STATUS Landed Earth
  POS -80.6758980 28.5227170
  HEADING 109.16
  [COLOR="Red"]ALT 0.000[/COLOR]
  [COLOR="Red"]AROT -54.479 -64.756 112.835[/COLOR]
  AFCMODE 7
  PRPLEVEL 0:1.000000
  NAVFREQ 0 0
END

You can see the difference in the orientation and altitude. If I copied the orientation and the altitude from the parent to the cargo, it appears correctly. How to do that in code?
 
Last edited:

fred18

Addon Developer
Addon Developer
Donator
Joined
Feb 2, 2012
Messages
1,646
Reaction score
55
Points
63
Take a look at the source code of my generalvehicle addon, it shows how to deal with landed vessels and vesselstatus. The arot parameter isn't trivial, have a look at the code i mentioned. while to set the altitude from the ground you need iirc to set the vrot.x parameter. I can t attach links now because i m from the phone.

In anycase i d say that what you are experiencing is this: the arot and the altitude change meaning when a vessel is landed, especially arot. It becomes relative to the planet and not to the general reference system (this allows orbiter s core to manage landed vessels easily also at high time accelerations). So i think that somehow the issue is around this point. I will give it a deeper look when i ll have a pc available
 

N_Molson

Addon Developer
Addon Developer
Donator
Joined
Mar 5, 2010
Messages
7,920
Reaction score
999
Points
188
Location
Toulouse
I'm not a specialist but I would say it has (a lot) to do with VESSELMATRIX
 

Woo482

Moderator
Moderator
Addon Developer
GFX Staff
Joined
Feb 13, 2008
Messages
3,049
Reaction score
11
Points
78
Location
Earth?
If you're wanting to copy the attitude / heading of the vessel that deployed the cargo vessel it should be possible to avoid touching arot at all - this is how I've solved it in oMMU:
Code:
/* New MMU status variables */
VESSELSTATUS2 vesselStatus;
memset(&vesselStatus, 0, sizeof(vesselStatus));
vesselStatus.version = 2;
pParentVessel->GetStatusEx(&vesselStatus); // Copy parent state

/* Calculate degrees / meter */
double planetRadius = oapiGetSize(pParentVessel->GetSurfaceRef());
double metersPerDegree = (planetRadius * 2 * PI) / 360;
			
VECTOR3 rotatedPosition; // Holds the airlock position after being converted to horizon frame
pParentVessel->HorizonRot(airlock.position, rotatedPosition);

/* Update the position of the MMU vessel to be at the airlock */
vesselStatus.surf_lat += (rotatedPosition.z / metersPerDegree) * RAD; 
vesselStatus.surf_lng += (rotatedPosition.x / metersPerDegree) * RAD;

auto mmuVessel = oapiCreateVesselEx(mmuName, "oMMU", &vesselStatus);

It's probably not as robust a solution as calculating a new arot - but there's definitely a lot less math involved :lol:
 

Abdullah Radwan

Addon Developer
Addon Developer
Joined
Aug 20, 2017
Messages
240
Reaction score
78
Points
43
Location
Cairo
Many thanks Fred! Your GenericVehicle code worked perfectly. I've modified it slightly (just removed xyz parameter from RotationMatrix, as it's always true) Here is the code:

Code:
		MATRIX3 rot1 = RotationMatrix({ 0 * RAD, 90 * RAD - releaseLongitude, 0 * RAD });
		MATRIX3 rot2 = RotationMatrix({ -releaseLatitude + 0 * RAD, 0, 0 * RAD });
		MATRIX3 rot3 = RotationMatrix({ 0, 0, 180 * RAD + status.surf_hdg });
		MATRIX3 rot4 = RotationMatrix({ 90 * RAD, 0, 0 });
		MATRIX3 RotMatrix_Def = mul(rot1, mul(rot2, mul(rot3, rot4)));

		status.arot.x = atan2(RotMatrix_Def.m23, RotMatrix_Def.m33);
		status.arot.y = -asin(RotMatrix_Def.m13);
		status.arot.z = atan2(RotMatrix_Def.m12, RotMatrix_Def.m11);

I found that the GetMeshLowerPoint always returns 0, so it's unnecessary to change vrot. I've added your name to the credits list

@Woo482: Thanks for your code, but the same problem happened. Maybe it's due to mesh/touchdown points difference, as I am using 2010 touchdown points, not 2016 ones.
 
Last edited:

Abdullah Radwan

Addon Developer
Addon Developer
Joined
Aug 20, 2017
Messages
240
Reaction score
78
Points
43
Location
Cairo
If you're wanting to copy the attitude / heading of the vessel that deployed the cargo vessel it should be possible to avoid touching arot at all - this is how I've solved it in oMMU:
Code:
/* New MMU status variables */
VESSELSTATUS2 vesselStatus;
memset(&vesselStatus, 0, sizeof(vesselStatus));
vesselStatus.version = 2;
pParentVessel->GetStatusEx(&vesselStatus); // Copy parent state

/* Calculate degrees / meter */
double planetRadius = oapiGetSize(pParentVessel->GetSurfaceRef());
double metersPerDegree = (planetRadius * 2 * PI) / 360;
			
VECTOR3 rotatedPosition; // Holds the airlock position after being converted to horizon frame
pParentVessel->HorizonRot(airlock.position, rotatedPosition);

/* Update the position of the MMU vessel to be at the airlock */
vesselStatus.surf_lat += (rotatedPosition.z / metersPerDegree) * RAD; 
vesselStatus.surf_lng += (rotatedPosition.x / metersPerDegree) * RAD;

auto mmuVessel = oapiCreateVesselEx(mmuName, "oMMU", &vesselStatus);

It's probably not as robust a solution as calculating a new arot - but there's definitely a lot less math involved :lol:

Thank you very much! Your code made my life much easier without a lot of distance calculations for the cargo deployment position! I still need Fred18 code.

Code:
		VECTOR3 pos;
		vessel->GetAttachmentParams(attachsMap[slot], pos, VECTOR3(), VECTOR3());

		pos.x += releaseDistance;

		double metersPerDegree = (oapiGetSize(status.rbody) * 2 * PI) / 360;

		vessel->HorizonRot(pos, pos);

		status.surf_lng += (pos.x / metersPerDegree) * RAD;
		status.surf_lat += (pos.z / metersPerDegree) * RAD;

		MATRIX3 rot1 = RotationMatrix({ 0 * RAD, 90 * RAD - status.surf_lng, 0 * RAD });
		MATRIX3 rot2 = RotationMatrix({ -status.surf_lat + 0 * RAD, 0, 0 * RAD });
		MATRIX3 rot3 = RotationMatrix({ 0, 0, 180 * RAD + status.surf_hdg });
		MATRIX3 rot4 = RotationMatrix({ 90 * RAD, 0, 0 });
		MATRIX3 RotMatrix_Def = mul(rot1, mul(rot2, mul(rot3, rot4)));

		status.arot.x = atan2(RotMatrix_Def.m23, RotMatrix_Def.m33);
		status.arot.y = -asin(RotMatrix_Def.m13);
		status.arot.z = atan2(RotMatrix_Def.m12, RotMatrix_Def.m11);
		status.vrot.x = 0.65;
 
Top