Improving collision between dynamic and kinematic entities

Discuss any questions about BEPUphysics or problems encountered.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

So, new question. I want to be able to specify any Vector3 as a rotation axis and any angle as a rotation angle, how would I set the basises from just that info? Can I? If I can't, what more information would I need?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

With revolute motors and limits, the entity A's basis's primary axis is the rotation axis. The X axis of the basis defines the direction of 0 angle. For the motor, the Y axis completes the basis- just set it to Vector3.Cross(primaryAxis, xAxis) for now. It's redundant information for the motor and the basis is being made 2D in the next version to avoid that.

The test axis for the revolute motor and limit are attached to entity B, so you'll need to pick a direction to attach to it that achieves the desired rotation for a given angle. This just depends on the configuration of the connected objects and what you want. A starting point is to set the test axis to the same as the xAxis you picked for the basis; that way, the initial configuration is aligned.

To get a feel for this, I recommend taking a known functional revolute motor configuration and then changing individual parts of the configuration and observing the results incrementally.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

The main problem I'm having is picking a proper xAxis for the given rotationAxis. If I was, say, to take the entity's orientation, rotate it around the rotation axis by the given angle, and then convert that to a vector, would that work? If so, how would I convert a quaternion to a vector (here is a picture to illustrate what I'm thinking of)?
Image
Unfortunately, transparency seems to have been untranparented. The vector pointing mostly up should be somewhat transparent.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Think simpler :)

The x axis must be perpendicular to the rotation axis. That's the only requirement. Which perpendicular axis you pick is completely arbitrary and up to you.

Consider the rotation axis to be a plane normal (the surface of which is shown by the box below). Consider the x axis to be an axis on that plane which defines what 0 angle is.

The test axis (attached to entity b) is projected onto that plane defined by the rotation axis (attached to entity a) and measured against the x axis (attached to entity a) to determine what the relative angle is.
revolute.jpg
revolute.jpg (17.66 KiB) Viewed 8372 times
There is no magical series of transforms that always produces a 'correct' configuration, because the 'correct' configuration is defined entirely and arbitrarily on how you want it to end up. I can't tell you exactly which basis or test axis to pick, because it depends on how you want to interpret and use it.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Yeah... I still don't get it. I think I got something that works, but... it's picky. Even after all this work, though, machines crush boxes. Worse than before, in fact. A box just landing on the machine starts clipping through it (at least for the rotation machine I've been working on). Also, I start rollers out with a RevoluteJoint connected to the world entity, and if it happens to be attached to a machine each of the four components' ConnectionA's are set to the parent, and the BallSocketJoint's LocalOffsetA is set to connectionA.Position - roller.Entity.Position, but it's missing the offset from the center of the parent joint. Here's the setup I have:

Code: Select all

baseJoint = new RevoluteJoint(null, baseEntity, center, rotationAxis);
baseJoint.Motor.IsActive = true;
baseJoint.Motor.Settings.Mode = BEPUphysics.Constraints.TwoEntity.Motors.MotorMode.Servomechanism;
baseJoint.Motor.Settings.Servo.Goal = 0;
baseJoint.Motor.Settings.Servo.SpringSettings.StiffnessConstant = 0;
baseJoint.Motor.Settings.Servo.SpringSettings.DampingConstant /= 10;
baseJoint.Motor.Settings.Servo.BaseCorrectiveSpeed = angle / rotateTime;
baseJoint.Motor.Basis.SetWorldAxes(rotationAxis, zeroAxis, Vector3.Cross(rotationAxis, zeroAxis)); // zeroAxis is the unit vector representing the direction from the center of the machine towards the edge of it.

// roller's SetParent (called by a rotation machine)
public void SetParent(Entity e, Vector3 anchor)
        {
            // motor is a RevoluteJoint, Ent is the roller's entity
            motor.Motor.ConnectionA = motor.Limit.ConnectionA = motor.AngularJoint.ConnectionA = motor.BallSocketJoint.ConnectionA = e;
            motor.BallSocketJoint.LocalOffsetA = e.Position - Ent.Position;
        }
Is the limit causing the crushing, mayhaps? (Nope, isn't. Removed it anyway.) I don't really need it, because I directly set the goal from the code. Machines' and rollers' masses are ten, boxes are five. In the version I made in the RobotArmDemo, balls I throw at it don't seem to have a problem... What ARE the masses of those balls? 1? Also, I tried changing the stiffness to stiffness / 10, but that was just... humorous. And it didn't help. Not sure what the issue is here...
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Even after all this work, though, machines crush boxes. Worse than before, in fact. A box just landing on the machine starts clipping through it (at least for the rotation machine I've been working on).
[...]
In the version I made in the RobotArmDemo, balls I throw at it don't seem to have a problem... What ARE the masses of those balls? 1? Also, I tried changing the stiffness to stiffness / 10, but that was just... humorous. And it didn't help. Not sure what the issue is here...
There's a strong implication of shenanigans here. Those balls have a mass of 20. The level of instability you describe is not expected behavior for a properly configured contraption.

If two identical joint configurations produce different results based on which project they're in, there's something else in the simulation configuration that's not the same.

If you reproduce the behavior in an isolated BEPUphysicsDemo such that I can debug the complete problematic configuration, I can probably offer better advice.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Well, that's kind of awkward. The problem was I was using MobileMeshSolidity.Solid where the model apparently was not solid (although by all rights appears to be). I think I should be good from here... I might have another problem with translate machines later, but isn't there something like a RailJoint or something like that? That could be useful.
Last edited by snoozbuster on Tue Apr 17, 2012 7:27 pm, edited 2 times in total.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

isn't there something like a RailJoint or something like that? That could be useful.
Yup, the PrismaticJoint. Or the LineSliderJoint. Or another combination :)

Pictures can be found in the documentation.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Alright. I'll check those out. I found another problem, though. Most of my machines rotate 180 degrees, and my previous approach to limits and bases isn't working. I often crash in space.Update() with a "function does not accept NaN-values" (probably in BoxShape.GetExtremePointWithoutMargin, in one of the Math.Sign calls). Got any more ideas? This xAxis thing hurts my brain... Is it a vector pointing to the direction I want to end up? The direction I start at? The direction I want 90 degrees to be at? The direction entityB initially points?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

Most of my machines rotate 180 degrees, and my previous approach to limits and bases isn't working. I often crash in space.Update() with a "function does not accept NaN-values"
Crashing should only happen if the joint is configured in a particularly invalid way, but most of those ways should be explicitly protected by an up-front exception telling you the configuration is unusable. If you can reproduce the crash in an isolated demo, I could take a look to see if it's an unprotected corner case.
This xAxis thing hurts my brain... Is it a vector pointing to the direction I want to end up? The direction I start at? The direction I want 90 degrees to be at? The direction entityB initially points?
Take a piece of paper. The surface normal of the paper (pointing out of it) is the rotation axis.

Draw a line in the middle, pointing whatever direction you want. That line is the x axis of the basis which defines which angle we want to call 0. You can use this to measure other lines. If a line is away from that line in one angular direction, the angle increases. If you move the other direction, the angle decreases. So another line could be 45 degrees off, or -45 degrees off; the measurement process (implemented with atan2) will tell you.

The piece of paper represents the basis attached to entity A.

Grab another thin straight object, like a pencil, and orient it on the paper. That pencil is the test axis attached to entity B. (Note the distinction here; the pencil-test-axis is capable of independent motion from the paper-basis.)

If the pencil is pointing the same direction as the line on your paper, the measured angle is 0. If it's 45 degrees off, the measured angle is 45 degrees. If it's -45 degrees off, the measured angle is -45 degrees.

Now, imagine that this piece of paper is attached to a freely moving rigid body. The paper-basis can be plastered onto the rigid body in any way desired; it doesn't have to line up with the body's local axes or anything like that. When you rotate the rigid body, the paper moves with it perfectly. Imagine a second object with the pencil attached. Once again, the pencil can be attached to the rigid body in any arbitrary orientation desired. Once attached, it follows the the rigid body's orientation perfectly.

Now, as entity A with the paper-basis attached and entity B with the pencil-test-axis attached tumble through space, it may look a bit trickier to compute the angle. However, you can still do the angle comparison even though the basis and test axis aren't right next to each other because translation is meaningless to an angular joint! It's still just a matter of looking at the relative angle between the basis x axis (the line on the paper) and the test axis (the pencil).

You might notice things get weird if the pencil isn't lined up with the surface of the paper. The RevoluteAngularJoint fights to keep the objects aligned, but it's possible for the RevoluteAngularJoint to become violated- but don't worry! You can still look straight down at the paper along the rotation axis and see the relative angle. Remember, translation is meaningless to angular joints, so you can translate the objects however you'd like to make it more convenient to look at and measure. That is projecting the test axis onto the basis plane (technically, it is an orthographic projection and doesn't have the distortion associated with looking at it with your eyeballs, but it's close enough :)).

(Note that while the above measurement process applies to RevoluteMotors and RevoluteLimits, not all constraints measure angle the same way for functional reasons. SwingLimits, for example, have no plane to project on, and angles range from 0 to pi rather than the revolute -pi to pi.)
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

So, the short version is if you set the test axis and the xAxis to the direction you can think of the machine as "pointing," that's 0. Right? Then, if you increase the servo's goal to pi or pi/2, it should work... right? Or should you set the testAxis to the xAxis rotated by angle around rotationAxis?
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

if you set the test axis and the xAxis to the direction you can think of the machine as "pointing," that's 0. Right?
The x axis does define what 0 is. If that is the direction the machine is "pointing," you can think of it that way. But that isn't true in all possible configurations (except for strange definitions of "pointing" :)).
Then, if you increase the servo's goal to pi or pi/2, it should work... right?
Setting the servo goal to pi/2 will make the entities move such that the test axis is pi/2 radians away from the x axis.
Or should you set the testAxis to the xAxis rotated by angle around rotationAxis?
Only if that is what you want to do :) There is a valid configuration in which that would be done. But that is not necessary for all possible configurations.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Alright. I think I got it. Something's slightly awry, though... I have the xAxis pointing the direction I want to be zero, and I have the rotation axis, and MathHelper.Pi... But an angle of pi doesn't do anything but make the machine wiggle a little. MathHelper.ToRadians(179) works fine, but it's a little more cumbersome to write. I'm thinking it's related to the xAxis and the projection being the same vector, just pointing opposite directions? You might wanna check that out, I think you can reproduce it in the RobotArmDemo by just making a simple RevoluteJoint and setting the xAxis and testAxis to some direction, then picking a goal of MathHelper.Pi. I know it works (or rather, doesn't work) with a rotation axis of UnitY and a xAxis of UnitX.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Improving collision between dynamic and kinematic entiti

Post by Norbo »

A quick reproduction attempt in the development version failed to show the problem. Are you using v1.1.0 still? If so, is the basis properly formed? The third axis must be the cross product of the first two, in order. In the development version the third parameter is simply gone.

If the basis is not properly formed, it can cause the system to think that it always has to go 'backwards' to reach the target, leading to oscillation.

If this is in the development version or with a properly formed basis, could you write up a configuration in the demos which reproduces it for me?
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Improving collision between dynamic and kinematic entiti

Post by snoozbuster »

Norbo wrote:A quick reproduction attempt in the development version failed to show the problem. Are you using v1.1.0 still? If so, is the basis properly formed? The third axis must be the cross product of the first two, in order. In the development version the third parameter is simply gone.

If the basis is not properly formed, it can cause the system to think that it always has to go 'backwards' to reach the target, leading to oscillation.

If this is in the development version or with a properly formed basis, could you write up a configuration in the demos which reproduces it for me?
It's more or less version 1.1.0, with a couple edits. The basis is correctly formed to my knowledge. I'll update and let you know if it's fixed.
Post Reply