Page 1 of 1

Vehicle non 0,-1,0 suspension

Posted: Thu Jul 18, 2013 11:28 am
by stino
Hello,

If i create a vehicle with suspension that looks straight down, the correct wheel position is calculated in the vehicle's RaycastWheelShape's UpdateWorldTransform().

But if i take an angled suspension, like {X:-0,7808688 Y:-0,6246951 Z:0} and {X:0,7808688 Y:-0,6246951 Z:0} (the wheels come closer to the body along the Y and X axis when the suspension is compressed).

Then the wheel is sunk into the support where it rests upon. From looking at the source code, i see you calculate the wheel position from the suspension length minus the wheel's radius, but this is incorrect as the wheel isn't angled like the suspension's detector is.

I can "fix" this to be graphically better looking, but for physical "correctness", i think some more editing is required, as the support point isn't nowhere near the wheel's location at shallow suspension angles.

EDIT: seems like there's more wrong, the rotation axis is perpendicular to the suspension, so the wheel rotates rotates around the wrong axis, like the axle broke.

Re: Vehicle non 0,-1,0 suspension

Posted: Thu Jul 18, 2013 6:33 pm
by Norbo
The RayCastWheelShape assumes the the 'up' direction of a wheel is parallel to the suspension direction, and assumes that the rotation is perpendicular to the up and forward directions.

The CylinderCastWheelShape does too, but you have control over the orientation of the shape cast. That would find a support point in the desired place. The graphical rotation would still assume an undesired direction, but that is purely a graphical effect. Making a customized version of the CylinderCastWheelShape would let you define the behavior however you wanted.

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Jul 19, 2013 11:59 am
by stino
So to use the RayCastWheelShape with an non 0,-1,0 axis would require to pre-rotate the wheel's graphic to be able to make it "roll" correctly?

I would have made it's default behavior to rotate the wheel shape to fit perpendicular on the suspension axis and forward axis, so that when the suspension is modified, the wheel's turns with it?

But i guess i'll implement my own RayCastWheelShape for this and override UpdateWorldTransform(). I can live with the graphical offset between the wheel and the point on the floor where the ray hits the support for now.

Also, a rest length > 1 makes the wheels bounce, because they extend through the support one frame, and stand correctly on the support the other frame.
Frame A
Frame B

Smaller lengths do not have this problem and the error doesn't seem to be proportional to the length itself.

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Jul 19, 2013 6:31 pm
by Norbo
So to use the RayCastWheelShape with an non 0,-1,0 axis would require to pre-rotate the wheel's graphic to be able to make it "roll" correctly?
Correct; the RayCastWheelShape makes no assumptions about the orientation of the graphical model. It assumes it is pretransformed appropriately.
I can live with the graphical offset between the wheel and the point on the floor where the ray hits the support for now.
The CylinderCastWheelShape would address this with almost no effort; it's probably worth switching.

Also, I just made a tiny change to the CylinderCastWheelShape such that the axis of rotation is based upon the LocalWheelOrientation, which solves the other issue.
Also, a rest length > 1 makes the wheels bounce, because they extend through the support one frame, and stand correctly on the support the other frame.
I do not observe this behavior, could you replicate it in the latest demos for me to look at?

My first guess would be that the support surface is gigantic, which interferes with the iterative intersection routines. I would expect this to be more visible with the CylinderCastWheelShape, because the RayCastWheelShape has special cases with boxes, triangles, and other simple primitives. If this is the problem, use a smaller support. For example, a flat sparse Terrain with each triangle being around 10-20 units across would be a good choice.

Re: Vehicle non 0,-1,0 suspension

Posted: Sun Jul 21, 2013 10:42 pm
by stino
The support surface is rather "big", it's a box entity of w100 h10 l100, and the wheel is a RayCastWheel.

I'll try with smaller supports and within the demo tomorrow.

Re: Vehicle non 0,-1,0 suspension

Posted: Tue Jul 23, 2013 12:29 pm
by stino
Oh, I realized i wasn't using the latest version of bepu, since the SlimDX fork hasn't been updated since june last year.

What do i need to do to get the latest version to use the slimdx math like the slimdx fork used to do?

EDIT: i've found the easiest way to get the dependency free fork to work with slimdx is to add implicit cast operators like this:

Code: Select all

        public static implicit operator SlimDX.Vector4(Vector4 vector)
        {
            return new SlimDX.Vector4(vector.X, vector.Y, vector.Z, vector.W);
        }
        public static implicit operator Vector4(SlimDX.Vector4 vector)
        {
            return new Vector4(vector.X, vector.Y, vector.Z, vector.W);
        }
I suppose it's a little slower then converting the entire library to slimdx, but it's a much faster conversion!

EDIT2:

With the new bepu source, the vehicle still bounces violently when the rest length is longer then 1, but its more stable.
I also noticed that the vehicle with the same settings remains more stable while cornering at high speeds.

I'll try to modify the demo and see if i can make it happen there.

Re: Vehicle non 0,-1,0 suspension

Posted: Thu Aug 01, 2013 9:58 am
by stino
I can't get the behavior replicated in the demos, but i did notice different behaviors in my editor/game.

In the vehicle editor i have a box entity of 100x50x100 and my vehicle with settings very similar to the demo vehicle.

And the vehicle "behaves" correctly if the suspension rest isn't to long. But, when i load the same vehicle in the game, on a different surface (triangle mesh) i get a different behavior.

The first terrain i tested it on was a full track (road + coarse terrain) which was scaled to 2.5% of the original size. Resulting in average road polygons of 10x10 units (the original triangles would be 393x393).

The scaling was done with an AffineTransform.

And this bounces horrible with the same vehicle settings as on the 100x50x100 box.

So, i tried something different, made some simple track segments (straight, corner, s-bend), .. and puzzled those together in the editor. Again at scale 2.5%, and now it behaves much better.

So i wonder, it'll probably be more efficient to do the scaling on import directly on the vertices instead of in the transformation matrix of the node.

I'm also going to try to get my meshes into the bepu demos with the same transformations.

Re: Vehicle non 0,-1,0 suspension

Posted: Thu Aug 01, 2013 6:11 pm
by Norbo
So i wonder, it'll probably be more efficient to do the scaling on import directly on the vertices instead of in the transformation matrix of the node.
For reference, at least as far as the StaticMeshes are concerned, an AffineTransform is always applied. Baking it will just result in an identity transform being used.

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Aug 02, 2013 3:50 pm
by stino
Yes, but baking it in results in smaller triangles.

And the behavior is improved, the kart doesn't bounce around the track now, but it still drives way different then in the editor.

If i accelerate in the editor, the kart has enough power to do a wheelie, while in the "game" it barely speeds up.

The game is based on a WinForms application while the editor is WPF based, but as far as the logic is concerned, both have ticks 60 times per second.

What i do with regards to bepu:
Startup:

Code: Select all

        public void Init()
        {
            this.space = new Space();
            this.space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);
             
            if (Environment.ProcessorCount > 1)
            {
                for (int i = 0; i < Environment.ProcessorCount; i++)
                {
                    this.space.ThreadManager.AddThread();
                }
            }
        }
Add Vehicle

Code: Select all

        public void AddVehicle(VehicleDefinition definition)
        { 
            Vehicle vehicle = getVehicleFromDefinition(definition); // creates a vehicle similar to the demo vehicle.
            space.Add(vehicle);
         }
Update:

Code: Select all

        public void Update()
        {
            dt = GetTickTime(); // calculates the time elapsed since last call to GetTickTime();
            space.Update(dt);
         }
i suppose i'm doing it right this way, but that doesn't explain the different behavior between the two programs.

also, if dt gets bigger, because of a breakpoint etc, the whole simulation runs a lot faster for a bit, depending on the duration of the break? Am i getting the whole Update() vs Update(dt) thing wrong perhaps?

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Aug 02, 2013 6:18 pm
by Norbo
I don't see anything in those snippets which would explain a substantial difference in behavior; I would recommend isolating chunks of the simulation/configuration and testing them individually to narrow down the source of the difference.
also, if dt gets bigger, because of a breakpoint etc, the whole simulation runs a lot faster for a bit, depending on the duration of the break? Am i getting the whole Update() vs Update(dt) thing wrong perhaps?
Space.Update(dt) will take as many timesteps as necessary to simulate the accumulated time, up to a maximum per frame (Space.TimeStepSettings.MaximumTimeStepsPerFrame, defaults to 3). So, if there's a hiccup (usually something small, but a breakpoint would do it), the simulation will rush to catch up.

If you want to limit the accumulated time, you can either clamp the dt passed into the update method or explicitly clamp the Space.TimeStepSettings.AccumulatedTime. Clamping dt would prevent any one frame from contributing too much to the accumulated time, while clamping the AccumulatedTime directly would prevent any sequence of slow frames from going beyond a certain threshold.

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Aug 02, 2013 7:48 pm
by stino
Isolating parts of the simulation? There isn't much more yet then this Tick function in both applications, one is fed by the windows message pump, the other by WPF's composition target.

These snippets are all that is related to bepu. The vehicle itself is loaded from a file in both situations:

Code: Select all

            var  wheels = new Wheel[wheelCount];
            for (int i = 0; i < wheelCount; i++)
            {
                var localWheelRotation = Quaternion.RotationAxis(new Vector3(0, 0, 1), MathHelper.PIOver2); // the rotation that is applied to "roll" the wheel, correct?
                var graphicWheelTransform = Matrix.RotationZ(wheelDefinition.SuspensionAttachment.X > 0 ? MathHelper.PIOver2 : -MathHelper.PIOver2); // same mesh used for left & right wheels, so rotate 180°

                var shape = new CylinderCastWheelShape(wheelDefinition.Radius, wheelDefinition.Width, localWheelRotation, graphicWheelTransform, true);
                var suspension = new WheelSuspension(wheelDefinition.SuspensionStiffness, wheelDefinition.SuspensionDamping, wheelDefinition.SuspensionAxis, wheelDefinition.SuspensionRest, wheelDefinition.SuspensionAttachment); // = (2000, 100, (0,-1,0), 0.5, (x,y,z))

                var motor = new WheelDrivingMotor(wheelDefinition.GripFriction, wheelDefinition.MaxForwardForce, wheelDefinition.MaxBackwardForce); // (2.5, 3000, 1000)
                var rollingFriction = new WheelBrake(wheelDefinition.DynamicBrakingFriction, wheelDefinition.StaticBrakingFriction, wheelDefinition.RollingFriction); // = (1, 2, 0.02)
                var slidingFriction = new WheelSlidingFriction(wheelDefinition.DynamicSlideFriction, wheelDefinition.StaticSlideFriction); // = (2,3)
                var physicsWheel = new Wheel(shape, suspension, motor, rollingFriction, slidingFriction);
                wheels[i] = physicsWheel;
            }

            var bodyShape = new Box(Vector3.Zero, size.X, size.Y, size.Z, bodyDefinition.Mass); //((0,0,0), 3, 1, 5.5, 61)

            bodyShape.CollisionInformation.LocalPosition = -bodyDefinition.CenterOfGravity;

            this.vehicle = new Vehicle(bodyShape, wheels);
The actual forward speed from the vehicle: Vector3.Dot(LinearVelocity, WorldForward) is identical in both situations,
From the motor i get a maximal total impulse of 10.29 in the editor. (with actual speed at -0.29 and targetSpeed at 1.34, so going from backward to forward motion) While in the game it never goes above 7.3. This could explain the wheelie in the editor, but this difference looks rather small.

If i turn left/right and set the targetspeed at -10 in the editor, i can complete one circle before the centrifugal force flips the vehicle over. In the game it stays on it wheels and completes many more circles without lifting a wheel of the ground. The game vehicle even manages to register a speed of -11 while doing this while the editor vehicle goes wheels up at -7 units/s on the world forward axis. Where is this difference coming from :'(




I also don't quite understand how the wheel motor's and brakes work, if I reduce the target speed of the wheels, the vehicle happily continues driving on. So i assume it only applies force to the "wheels" when TargetSpeed < ActualSpeed? So i also have to brake when i want to slow down.

So when i brake, i notice the vehicle going into a nosedive, lifting the rear wheels of the ground, and they are still spinning freely.
So the brake force is applied between the body and the support? Which is perfectly fine of course, as long as the wheels are touching a support.

So i investigated into this, and i noticed, when i put the vehicle on it's roof and accelerate, the wheels start spinning, as is to be expected. But as soon as i return the TargetSpeed back to 0, the wheels slow down and stop. I'd assume this is due to some kind of friction, but none of the friction values i know of have influence on this (Setting Brake friction, Grip Friction or Slide Friction to 0 doesn't help).

But then i apply the brakes (IsBraking = true), and the wheels slow down at the same rate, as would be expected from the observation before, that, wheels are not affected by brakes.

I have worked with JigLibX before, and modified the most vehicle code there to simulate a motor with gearbox, but Bepu seems to be a lot more complicated to achieve this.

In jiglib, a wheel is for all purposes, a stationary object with mass of it's own and no collision response, when torque is applied to it, the wheel spins up/slows down, the difference in speed between the wheel surface and the world results in a force, that is applied to the world and the vehicle's body, and it's torque is also subtracted from the, to the wheel applied torque.

This gave me feedback on the "axle" that i used to calculate the forces on the engine.
But from what i find in bepu, the Driving Motors are only "thrusters", applying action force to the body and a reaction force to the world?

I guess i'll have to find me some time and create a vehicle from scratch with best of both worlds after i figured out why it behaves differently in these two scenarios.

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Aug 02, 2013 9:15 pm
by Norbo
Isolating parts of the simulation? There isn't much more yet then this Tick function in both applications, one is fed by the windows message pump, the other by WPF's composition target.
For example, by trying out the same simulation configuration in the BEPUphysicsDemos, you would have a reference for what the expected behavior is (well, probably- if you notice something strange going on in the BEPUphysicsDemos, I can take a look directly). Having a reference behavior to compare against lets you prune down possible causes- perhaps one of the programs matches the reference, while the other is clearly behaving anomalously.
I also don't quite understand how the wheel motor's and brakes work, if I reduce the target speed of the wheels, the vehicle happily continues driving on. So i assume it only applies force to the "wheels" when TargetSpeed < ActualSpeed? So i also have to brake when i want to slow down.
Correct; the motor only does work if the actual speed is less than the target speed. If you want to slow down, either brake or accelerate in the opposite direction.
So when i brake, i notice the vehicle going into a nosedive, lifting the rear wheels of the ground, and they are still spinning freely.
So the brake force is applied between the body and the support? Which is perfectly fine of course, as long as the wheels are touching a support.

So i investigated into this, and i noticed, when i put the vehicle on it's roof and accelerate, the wheels start spinning, as is to be expected. But as soon as i return the TargetSpeed back to 0, the wheels slow down and stop. I'd assume this is due to some kind of friction, but none of the friction values i know of have influence on this (Setting Brake friction, Grip Friction or Slide Friction to 0 doesn't help).
The Vehicle class's wheels do not physically exist, they are just queries. The apparent rotation is strictly graphical. All constraint interaction takes place at the query's intersection with the environment.

Because the rotation is purely graphical, you can do whatever you want with it. The default behaviors are controlled by the WheelShape. It has properties like AirborneWheelAcceleration, AirborneWheelDeceleration, BrakeFreezeWheelDeceleration, and FreezeWheelsWhileBraking. Additionally, you could customize the behavior however you wanted by modifying the source of the wheel shape implementation; the graphical transform has no effect on the physics.
But from what i find in bepu, the Driving Motors are only "thrusters", applying action force to the body and a reaction force to the world?
Roughly, yes- they do work at the proper locations so the responses appear physically reasonable, but it's a very simple model. The wheels are basically a specialized form of contact point.

Re: Vehicle non 0,-1,0 suspension

Posted: Fri Aug 02, 2013 10:36 pm
by stino
Great, the demo behaves roughly the same as the game version :( I'm calling it a day, further investigation follows tomorrow (i hope).