Esempio n. 1
0
btVector3 Tire::getForce(
	btScalar normal_force,
	btScalar friction_coeff,
	btScalar inclination,
	btScalar ang_velocity,
	btScalar lon_velocity,
	btScalar lat_velocity)
{
	if (normal_force < 1E-3 || friction_coeff < 1E-3)
	{
		slide = slip = 0;
		ideal_slide = ideal_slip = 1;
		fx = fy = fz = mz = 0;
		vx = vy = 0;
		return btVector3(0, 0, 0);
	}

	// pacejka in kN
	normal_force = normal_force * 1E-3;

	// limit input
	btClamp(normal_force, btScalar(0), btScalar(max_load));
	btClamp(inclination, -max_camber, max_camber);

	// get ideal slip ratio
	btScalar sigma_hat(0);
	btScalar alpha_hat(0);
	getSigmaHatAlphaHat(normal_force, sigma_hat, alpha_hat);

	btScalar Fz = normal_force;
	btScalar gamma = inclination; // positive when tire top tilts to the right, viewed from rear
	btScalar denom = btMax(btFabs(lon_velocity), btScalar(1E-3));
	btScalar lon_slip_velocity = lon_velocity - ang_velocity;
	btScalar sigma = -lon_slip_velocity / denom; // longitudinal slip: negative in braking, positive in traction
	btScalar tan_alpha = lat_velocity / denom;
	btScalar alpha = -atan(tan_alpha) * 180.0 / M_PI; // sideslip angle: positive in a right turn(opposite to SAE tire coords)
	btScalar max_Fx(0), max_Fy(0), max_Mz(0);

	// combining method 1: beckman method for pre-combining longitudinal and lateral forces
	// seems to be a variant of Bakker 1987:
	// refined Kamm Circle for non-isotropic tire characteristics
	// and slip normalization to guarantee simultaneous sliding
	btScalar s = sigma / sigma_hat;
	btScalar a = alpha / alpha_hat;
	btScalar rho = btMax(btSqrt(s * s + a * a), btScalar(1E-4)); // normalized slip
	btScalar Fx = (s / rho) * PacejkaFx(rho * sigma_hat, Fz, friction_coeff, max_Fx);
	btScalar Fy = (a / rho) * PacejkaFy(rho * alpha_hat, Fz, gamma, friction_coeff, max_Fy);
	// Bakker (with unknown factor e(rho) to get the correct direction for large slip):
	// btScalar Fx = -s * PacejkaFx(rho * sigma_hat, Fz, friction_coeff, max_Fx);
	// btScalar Fy = -a * e(rho) * PacejkaFy(rho * alpha_hat, Fz, gamma, friction_coeff, max_Fy);

/*
	// combining method 2: orangutan
	btScalar Fx = PacejkaFx(sigma, Fz, friction_coeff, max_Fx);
	btScalar Fy = PacejkaFy(alpha, Fz, gamma, friction_coeff, max_Fy);

	btScalar one = (sigma < 0.0) ? -1.0 : 1.0;
	btScalar pure_sigma = sigma / (one + sigma);
	btScalar pure_alpha = -tan_alpha / (one + sigma);
	btScalar pure_combined = sqrt(pure_sigma * pure_sigma + pure_alpha * pure_alpha);
	btScalar kappa_combined = pure_combined / (1.0 - pure_combined);
	btScalar alpha_combined = atan((one + sigma) * pure_combined);
	btScalar Flimitx = PacejkaFx(kappa_combined, Fz, friction_coeff, max_Fx);
	btScalar Flimity = PacejkaFy(alpha_combined * 180.0 / M_PI, Fz, gamma, friction_coeff, max_Fy);

	btScalar x = fabs(Fx) / (fabs(Fx) + fabs(Fy));
	btScalar y = 1.0 - x;
	btScalar Flimit = (fabs(x * Flimitx) + fabs(y * Flimity));
	btScalar Fmag = sqrt(Fx * Fx + Fy * Fy);
	if (Fmag > Flimit)
	{
		btScalar scale = Flimit / Fmag;
		Fx *= scale;
		Fy *= scale;
	}
*/
/*
	// combining method 3: traction circle
	btScalar Fx = PacejkaFx(sigma, Fz, friction_coeff, max_Fx);
	btScalar Fy = PacejkaFy(alpha, Fz, gamma, friction_coeff, max_Fy);

	// determine to what extent the tires are long (x) gripping vs lat (y) gripping
	// 1.0 when Fy is zero, 0.0 when Fx is zero
	btScalar longfactor = 1.0;
	btScalar combforce = btFabs(Fx) + btFabs(Fy);
	if (combforce > 1) longfactor = btFabs(Fx) / combforce;

	// determine the maximum force for this amount of long vs lat grip by linear interpolation
	btScalar maxforce = btFabs(max_Fx) * longfactor + (1.0 - longfactor) * btFabs(max_Fy);

	// scale down forces to fit into the maximum
	if (combforce > maxforce)
	{
		Fx *= maxforce / combforce;
		Fy *= maxforce / combforce;
	}
*/
/*
	// combining method 4: traction ellipse (prioritize Fx)
	// issue: assumes that adhesion limits are fully reached for combined forces
	btScalar Fx = PacejkaFx(sigma, Fz, friction_coeff, max_Fx);
	btScalar Fy = PacejkaFy(alpha, Fz, gamma, friction_coeff, max_Fy);
	if (Fx < max_Fx)
	{
		Fy = Fy * sqrt(1.0 - (Fx / max_Fx) * (Fx / max_Fx));
	}
	else
	{
		Fx = max_Fx;
		Fy = 0;
	}
*/
/*
	// combining method 5: traction ellipse (prioritize Fy)
	// issue: assumes that adhesion limits are fully reached for combined forces
	btScalar Fx = PacejkaFx(sigma, Fz, friction_coeff, max_Fx);
	btScalar Fy = PacejkaFy(alpha, Fz, gamma, friction_coeff, max_Fy);
	if (Fy < max_Fy)
	{
		Fx = Fx * sqrt(1.0 - (Fy / max_Fy) * (Fy / max_Fy));
	}
	else
	{
		Fy = max_Fy;
		Fx = 0;
	}
*/
/*
	// no combining
	btScalar Fx = PacejkaFx(sigma, Fz, friction_coeff, max_Fx);
	btScalar Fy = PacejkaFy(alpha, Fz, gamma, friction_coeff, max_Fy);
*/
	btScalar Mz = PacejkaMz(sigma, alpha, Fz, gamma, friction_coeff, max_Mz);

	camber = inclination;
	slide = sigma;
	slip = alpha;
	ideal_slide = sigma_hat;
	ideal_slip = alpha_hat;
	fx = Fx;
	fy = Fy;
	fz = Fz;
	mz = Mz;
	vx = lon_slip_velocity;
	vy = lat_velocity;

	// Fx positive during traction, Fy positive in a right turn, Mz positive in a left turn
	return btVector3(Fx, Fy, Mz);
}
Esempio n. 2
0
btVector3 Tire::getForce(
	btScalar normal_load,
	btScalar friction_coeff,
	btScalar camber,
	btScalar rot_velocity,
	btScalar lon_velocity,
	btScalar lat_velocity)
{
	if (normal_load * friction_coeff  < btScalar(1E-6))
	{
		slip = slip_angle = 0;
		ideal_slip = ideal_slip_angle = 1;
		fx = fy = fz = mz = 0;
		vx = vy = 0;
		return btVector3(0, 0, 0);
	}

	// limit input
	normal_load = Clamp(normal_load, btScalar(0), btScalar(max_load));
	camber = Clamp(camber, -max_camber, max_camber);

	// sigma and alpha
	btScalar denom = Max(btFabs(lon_velocity), btScalar(1E-3));
	btScalar lon_slip_velocity = lon_velocity - rot_velocity;
	btScalar sigma = -lon_slip_velocity / denom;
	btScalar alpha = btAtan(lat_velocity / denom);

	// force parameters
	btScalar Fz = normal_load;
	btScalar Fz0 = nominal_load;
	btScalar dFz = (Fz - Fz0) / Fz0;

	// pure slip
	btScalar Dy, BCy, Shf;
	btScalar Fx0 = PacejkaFx(sigma, Fz, dFz, friction_coeff);
	btScalar Fy0 = PacejkaFy(alpha, camber, Fz, dFz, friction_coeff, Dy, BCy, Shf);
	btScalar Mz0 = PacejkaMz(alpha, camber, Fz, dFz, friction_coeff, Fy0, BCy, Shf);

	// combined slip
	btScalar Gx = PacejkaGx(sigma, alpha);
	btScalar Gy = PacejkaGy(sigma, alpha);
	btScalar Svy = PacejkaSvy(sigma, alpha, camber, dFz, Dy);
	btScalar Fx = Gx * Fx0;
	btScalar Fy = Gy * Fy0 + Svy;

	// ideal slip and angle
	btScalar sigma_hat(0), alpha_hat(0);
	getSigmaHatAlphaHat(normal_load, sigma_hat, alpha_hat);

	slip = sigma;
	slip_angle = alpha;
	ideal_slip = sigma_hat;
	ideal_slip_angle = alpha_hat;
	fx = Fx;
	fy = Fy;
	fz = Fz;
	mz = Mz0;
	vx = lon_slip_velocity;
	vy = lat_velocity;

	return btVector3(Fx, Fy, Mz0);
}