SDK Question Setting vessel velocity from a plugin

dumbo2007

Crazy about real time sims
Joined
Nov 29, 2009
Messages
675
Reaction score
0
Points
0
Location
India
Hi,

I am trying to set the velocity of a vessel using the code given in :

http://www.orbiter-forum.com/showthread.php?t=14764

So i use this code in the clbkPreStep() function of the plugin:

VESSELSTATUS2 mystat;
memset(&mystat,0,sizeof(VESSELSTATUS2));
mystat.version = 2;
VESSEL* v = (VESSEL*)(vessel[0].hVessel);
v->GetStatusEx(&mystat);

vessel[] is an array of all vessels in the scenario. But I get an error :
First-chance exception at 0x00482577 in Orbiter.exe: 0xC0000005: Access violation reading location 0x652065bb.
Unhandled exception at 0x00482577 in Orbiter.exe: 0xC0000005: Access violation reading location 0x652065bb.

Is it not allowed to set the vessel velocity from outside the vessel ? I have not reached the setting part yet using DefSetStateEx() as for that GetStatusEx() has to work first.
 
Last edited:
It looks like you're casting a handle to a vessel (hVessel) into a VESSEL pointer. That won't work--use oapiGetVesselInterface().
 
VESSELSTATUS2 mystat;
memset(&mystat,0,sizeof(VESSELSTATUS2));
mystat.version = 2;
VESSEL* v = oapiGetVesselInterface((vessel[0].hVessel));
v->GetStatusEx(&mystat);


double longitude, latitude, radius;
oapiGetEquPos(vessel[0].hVessel, &longitude, &latitude, &radius);
radius = oapiGetSize(mystat.rbody) + 3.0f;
oapiEquToLocal(mystat.rbody, longitude, latitude, radius, &mystat.rpos);

v->DefSetStateEx(&mystat);

ok now I am trying to suspend the delta glider 3 metres above the surface of its pad on Brighton Beach. So I found the equatorial co-ordinates using oapiGetEquPos() - it should use the moon as the reference - and added 3 metres to the radius. Then I converted to local cartesian co-ordinates using the moon as the local object and set it using DefSetStateEx(). This should make it hover above its position as I set the position specifically every turn. But the DG does random movements around the moon instead. Am I doing something wrong ?

I logged the values and they are :
Initial DG co-ordinates wrt moon
1161787.803009, 1171797.204320, -545704.449387

Equatorial co-ordinates before setting altitude of 3 m
-0.583594, 0.717882, 1738002.570000

Equatorial co-ordinates after setting altitude of 3 m
-0.583594, 0.717882, 1738003.000000

Final DG co-ordinates wrt moon
1092398.445986, 1143242.150966, -721330.331729

The final co-ordinates seems very different.

When I try to use the Brighton Beach pad 4 to fix the location of the DG using :

oapiGetBasePadEquPos(hBase[35], 3, &longitude, &latitude, &radius); //hBase[] is an array of all handles to the bases in the scenario

sprintf(output, "%s : %f, %f, %f", output, longitude, latitude, radius);
radius = oapiGetSize(mystat.rbody) + 3.0f;

oapiEquToLocal(mystat.rbody, longitude, latitude, radius, &mystat.rpos);

sprintf(output, "%s : %f, %f, %f", output, longitude, latitude, radius);
sprintf(output, "%s : %f, %f, %f", output, mystat.rpos.x, mystat.rpos.y, mystat.rpos.z);
oapiWriteLog(output);

v->DefSetStateEx(&mystat);

The position of DG is still changing randomly and its placed somewhere else.
 
Last edited by a moderator:
VESSELSTATUS2.rpos is a vector from rbody to the vessel in the ecliptic frame. You are setting it as a vector in the body frame of rbody. You need to rotate the vector to the ecliptic frame first.

Personally, I think a simpler technique would be to just set the length of rpos directly:
Code:
mystat.rpos = (mystat.rpos/length(mystat.rpos)) * (oapiGetSize(mystat.rbody) + 3.0);
v->DefSetStateEx(&mystat);
 
Thanks so much for the reply. It works as expected.

So this gets the unit vector : (mystat.rpos/length(mystat.rpos))
and that is then multiplied by the required length I guess.

But I do not understand how the earlier way is incorrect which is due to me being a bit unclear on the various reference frames in use in orbiter. Suppose I wanted to do the rotation after getting the equatorial position, then how should I proceed. According to my understanding so far :

the following function :
oapiGetEquPos(vessel[0].hVessel, &longitude, &latitude, &radius);
does return a vessel's spherical equatorial coordinates (longitude, latitude and radius) with respect to the closest planet or moon.
So I got -0.583594, 0.717882, 1738002.570000, where 1738000 is the moon's radius and 2.57 is the height of the dg above the ground.

Then
radius = oapiGetSize(mystat.rbody) + 3.0f;
oapiEquToLocal(mystat.rbody, longitude, latitude, radius, &position_wrt_moon_centre); //position_wrt_moon_centre is a VECTOR3
should return the cartesian co-ordinates wrt moon's centre.

Now rpos is in the ecliptic frame of reference. As I undertand this is the frame defined by the plane of earths orbit and the Sun is at the origin. So how would I calculate the rpos which is wrt ecliptic frame of reference from position_wrt_moon_centre ?

Also if i was setting rpos to the position wrt the moon instead of wrt ecliptic frame, then the dg should not have been anywhere near to the moon but should instead have been near the Sun. But it is quite close to the moon.
 
Last edited:
The problem is that you are calculating the vessel position in the planet's local, rotating frame of reference (y-axis in direction of planet's north pole, x-axis towards lng=0/lat=0). The oapiEquToLocal function essentially only converts from polar to cartesian coordinates.

What the vessel state requires however is the position in the ecliptic frame. To convert from the planet-local frame to the ecliptic frame, you have to rotate the point you get with oapiEquToLocal with the planet's rotation matrix (oapiGetRotationMatrix).

But since you only want to adjust the radius, the method suggested by tblaxland is much more efficient.
 
Thanks Martin. Well I am attempting this to learn the coordinate transformation functions rather than as part of an addon. So this is what I do now :
Code:
double longitude, latitude, radius;
VECTOR3 position_wrt_moon_frame;
MATRIX3 mat;
	
oapiGetBasePadEquPos(hBase[35], 3, &longitude, &latitude, &radius);
sprintf(output, "Got base pad Polar co-ords(lo,la,r): %f, %f, %f", longitude, latitude, radius);
oapiWriteLog(output);
	
radius = radius + 5.0f;
sprintf(output, "Added radius(lo,la,r): %f, %f, %f", longitude, latitude, radius);
oapiWriteLog(output);

oapiEquToLocal(mystat.rbody, longitude, latitude, radius, &position_wrt_moon_frame);
sprintf(output, "Converted to cartesian position in Moon's Ref Frame : %f, %f, %f", position_wrt_moon_frame.x, position_wrt_moon_frame.y, position_wrt_moon_frame.z);
oapiWriteLog(output);

oapiGetRotationMatrix(mystat.rbody, &mat); 
mystat.rpos = mul(mat, position_wrt_moon_frame);
sprintf(output, "Rotated by Planet's rotation matrix: %f, %f, %f", mystat.rpos.x, mystat.rpos.y, mystat.rpos.z);	
oapiWriteLog(output);

So I do get the DG suspended 5 m over the pad, but its not very stable and keeps on moving up or down. The earlier method of multiplying the vector by the required length had no such problems. So is the DG not stable due to calculation errors accumulated in the many calls to the coordinate transformation functions ?
 
Last edited:
So I do get the DG suspended 5 m over the pad, but its not very stable and keeps on moving up or down. The earlier method of multiplying the vector by the required length had no such problems. So is the DG not stable due to calculation errors accumulated in the many calls to the coordinate transformation functions ?
Perhaps :shrug:. What is the range of motion, and is it vertical only or does it also occur laterally?

FWIW, I have a reference frame guide in the works. Not much to show ATM, but hopefully it will help when it is finally done.

BTW, can you please wrap your code in [code][/code] tags when you post it? It makes it much easier to read. More info on bbcodes here.
 
The movement is only vertical. No lateral movement.

Great that you have a reference guide in mind. Will it include a guide to the function calls as well for converting from 1 frame to another ?
 
The movement is only vertical. No lateral movement.

This is curious, because it suggests that the problem arises in the polar part of the calculation, not the cartesian part. Otherwise I would expect the noise to cause jitter in all directions.

I assume that the first part of the calculations,
Code:
oapiGetBasePadEquPos(hBase[35], 3, &longitude, &latitude, &radius);
radius = radius + 5.0f;
oapiEquToLocal(mystat.rbody, longitude, latitude, radius, &position_wrt_moon_frame);
is done only once, since position_wrt_moon_frame doesn't change between frames, and only the multiplication with the rotation matrix is performed at each frame:
Code:
oapiGetRotationMatrix(mystat.rbody, &mat); 
mystat.rpos = mul(mat, position_wrt_moon_frame);
So the only source of error I can see is if the rotation matrix used is out of sync with the frame it is applied in (e.g. vessel state is applied a frame after the rotation matrix was valid). You can test that by forcing constant step lengths in the debug options and checking if that reduces the jitter. Also, if you applied the vessel state in clbkPostStep, try clbkPreStep or vice versa and see if this makes a difference.

Still, this doesn't explain why the jitter only occurs in altitude. (BTW you should remove the 'f' postfix in your 5.0 altitude shift. It won't fix the problem here since the result is constant anyway, but there is no good reason for adding a small single-precision constant to a large double-precision variable.)

Edit:
Actually, there is something odd going on. Applying the rotation matrix should not change the length of the position vector. So any problems with it should only cause a lateral offset, not a radial one. But you are reporting the exact opposite problem. Unless the rotation matrix is corrupt (e.g. not orthonormal), which is unlikely, it should not cause this particular problem.

Here is what you could try:

  • Make sure that the length of the position vector is correct before you apply the rotation
  • Make sure that the length is still the same after the rotation.
  • Compare the position vector you get with this method with the one from the working method. For that it is best to convert both to polar format. Do they really differ only in length?
Somewhere there is an inconsistency here. I can't fathom how you can get a jitter in altitude and nothing else with the above code. You haven't used single-precision arithmetic anywhere else in your code?
 
Will it include a guide to the function calls as well for converting from 1 frame to another ?
Function calls/code samples as appropriate, to supplement conventional vector/matrix notation, is how I have started. I was also hoping to include some graphics too, but that might stretch the time budget too much :shrug:
 
To add to Martin's comments: How much does the radius vary by? Can you post some of the numbers you are writing to the log?
 
It does not appear to vary by more than a meter and its definitely only vertical.

Here is the code used
Code:
// ==============================================================
//                 ORBITER MODULE: Bump
//                  Part of the ORBITER SDK
//          Copyright (C) 2002-2004 Martin Schweiger
//                   All rights reserved
//
// Bump.cpp
// Control module for Bump Plugin class
//
// ==============================================================

#define STRICT
#define ORBITER_MODULE

#include <stdlib.h>
#include <tchar.h>

#include "orbitersdk.h"
#include "ModuleAPI.h"


char output[1000];



// ==============================================================
// Bump class interface
// ==============================================================

class Bump: public oapi::Module {	
	

public:
	Bump (HINSTANCE  hModule) : oapi::Module (hModule) {}
	~Bump(){}
	
	//Module Overrides
	void	clbkPreStep(double SimT, double SimDT, double MJD);	
	void	clbkSimulationStart(RenderMode mode);
	void	clbkSimulationEnd();	
	
};



// --------------------------------------------------------------
// Plugin initialisation
// --------------------------------------------------------------
DLLCLBK void InitModule  ( HINSTANCE  hModule   )  
{
	oapiWriteLog("Bump: Initing !");
	oapiRegisterModule(new Bump (hModule));
	
}

// --------------------------------------------------------------
// Plugin cleanup
// --------------------------------------------------------------
DLLCLBK void ExitModule  ( HINSTANCE  hModule   )  
{		

	oapiWriteLog("Bump: Exiting");	

}



void Bump::clbkPreStep(double SimT, double SimDT, double MJD) 
{
	VESSELSTATUS2 mystat;
	double longitude, latitude, radius;
	VECTOR3 position_wrt_moon_frame;
	MATRIX3 mat;


	memset(&mystat,0,sizeof(VESSELSTATUS2));
	mystat.version = 2;
	VESSEL* v = oapiGetVesselInterface(oapiGetVesselByName("GL-NT"));
	v->GetStatusEx(&mystat);		
	
	//oapiGetEquPos(vessel[0].hVessel, &longitude, &latitude, &radius);
	
	oapiGetBasePadEquPos(oapiGetBaseByName(oapiGetGbodyByName("Moon"),"Brighton Beach"), 3, &longitude, &latitude, &radius);
	sprintf(output, "Got base pad Polar co-ords(lo,la,r): %f, %f, %f", longitude, latitude, radius);oapiWriteLog(output);
	
	radius = radius + 5.0f;
	sprintf(output, "Added radius(lo,la,r): %f, %f, %f", longitude, latitude, radius);oapiWriteLog(output);

	oapiEquToLocal(mystat.rbody, longitude, latitude, radius, &position_wrt_moon_frame);
	sprintf(output, "Converted to cartesian position in Moon's Ref Frame : %f, %f, %f", position_wrt_moon_frame.x, position_wrt_moon_frame.y, position_wrt_moon_frame.z);
	oapiWriteLog(output);

	oapiGetRotationMatrix(mystat.rbody, &mat); 
	mystat.rpos = mul(mat, position_wrt_moon_frame);
	sprintf(output, "Rotated by Planet's rotation matrix: %f, %f, %f", mystat.rpos.x, mystat.rpos.y, mystat.rpos.z);	
	oapiWriteLog(output);

	v->DefSetStateEx(&mystat);

	v->GetStatusEx(&mystat);
	sprintf(output, "After setting position : %f, %f, %f\n----------",  mystat.rpos.x, mystat.rpos.y, mystat.rpos.z);	
	oapiWriteLog(output);


	
			
}

void Bump::clbkSimulationStart(RenderMode mode) 
{
	oapiWriteLog("Bump: Sim starting");	

		
}

void Bump::clbkSimulationEnd()  
{
	oapiWriteLog("Bump: Sim ending");
	
}

And the obtained orbiter log is attached after running for about a minute. Scenario used was Delta-glider/Brighton Beach.

I have a question regarding the ecliptic frame of reference. So it has the centre of the earth at the origin, with the y-axis pointing towards the ecliptic north pole ? And the x-axis towards the vernal equinox ? Which would mean the xz plane is in the same plane as the sun-earth orbital plane.
 

Attachments

Last edited:
It does not appear to vary by more than a meter and its definitely only vertical.
I haven't graphed the numbers in your log nor tried your module, but that amount of variation in altitude is not readily apparent to me from the numbers :hmm:

Martin, I am curious about the difference in the output between these two chunks of code:
Code:
	sprintf(output, "Rotated by Planet's rotation matrix: %f, %f, %f", mystat.rpos.x, mystat.rpos.y, mystat.rpos.z);	
	oapiWriteLog(output);
	v->DefSetStateEx(&mystat);

	v->GetStatusEx(&mystat);
	sprintf(output, "After setting position : %f, %f, %f\n----------",  mystat.rpos.x, mystat.rpos.y, mystat.rpos.z);	
	oapiWriteLog(output);
What occurs between DefSetStateEx and GetStatusEx that would cause VESSELSTATUS2::rpos to change? The change is only small, but surprising.

I have a question regarding the ecliptic frame of reference. So it has the centre of the earth at the origin with the y-axis pointing towards the ecliptic north pole ? And the x-axis towards the vernal equinox ? Which would mean the xz plane is in the same plane as the sun-earth orbital plane.
No. What I have written about it in my document thus far:
3.2 Ecliptic (aka Global)

Handedness Left

Parent None

Origin Solar System barycentre at J2000

+X-axis Points to the longitude of the ascending node of the mean ecliptic plane through the mean equatorial plane of Earth at J2000

+Y-axis Cross product of +Z with +X

+Z-axis Perpendicular to the mean ecliptic plane at J2000, on the same side as the orbital angular momentum of Earth​
 
Back
Top