PDA

View Full Version : Compass +GPS



Al Grant
08-04-2006, 01:43 PM
Hi Folks,

I am writing a little program to display a graphical compass using opengl. The source data about headings etc comes from a library I am using which allows you to connect to a GPS.

I have two problems tho:

1. The GPS I have can update the heading 5 times per second, yet the openGL can update at about 60 times a second. Whats a good way to avoid calling the GPS routine unnessecarily?

2. In theory, the GPS could give a heading of say 050, then the next reading might be 065. To simulate a real world compass, and to look good, opengl wants to rotate smootly (albiet very fast) so I guess I need a if loop with roatate1 being the start value until hit reaches rotate2 and then rotate1 needs to take on the next compass reading and loop from rotate2 until it hits rotate1 value again?

Could someone please try to formalise this logic for me please?

Thanks heaps in advance,

-Al

zeoverlord
08-04-2006, 02:03 PM
1. take a float variable(0.0f), and for each frame add the delta time to this variable(in seconds), then if the variable is above 0.2 then read the gps and subtract the variable with 0.2

2. in this case you have to delay any reaction with 0.2 seconds.
To do this, whenever you read a GPS heading then start moving the previous heading towards the new one at a rate that corresponds to 0.2 seconds.

It's relativly easy to implement, but a bit hard to explain.

Al Grant
08-04-2006, 02:35 PM
zeoverlord - you're always helpful, and give great answers!!

How do I get delta time?

-Al

zeoverlord
08-04-2006, 05:54 PM
It depends on your platform, in most APIs there are some kind of timing functions, most give the time in milliseconds after the program was started.

In my own game engine i use this before every frame to get the delta time, it is based on the windows API.

tickCount = GetTickCount();
deltaTime = ((float)(tickCount - lastTickCount))/1000;
lastTickCount = tickCount;

This version is based on the SDL API (used in the new NeHe lessons).

m_currentTime = SDL_GetTicks();
delta = static_cast<float>(m_currentTime - m_lastTime) / 1000.0f;
m_lastTime = m_currentTime;

Unfortunatly i can't tell you exactly how it should look like because i don't know what API you are using, but i think you can figure it out.

k_szczech
08-05-2006, 02:40 AM
About #1 - if you subtract 0.2 second every time you read gps you will get average delay of 0.2 seconds.
If you want to make sure that delay will be no less than 0.2s then instead of subtracting 0.2 just reset value to 0.0.

Al Grant
08-06-2006, 04:46 PM
zeoverlord,

I have tried to impliment the solution, but somethnig is not quite right.

Please let me know if you spot something. The important parts are as below:



void GetGPSData()
{int Code;
char *pend;

// lock data buffer
mgcLockData(1);
// get timestamp
Code = mgcGetData(GPRMC_COURSE,(LPSTR)DataBuffer);
if(Code<0) ShowMGC32Error(Code);
// if(Code>0) course=(LPSTR)DataBuffer;
course=strtod(DataBuffer, &amp;pend);
mgcLockData(0); // Lock Data Buffer
Sleep(200);

deltacourse=(course-lastcourse);
lastcourse=course;

courseincrement=(deltacourse/(1/deltaTime));
} /* end GetGPSData */

// EXTRACT FROM WINMAIN
while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&amp;msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&amp;msg); // Translate The Message
DispatchMessage(&amp;msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if (active) // Program Active?
{
if (keys[VK_ESCAPE]) // Was ESC Pressed?
{
done=TRUE; // ESC Signalled A Quit
}
else // Not Time To Quit, Update Screen
{ tickCount = GetTickCount();
deltaTime = ((float)(tickCount - lastTickCount))/1000;
lastTickCount = tickCount;

timecounter=timecounter+deltaTime;

if (timecounter>1.0)
{
GetGPSData();
timecounter=0;
}

DrawGLScene(); // Draw The Scene
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
course=lastcourse+courseincrement;
}
}

if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}

//EXTRACT FROM GLDRAWSCENE
glPushMatrix();
glRotatef(course,0.0f,0.0f,1.0f);
glBegin(GL_LINES); // LINES FORMING EDGE OF COMPASS ROSE
for (deg=0;deg<360;deg+=10)
{
d = deg*pi/180;
glVertex3f(2.0*cos(d),2.0*sin(d),0.0f);
glVertex3f(2.25*cos(d),2.25*sin(d),0.0f);
}
glEnd();