world scaling reprise: mass scales with geometry?

Post Reply
ratatouille
Posts: 21
Joined: Fri Oct 24, 2014 10:48 am

world scaling reprise: mass scales with geometry?

Post by ratatouille »

Hello all,

Some time ago, I implemented a simple damped pendulum simulation to check the physical accuracy of Bullet. The thread is here:

http://www.bulletphysics.org/Bullet/php ... =9&t=10184

After making the adjustments mentioned in the thread, accuracy was very good with MKS units and parameter values greater than 1 (e.g. 1 kg spheres of radius 1 m).

Now, I am trying to do the same for a very small, high-frequency pendulum (e.g. 1 gram spheres of radius 1 mm). Because of the known issues of Bullet with small objects, I am scaling the world by 1000, to get the size back to 1 in normalized units.

However, there is a lot of conflicting information on world scaling. The wiki page (http://www.bulletphysics.org/mediawiki- ... _The_World) apparently has an error where inertias should be scaled by X^2 instead of X (see http://bulletphysics.org/Bullet/phpBB3/ ... 526#p15516 and http://www.bulletphysics.org/Bullet/php ... =15#p23545). The wiki info also differs a lot from the scaling mentioned in this thread (http://bulletphysics.org/Bullet/phpBB3/ ... ale#p15506) which someone then commented 'works very nicely'. Also there is conflicting info on mass scaling: wiki says don't scale mass, but this post says scale mass by X^3.

So what is right? I hope it is not necessary to go into btGeneric6DofSpring2Constraint.cpp and add scaling factors there as well?

thanks!
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: world scaling reprise: mass scales with geometry?

Post by Basroil »

ratatouille wrote:Hello all,

Some time ago, I implemented a simple damped pendulum simulation to check the physical accuracy of Bullet. The thread is here:

http://www.bulletphysics.org/Bullet/php ... =9&t=10184

After making the adjustments mentioned in the thread, accuracy was very good with MKS units and parameter values greater than 1 (e.g. 1 kg spheres of radius 1 m).

Now, I am trying to do the same for a very small, high-frequency pendulum (e.g. 1 gram spheres of radius 1 mm). Because of the known issues of Bullet with small objects, I am scaling the world by 1000, to get the size back to 1 in normalized units.

However, there is a lot of conflicting information on world scaling. The wiki page (http://www.bulletphysics.org/mediawiki- ... _The_World) apparently has an error where inertias should be scaled by X^2 instead of X (see http://bulletphysics.org/Bullet/phpBB3/ ... 526#p15516 and http://www.bulletphysics.org/Bullet/php ... =15#p23545). The wiki info also differs a lot from the scaling mentioned in this thread (http://bulletphysics.org/Bullet/phpBB3/ ... ale#p15506) which someone then commented 'works very nicely'. Also there is conflicting info on mass scaling: wiki says don't scale mass, but this post says scale mass by X^3.

So what is right? I hope it is not necessary to go into btGeneric6DofSpring2Constraint.cpp and add scaling factors there as well?

thanks!
I think the problem is just simply not putting units in your math, which is getting you confused between base and derived unit scaling. Here's how scaling will work if scaling base length and mass by 1000:
simple conversions are represented as units in base units (1m-> m, 1kg->kg, 1s->s)
m=1000 mm
kg=1000 g
s->s
Volume is m^3, so in mm^3=(1000*m)^3 (1000000000 times larger number for same item).
Force is mass times acceleration, which means kg-m/s^2, so (1000g)(1000m)/s^2, so 100000 times for same force in new units.
Inertia is generally derived as some scaling of mass by swept area, so kg-m^2, (1000kg)*(1000m)^2 for same item.
Density is given as kg/m^3, so new density will be 100000 times smaller for the same item.
Force is kg-m/s^2, and impulse is kg-m/s, so both are 100000 times larger for same item.

The second link you used actually defines density scaling as 1 and linear scaling by some number, which results in mass getting scaled disproportionately to what you have described, and generally not suggested because it makes things scale in very ugly ways.

The good thing is that you do not need to modify 6dof spring class to make scaling work, and for a given mass and length you shouldn't need to change CFM/ERP values. HOWEVER, you should note that the class has a protection against fast oscillations that are above the nyquist frequency, so if your oscillations are quite fast you should increase your sampling rate (decrease timestep) until the oscillation is below the minimum allowable frequency of your simulation. For the default 60fps solving, the Ks to m (remember m and Ks are being scaled! Shouldn't be an issue though since Ks is derived from mass and any mass increase will equally increase Ks) ratio should be less than 225 (if 1 mass unit, Ks should be less than 225 Ks units), but if you move up to 300fps you can use a ratio of 5625 and 1000fps will let you have ratios up to 62 thousand.
ratatouille
Posts: 21
Joined: Fri Oct 24, 2014 10:48 am

Re: world scaling reprise: mass scales with geometry?

Post by ratatouille »

thanks for your detailed reply.

Unfortunately, the pendulum does not scale right with the given factors: it is much too sluggish.

Code: Select all

	// physical parameters
	// N.B. [N] = [kg·m/s^2]
	const float pendulum_length = 5E-3; // [m]
	const float mass = 1E-3f; // [kg]
	const float spring_constant = 75E-3; // [N·m/rad]
	const float damping_coeff = .5E-5f; // [kg·m^2/(s·rad)]
	const float radius = 1E-3;	// [m]
	const float initial_angle = 0.f; // [rad]
	const float initial_linear_velocity = 1.f; // [m/s]

	const float pendulum_length_scaled = pendulum_length * world_scale;
	const float mass_scaled = mass * mass_scale;
	const float spring_constant_scaled = spring_constant * mass_scale * world_scale * world_scale;
	const float damping_coeff_scaled = damping_coeff * mass_scale * world_scale * world_scale;
	const float radius_scaled = radius * world_scale;
	const float initial_linear_velocity_scaled = initial_linear_velocity * world_scale;
As you can see, whenever a [m] appears in the units I insert a factor of world_scale, and for every [kg] that appears there is a factor mass_scale.

But the behavior is only (approximately) correct if the output from calculateLocalInertia is scaled by a factor of 1/world_scale, instead of the world_scale^2 that would be expected (mass is already scaled in the function parameter to calculateLocalInertia).

I guess this kindof makes sense, as small objects should have very small inertia. But it does not make sense looking at the units.

Even in spite of this change, the match is not very good, much worse in fact than with the unscaled pendulum. Maybe there are scaling factors being put in the wrong place?
Basroil
Posts: 463
Joined: Fri Nov 30, 2012 4:50 am

Re: world scaling reprise: mass scales with geometry?

Post by Basroil »

ratatouille wrote:thanks for your detailed reply.

Unfortunately, the pendulum does not scale right with the given factors: it is much too sluggish.

Code: Select all

	// physical parameters
	// N.B. [N] = [kg·m/s^2]
	const float pendulum_length = 5E-3; // [m]
	const float mass = 1E-3f; // [kg]
	const float spring_constant = 75E-3; // [N·m/rad]
	const float damping_coeff = .5E-5f; // [kg·m^2/(s·rad)]
	const float radius = 1E-3;	// [m]
	const float initial_angle = 0.f; // [rad]
	const float initial_linear_velocity = 1.f; // [m/s]

	const float pendulum_length_scaled = pendulum_length * world_scale;
	const float mass_scaled = mass * mass_scale;
	const float spring_constant_scaled = spring_constant * mass_scale * world_scale * world_scale;
	const float damping_coeff_scaled = damping_coeff * mass_scale * world_scale * world_scale;
	const float radius_scaled = radius * world_scale;
	const float initial_linear_velocity_scaled = initial_linear_velocity * world_scale;
As you can see, whenever a [m] appears in the units I insert a factor of world_scale, and for every [kg] that appears there is a factor mass_scale.

But the behavior is only (approximately) correct if the output from calculateLocalInertia is scaled by a factor of 1/world_scale, instead of the world_scale^2 that would be expected (mass is already scaled in the function parameter to calculateLocalInertia).

I guess this kindof makes sense, as small objects should have very small inertia. But it does not make sense looking at the units.

Even in spite of this change, the match is not very good, much worse in fact than with the unscaled pendulum. Maybe there are scaling factors being put in the wrong place?
Have you tried using double precision units? What about smaller time-steps?

If your pendulum is affected by gravity and a spring, the angular rate might be far too large (see above post), especially considering that your natural frequency from gravity is ~2000 (while max with default settings is about 225)
Post Reply