Vehicle non 0,-1,0 suspension
Vehicle non 0,-1,0 suspension
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.
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
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.
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
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.
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
Correct; the RayCastWheelShape makes no assumptions about the orientation of the graphical model. It assumes it is pretransformed appropriately.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?
The CylinderCastWheelShape would address this with almost no effort; it's probably worth switching.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, 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.
I do not observe this behavior, could you replicate it in the latest demos for me to look at?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.
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
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.
I'll try with smaller supports and within the demo tomorrow.
Re: Vehicle non 0,-1,0 suspension
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:
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.
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);
}
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
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.
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
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.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.
Re: Vehicle non 0,-1,0 suspension
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:
Add Vehicle
Update:
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?
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();
}
}
}
Code: Select all
public void AddVehicle(VehicleDefinition definition)
{
Vehicle vehicle = getVehicleFromDefinition(definition); // creates a vehicle similar to the demo vehicle.
space.Add(vehicle);
}
Code: Select all
public void Update()
{
dt = GetTickTime(); // calculates the time elapsed since last call to GetTickTime();
space.Update(dt);
}
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
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.
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.
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.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?
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
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:
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.
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);
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
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.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.
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.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.
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.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).
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.
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.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?
Re: Vehicle non 0,-1,0 suspension
Great, the demo behaves roughly the same as the game version
I'm calling it a day, further investigation follows tomorrow (i hope).
