The Source for Java Technology Collaboration
User: Password:



Joerg Plewe's Blog

September 2007 Archives


Head banging...

Posted by herkules on September 30, 2007 at 10:58 AM | Permalink | Comments (2)

TrackIR is a headtracking device that currently is quite popular amongst gamers, especially in the simulation community.
It consists of a small device to be placed on top of the monitor and a prepared base cap with three IR reflecting strips.
JTrackIR is my Java binding. Not a big thing, but maybe useful to somebody.


TrackIR4-laptop-TrackClip-hat.jpg

2inch-TRACKIR4-iso-ns.jpg

TrackIR shows an impressive resolution and supports all 6 axes (x,y,z,yaw,pitch,roll). So it not only detects the heads attitude but also the translational position and even the heads distance from the screen.

6DOFmovement.jpg

The device is not cheap but also not extraordinary expensive and definitely worth the money if you have a good use-case.

As with all parts of the Distributed RealTime Simulation project on SourceForge, the source is available from cvs.
The Java source code is free while I'm not allowed to opensource the C/C++ code accessing the TrackIR DLL because it is covered under an NDA. So you have to refer to the compiled binary located in the bin directory.

The API is stupid simple. For there can only be a single device, the API layout is completely static. Here are parts of it:


public static void setDeveloperID( int id );
public static void update();
public static boolean isOperational();
public static float getRoll();
public static float getPitch();
public static float getYaw();
public static float getX();
public static float getY();
public static float getZ();
...


The jar file in the bin folder there also contains a simple test UI that paints the values as it is delivered by the device.

.


jtrackir_screenshot.jpg


Currently, JTrackIR is not yet embodied to FlyingGuns. My own architecture placed the camera far away from the input system, so they are hard to connect :). But there is still some hope.

If you think controlling something with your head and you like to use your head not only for its mental power, JTrackIR allows you to do that easily and your application might proudly show a new logo:
trackir_logo50.jpg




A simple physics/dynamics stack

Posted by herkules on September 23, 2007 at 10:09 AM | Permalink | Comments (12)

Are you doing engineering using Java? Or even science? Than you sometimes might need to calculate how objects move under the impression of forces and torques. The following might be for you then...

Maybe somebody of you, dear reader, has already tried out my flight simulator FlyingGuns which is part of the Distributed RealTime Simulation project on SourceForge. The flight model of motion is very simple. I call it physically motivated instead of physical because it relies on some heuristics that are not modeled using forces and torques. That is appropriate for a game but not for a true simulator.

There is no framework to plug in forces that are then correctly treated. This is the main reason why the airplane cannot land, because there is just no mean to model the forces caused by the undercarriage on the ground.

In order to change this, I started to develop a simple dynamics framework. It currently is located in the projects sandbox because the API is not fully settled yet. With this package, it is easy to define bodies that behave physically correct. This is a piece of sample code to setup a 5kg body with gravity G and a Spring:

Body body = new Body();
body.setMass(5.0);

KinematicState state = new KinematicState();
state.attitude(QuatUtil.ONEd);		

CompositeForce f = new CompositeForce();
f.addForce(new G(body));

Vector3d springcenter = new Vector3d(0,0,5);
Spring s = new Spring(springcenter, 5 );
f.addForce( s );

Dynamic dynbody = new Dynamic(body, state, f);
		


I call it dynamics stack to keep it apart from a physics engine like ODEJava or JOODE. A physics engine is a far more complex beast dealing a lot with collision detection and - as a main task - computing the appropriate forces. But any physics engine needs some kind of dynamics code under the hood.

There is no secret in how to do that. The math is known for hundreds of years meanwhile. Yet some aspects, esp. those concerning rotational motion are highly unintuitive (it took me 2 years to develop kind of mental image). Having this thoroughly solved makes the value of this package.

Stack

Why is it a stack? Because on each level of the stack there is a set of classes implementing the interface of the next lower level. Each level of the stack can be used on its own, omitting higher levels as desired. These are the stacked components:
  • intergrator
  • kinematics
  • dynamics
  • physics
  • application, e.g. flight model
dynamics_overview.jpg

Integration

Integration has the task to solve ordinary differential equations (ODE). It gets some initial values and an object that can calculate the resp. derivatives in time d/dt. The integrator has no idea what the values do mean - it has no notion of e.g. position or speed.
There are several well-known ways to do that with different quality and performance. My package implements Euler and RungeKutta. While the algorithms are not easy to understand, the resp. code is quite simple because the algorithms are very well described in various textbooks and there are many samples on the net. Cash-Karp (see Numerical Recipes in C) is currently under development.

The Euler integrator is the most simple one basically perfoming:

x_new = x_old + v*dt

Thats very fast, but only works if forces are small and do hardly ever change. A common spring already may blow that approach. RungeKutta is much more advanced but also takes (at least) four times more CPU power.

Kinematics

Kinematics gives a meaning to terms like position or speed and can transform them to the array of values needed by the integrator. It also respects that we are dealing with second order differential equations (eg. position is order 0, velocity is order 1, acceleration is order 2) and transforms them into a system of equations of first order:
One second order equation
			position = f( velocity, acceleration )
        
makes 2x first order equation:
			position = f(velocity)
			velocity = f(acceleration)
        
On the kinematics level, the interface Acceleration plays the key role. On this level, there still is no notion of a phyical body having mass properties.

Dynamics

Dynamics introduces the phyical body having mass and inertia. A class implementing the kinematics interface Acceleration converts forces and torques acting on a physical body into acceleration. While this is trivial for translational properties (just divide by mass - F=ma - remember?), the rotational parts needs some consideration concerning world- and body-fixed coordinate systems and the transforms between them. On the dynamics level, the interface Force plays the key role.

Physics

On this level, forces and torques are defined. It is not truely a level in the stack, but more a collection of utilities. There are predefined forces like gravity G or a spring. Conceptually harder is a class called RotatingPart which allows to model parts within a body that do rotate themselves. Think of propellers or turbines as an example. Again, this rotational things are not easy to deal with on an intuitive level.

Tests

Now how to test dynamics? I took two approaches. One is the classical unit test comparing the results of the integration with a know analytical solution. Here is one taken from a textbook:

	
// problem 10-32 in my edition of Classical Dynamics by Marion+Thornton
@Test
public void spinningPlate() 
{
    Body b = new Body();

    // I1 = 1, I2 = 2*I1, I3 = I1 + I2
    b.setInertia(new Matrix3d(1.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 3.0));

    KinematicState state = new KinematicState();
    state.omega(new Vector3d(Math.sqrt(3), 0, 1));

    // with no forces and torques, w_body_y(t) should be |w| cos(a) tanh(|w| t sin(a)).
    // a = 30 degrees, so cos(a) = sqrt(3)/2 and sin(a) = 1/2.  the expected result is
    // thus sqrt(3) * tanh(t).		

    Dynamic d = new Dynamic(b, state, Force.NONE );

    double dt = 1.0/1000.0;
    double t = 0;
    for( int i = 0; i < 300; i++ )
    {
        d.progress((long)t, dt);
        t += dt;
//		System.out.println(i + " " + Math.sqrt(3)*Math.tanh(t) + " " +  state.omega().y);
        assertEquals(Math.sqrt(3)*Math.tanh(t), state.omega().y, 0.05 );
    }
}


The other approach is piecewise comparison with a human judging from the visuals. E.g. assuming euler integration works, I run the system with a RungeKutta integration. The results have to be comparable. The same can be done to show that the calculation of acceleration from forces work correct or that a rotating body behaves like one that does not rotate, but has a rotating part with same inertia.

screenshot_DynamicSample.jpg

Next

Things to come (besides an application for a new flight model for FlyingGuns) is some kind of exception handling in case of overstress. Sometime, forces may go beyond their limits that e.g. may destroy the structure. This could be implemented using exceptions.

Links





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds