Tank rotations out of control

Started by brainmaster, April 08, 2007, 03:33:12 AM

Previous topic - Next topic

brainmaster

I am working on a simple tank game, move around in tank and shoot stuff. I based my move rotation on the car example (the tilting based on ground), but I am having problems. The tank moves correctly for a while on the hills i made, but it soon rotates out of control and flies upward. Any help?


public boolean place(Object3D ground) {
//get bottom direction
Object3D o = new Object3D(3);
o.addTriangle(getFrontTireRight().getTransformedCenter(),
getBackTireLeft().getTransformedCenter(),
getFrontTireLeft().getTransformedCenter());
o.calcNormals();
SimpleVector v = o.getPolygonManager().getTransformedNormal(0);
float dis = 300f;
boolean good = false;
Object3D body = getBody();
//move up in case of vertical ascending
body.translate(0,-150,0);
float disFrontLeftBottom  = getTireLeft().rayIntersectsAABB(
getFrontTireLeft().getTransformedCenter(),v,false);
float disFrontRightBottom = getTireRight().rayIntersectsAABB(
getFrontTireRight().getTransformedCenter(),v,false);
float disBackLeftBottom   = getTireLeft().rayIntersectsAABB(
getBackTireLeft().getTransformedCenter(),v,false);
float disBackRightBottom  = getTireRight().rayIntersectsAABB(
getBackTireRight().getTransformedCenter(),v,false);
float disCenterBottom     = getTireLeft().rayIntersectsAABB(
getTireInsideLeft().getTransformedCenter(),v,false);
SimpleVector vFrontLeft  = new SimpleVector(
getFrontTireLeft().getTransformedCenter());
SimpleVector vFrontRight = new SimpleVector(
getFrontTireRight().getTransformedCenter());
SimpleVector vBackLeft   = new SimpleVector(
getBackTireLeft().getTransformedCenter());
SimpleVector vBackRight  = new SimpleVector(
getBackTireRight().getTransformedCenter());
SimpleVector vBody       = new SimpleVector(
getBody().getTransformedCenter());
vFrontLeft.add(new SimpleVector(0,-disFrontLeftBottom,0));
vFrontRight.add(new SimpleVector(0,-disFrontRightBottom,0));
vBackLeft.add(new SimpleVector(0,-disBackLeftBottom,0));
vBackRight.add(new SimpleVector(0,-disBackRightBottom,0));
vBody.add(new SimpleVector(0,-disCenterBottom,0));
float tireFrontLeft  = ground.calcMinDistance(vFrontLeft,v,dis*10);
float tireFrontRight = ground.calcMinDistance(vFrontRight,v,dis*10);
float tireBackLeft   = ground.calcMinDistance(vBackLeft,v,dis*10);
float tireBackRight  = ground.calcMinDistance(vBackRight,v,dis*10);
float bodyDis        = ground.calcMinDistance(vBody,v,dis*10);
if (tireFrontLeft !=Object3D.COLLISION_NONE&&
tireFrontRight!=Object3D.COLLISION_NONE&&
tireBackLeft  !=Object3D.COLLISION_NONE&&
tireBackRight !=Object3D.COLLISION_NONE) {
good = true;

//Vert Balance, rotation on X
double angleFront=((tireFrontRight+tireFrontLeft)/2-bodyDis);
    double as=(angleFront/(bodyDisToFront))%1;
    angleFront=Math.asin(as);
    double angleRear=-((tireBackRight+tireBackLeft)/2-bodyDis);
        as=(angleRear/(bodyDisToBack))%1;
        angleRear=Math.asin(as);
    float rot=(float) ((angleFront+angleRear)/2);
        body.rotateX(rot);
       
    //Hori Balance, rotation on Z
        double angleLeft=((tireFrontLeft+tireBackLeft)/2-bodyDis);
        as=(angleLeft/(bodyDisToLeft))%1;
        angleLeft=Math.asin(as);
    double angleRight=-((tireBackRight+tireFrontRight)/2-bodyDis);
        as=(angleRight/(bodyDisToRight))%1;
        angleRight=Math.asin(as);
    rot=(float) ((angleLeft+angleRight)/2);
        body.rotateZ(rot);
       
        //move
        body.translate(0,bodyDis,0);
                     return good;
}

EgonOlsen

Maybe one of the wheels is missing the ground, so that the if is never taken and the -150 upwards never really reseted?

brainmaster

I found another problem with my code. After finding the angles, I move the tank directly down instead of in the direction the base of the tank was facing, so I fixed that. Now the tank moves better over the map, but it wobbles at times when it is not supposed to and on a flat surface in certain positions the tank rotates again out of control and gets stuck with its face in the ground.

Here's the improved code
maxVertDis is the max ascention the tank may take
public boolean place(Object3D ground) {
//get bottom direction
Object3D o = new Object3D(3);
o.addTriangle(getFrontTireRight().getTransformedCenter(),
getBackTireLeft().getTransformedCenter(),
getFrontTireLeft().getTransformedCenter());
o.calcNormals();
SimpleVector v = o.getPolygonManager().getTransformedNormal(0);
v = v.normalize();
float dis = 300f;
boolean good = false;
Object3D body = getBody();
//move up based on tank pos for ascension
body.translate(v.x*-maxVertDis,v.y*-maxVertDis,v.z*-maxVertDis);
float disFrontLeftBottom  = getTireLeft().rayIntersectsAABB(
getFrontTireLeft().getTransformedCenter(),v,true);
float disFrontRightBottom = getTireRight().rayIntersectsAABB(
getFrontTireRight().getTransformedCenter(),v,true);
float disBackLeftBottom   = getTireLeft().rayIntersectsAABB(
getBackTireLeft().getTransformedCenter(),v,true);
float disBackRightBottom  = getTireRight().rayIntersectsAABB(
getBackTireRight().getTransformedCenter(),v,true);
float disCenterBottom     = getTireLeft().rayIntersectsAABB(
getTireInsideLeft().getTransformedCenter(),v,true);
SimpleVector vFrontLeft  = new SimpleVector(
getFrontTireLeft().getTransformedCenter());
SimpleVector vFrontRight = new SimpleVector(
getFrontTireRight().getTransformedCenter());
SimpleVector vBackLeft   = new SimpleVector(
getBackTireLeft().getTransformedCenter());
SimpleVector vBackRight  = new SimpleVector(
getBackTireRight().getTransformedCenter());
SimpleVector vBody       = new SimpleVector(
getBody().getTransformedCenter());
vFrontLeft.add(new SimpleVector(v.x*-disFrontLeftBottom,
v.y*-disFrontLeftBottom,v.z*-disFrontLeftBottom));
vFrontRight.add(new SimpleVector(v.x*-disFrontRightBottom,
v.y*-disFrontRightBottom,v.z*-disFrontRightBottom));
vBackLeft.add(new SimpleVector(v.x*-disBackLeftBottom,
v.y*-disBackLeftBottom,v.z*-disBackLeftBottom));
vBackRight.add(new SimpleVector(v.x*-disBackRightBottom,
v.y*-disBackRightBottom,v.z*-disBackRightBottom));
vBody.add(new SimpleVector(v.x*-disCenterBottom,
v.y*-disCenterBottom,v.z*-disCenterBottom));
float tireFrontLeft  = ground.calcMinDistance(vFrontLeft,v,dis*10);
float tireFrontRight = ground.calcMinDistance(vFrontRight,v,dis*10);
float tireBackLeft   = ground.calcMinDistance(vBackLeft,v,dis*10);
float tireBackRight  = ground.calcMinDistance(vBackRight,v,dis*10);
float bodyDis        = ground.calcMinDistance(vBody,v,dis*10);
if(tireFrontLeft !=Object3D.COLLISION_NONE&&
   tireFrontRight!=Object3D.COLLISION_NONE&&
   tireBackLeft  !=Object3D.COLLISION_NONE&&
   tireBackRight !=Object3D.COLLISION_NONE&&
   bodyDis       !=Object3D.COLLISION_NONE){
good = true;
//Vert Balance, rotation on X
double angleFront=((tireFrontRight+tireFrontLeft)/2-bodyDis);
    double as=(angleFront/(bodyDisToFront))%1;
    angleFront=Math.asin(as);
    double angleRear=-((tireBackRight+tireBackLeft)/2-bodyDis);
        as=(angleRear/(bodyDisToBack))%1;
        angleRear=Math.asin(as);
    float rot=(float) ((angleFront+angleRear)/2);
        body.rotateX(rot);
       
    //Hori Balance, rotation on Z
        double angleLeft=((tireFrontLeft+tireBackLeft)/2-bodyDis);
        as=(angleLeft/(bodyDisToLeft))%1;
        angleLeft=Math.asin(as);
    double angleRight=-((tireBackRight+tireFrontRight)/2-bodyDis);
        as=(angleRight/(bodyDisToRight))%1;
        angleRight=Math.asin(as);
    rot=(float) ((angleLeft+angleRight)/2);
        body.rotateZ(rot);
       
        //move based on new
        body.translate(v.x*bodyDis,v.y*bodyDis,v.z*bodyDis);
        saveToLastLoc();
}else
{
resetToLastLoc();
}

return good;
}

brainmaster

I figured out the problem with my method. Once it calculates the angle to rotate the tank and then moves downward based on the center, the newly made angles will not be correct, depending on the ground below they usually are close to correct. This inacurracy becomes more accurate if the tank stays still and the place method is called repeatingly. I know of no way to improve my current method to make it accurate since i would have to select specific points on the field. Does anyone know of an accuracte method?

EgonOlsen

I'm not sure if i understand this totally...you are calculating an angle for the base similar to the car example and then move the base/tank down in the direction of the base's normal after rotation? That's basically what the car example does except that it moves straight down IIRC. That approach wasn't working in your case?

brainmaster

You understand it correctly. In the car example, the new positions for the wheels are set with so that the horizontal distance is always the same by using atan. That causes the length/width of the car to change slightly when placed. I used asin to keep the distance from the center to the ends of the tire the same, but by keeping the distances the same, rotating and translating doesn't put them where they were calculated to be. Depending on the angle the ends do not reach the rays intersection.
_____________________________________
|                        |                               |
|                       /| (Intersction)             |
|                      / |                               |
|                     /  |                               |
|                    /   |                               |
|                   /    |                               |
|                  /     |                               |
|                 /      |                               |
|                /       |                               |
|    (Does   /         |                              |
|      not              |                              |
|      reach)          |                              |
|                         |                              |
|   (Intersection     |                              |
---- with field)
(Hopefully you get the idea) ;)


The inaccuracy causes it to wobble.
(How do you insert an image? I trying to show you an image but when I insert it and try to preview the reply, the location of my image adds "http://" to the front.)

EgonOlsen

I don't see why the calculations in the car example should change the tires' distance from the center ??? It just calculates the tilt angles for the car and rotate it accordingly. And the tires rotate with the car's body because they are child object's of the car. How should that change the car's width?

About the images: You've to upload them somewhere or you can upload them to this server if they don't exceed 64kb by using the "additional options" button on the "Post reply"-page.

brainmaster

The rotation doesn't change the tire distances (sorry if i wrote that). But when calculating the car's angle,
{Imagine a right triange the horizontal leg is A, the vertical leg is B , and the hyp. is C}
A is set to 16 and B is set to the current difference in height. Since A doesn't represent the width/length of the car the angle desired is not the correct one. The tire of the car will end in a spot short of where the ray intersected the ground. The tire locations might then be on a different heights compare to the predicted ones related to the ground. I would like to find a rotation that will stick at least three of the four tires on the field  (My current method does not work). If this is too difficult I will try to smooth the current method.

I sorry if I am too confusing. :) I am still working on writing my thoughts in an understandable way.

EgonOlsen

Ok, the angle that the car example creates is averaged and doesn't guarantee a defined number of wheels to touch the ground. I've never cared about it, because it thought (and still think) that the results are "good enough(tm)". However, i think i understand somehow, where the jittering in your approach comes from but i'm not sure how to fix it. Maybe a kind of threshold would help, so that only little changes in the angle/position will be ignored...i'm not sure...could be a totally stupid idea too...

brainmaster

Thanks. I know i was asking a little too much, but i don't want to offend your programming style. I found a method that i'm about to implemment. It basically makes the terrain predictable and set the locations of the tires in the calculated spots. Yay, its not exact. I don't think any method will be exact. But it will be consistant. Nice talking to ya.

EgonOlsen

Quote from: brainmaster on April 27, 2007, 02:55:38 AM
...but i don't want to offend your programming style.
You never did. The car example is just a simple example. I would never claim that it's perfect or something... ;)