Using user input to drive a ballSocket + angular motor

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
holophone3d
Posts: 13
Joined: Sun Aug 14, 2011 7:40 pm

Using user input to drive a ballSocket + angular motor

Post by holophone3d »

I'm trying to create a motorized armiture that is closely synchronized with user input. I have something that kind of works (Ball socket + angular motor), but it's crazy springy, just bouncing everywhere. I tried to play with the damping settings, but that just seemed to make everything really slow and springy. Ideally, this would work just like you'd expect a real robot arm to work if a user was controlling it via a joystick - almost real time and very precise. The user input is the following range ( X= -1,1 Y=-1,1 Z=1,0) and is updated approximately 30 times per second. I feel like I'm really close... perhaps just a setting or two away from the behavior I want.

Here is the code (a little out of context, but should still be representative) I wrote thus far, any assistance is greatly appreciated!

Code: Select all

           //Setup code
            Entity fixedPivotLocation = new Box(Vector3.Zero, .1f, .1f, .1f);
            fixedPivotLocation.IsAffectedByGravity = false;
            fixedPivotLocation.IsAlwaysActive = true;
            game.PhysicsManager.Space.Add(fixedPivotLocation);

            entity= new Box(new Vector3(0, 0, 1), .1f, .1f, .1f, 1);
            entity.IsAffectedByGravity = false;
            entity.IsAlwaysActive = true;
            //entity.CollisionInformation.CollisionRules.Personal = CollisionRule.NoBroadPhase; //prevent entityfrom interacting with anything
            game.PhysicsManager.Space.Add(entity);

            BallSocketJoint joint = new BallSocketJoint(fixedPivotLocation, entity, fixedPivotLocation.Position);
            joint.IsActive = true;
            game.PhysicsManager.Space.Add(joint);

            motor = new AngularMotor(fixedPivotLocation, entity);
            motor.Settings.Mode = MotorMode.Servomechanism;
            motor.IsActive = true;
            motor.Settings.Servo.Goal = Quaternion.CreateFromYawPitchRoll(0, 0, 1);
            motor.Settings.MaximumForce = 100;
            game.PhysicsManager.Space.Add(motor);


      //*This code is called on each frame update 
       GoalPosition = UserInput;
 motor.Settings.Servo.Goal = Quaternion.CreateFromYawPitchRoll(GoalPosition.X * (float)MathHelper.PiOver2, GoalPosition.Y * (float)MathHelper.PiOver2, GoalPosition.Z * (float)MathHelper.PiOver2);

Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Using user input to drive a ballSocket + angular motor

Post by Norbo »

Interesting, you may have found a bug with the ball socket joint at low inertia! I'm looking into it. Was this in v0.16.2, or the development version?
holophone3d
Posts: 13
Joined: Sun Aug 14, 2011 7:40 pm

Re: Using user input to drive a ballSocket + angular motor

Post by holophone3d »

Actually looks like I was using the older 16.0. I just updated to 16.2 and it acutally looks a bit better, but still pretty oscillating (and it appears to be have increasing energy as well). Thanks a bunch for looking into this. I'm really glad to hear that it sounds like my scenario can work. :)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Using user input to drive a ballSocket + angular motor

Post by Norbo »

Tests so far are pointing away from a bug at the moment. The problem appears to be related to the difficulty the solver is having with the relatively long lever arm compared to the tiny inertia of the box combined with very strong constraints.

Here's a few approaches to improving the behavior:
1) Placing the anchor closer to the kinematic box should result in more stability.

2) Additionally, increasing the inertia tensor of the dynamic box will help. You can do this explicitly by setting the LocalInertiaTensor(Inverse) property, or you can just increase the dimensions of the shape. Specifically, increasing the length of the box to 1 pretty much eliminates the problem.

3) Weaken the involved constraints so they don't apply gigantic forces relative to the involved entity's inertia.

Here's a test showing spring settings which result in a pretty nice simulation:

Code: Select all

            //Setup code
            Entity fixedPivotLocation = new Box(Vector3.Zero, .1f, .1f, .1f);
            Space.Add(fixedPivotLocation);

            var entity = new Box(new Vector3(0, 0, 1), .1f, .1f, .1f, 1);
            entity.IsAffectedByGravity = false;
            Space.Add(entity);

            BallSocketJoint joint = new BallSocketJoint(fixedPivotLocation, entity, fixedPivotLocation.Position);
            joint.SpringSettings.StiffnessConstant = 1000;
            joint.SpringSettings.DampingConstant = 25;

            Space.Add(joint);

            motor = new AngularMotor(fixedPivotLocation, entity);
            motor.Settings.Mode = MotorMode.Servomechanism;
            motor.Settings.Servo.Goal = Quaternion.CreateFromYawPitchRoll(0, 0, 0);
            motor.Settings.Servo.SpringSettings.StiffnessConstant = 15;
            motor.Settings.Servo.SpringSettings.DampingConstant = 3;
            Space.Add(motor);
If your character is expected to encounter significant opposing forces, it would be wise to make the configuration more stable with all three options.

I'll do some more tests to rule out any hiding bug, but at this point it, the above looks to be it.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Using user input to drive a ballSocket + angular motor

Post by Norbo »

By the way, you may have already seen it, but the BEPUphysicsDemos project includes a RobotArmDemo showing a fairly complicated articulated arm controlled with user input. It may contain some helpful information you can use to create your own articulated structures.
holophone3d
Posts: 13
Joined: Sun Aug 14, 2011 7:40 pm

Re: Using user input to drive a ballSocket + angular motor

Post by holophone3d »

Thanks for the investigation and quick reply (on a Sunday no less...) very much appreciated. I played around with the box size, mass, stiffness and damping constants a bit more and I've gotten the simulation to look just how I want - overall it's working great now. I also spent some time (when writing this code initiailly) looking at the Robot Arm demo, it was very helpful and very cool.

Are there any docs on the usage of the stiffness and damping settings or are those just magic numbers that you need to know the appropriate ranges to tweak (plus trial and error) to get the desired behavior. Thanks in advance!
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Using user input to drive a ballSocket + angular motor

Post by Norbo »

The stiffness and damping constants correspond to real life stiffness and damping spring constants. Stiffness applies forces based on the position error while damping seeks to eliminate relative velocity. The default values are high, designed for rigidity (90000 damping, 600000 stiffness).

Just like real life springs, the spring has to be stronger to have the same effect on heavier objects and weaker for lighter objects.

The "heaviness" of an object depends on the configuration and the amount of mass felt by the constraint. In the above example, due to the long lever arm, the inertia tensor was a big factor in determining the constraint's effective mass. Because the inertia was so tiny and the springs were so strong, the solver had a hard time.

So basically, you can make an educated guess about the stiffness and damping required, but usually there will be some extra tuning required to get it just right. The easier the initial configuration is, the less fine tuning will be required.

There's also the option of using the 'advanced' settings. You can enable these by setting the joint's SpringSettings.Advanced.UseAdvancedSettings to true. The associated ErrorReductionFactor and Softness can then be used as an alternate method to tune the constraint. When operating normally, these two factors are derived from the damping and stiffness constants and the time step duration. However, it can sometimes be easier to modify them directly.

ErrorReductionFactor introduces a bias to the constraint's velocity goal based on the position error. It tries to modify the velocity such that ErrorReductionFactor * error is fixed each frame. Softness (also known as constraint force mixing) allows the constraint to be violated a bit- in other words, unsurprisingly, making the constraint softer.

Be careful when using the advanced settings. Under normal circumstances, stiffness and damping are combined with the time step duration to compute them; by setting the ErrorReductionFactor and Softness directly, behavior is no longer independent of time step duration. That is, if you change Space.TimeStepSettings.TimeStepDuration while using advanced settings, you have to change your settings.
holophone3d
Posts: 13
Joined: Sun Aug 14, 2011 7:40 pm

Re: Using user input to drive a ballSocket + angular motor

Post by holophone3d »

Wow. Fantastic data! That's exactly what I needed. I"m sure if you compiled all your responses into a wiki, you'd have some incredibly detailed documentation. :D
Post Reply