Esempio n. 1
0
static void
updateSpool(tCar *car, tDifferential *differential, int first)
{
    tdble	DrTq;
    tdble	ndot;
    tdble	spinVel;
    tdble	BrTq;
    tdble	engineReaction;
    tdble	I;
    tdble	inTq, brkTq;
    
    DrTq = differential->in.Tq;

    I = differential->outAxis[0]->I + differential->outAxis[1]->I;
    inTq = differential->inAxis[0]->Tq + differential->inAxis[1]->Tq;
    brkTq = differential->inAxis[0]->brkTq + differential->inAxis[1]->brkTq;

    ndot = SimDeltaTime * (DrTq - inTq) / I;
    spinVel = differential->inAxis[0]->spinVel + ndot;
    
    BrTq = - SIGN(spinVel) * brkTq;
    ndot = SimDeltaTime * BrTq / I;
    
    if (((ndot * spinVel) < 0.0) && (fabs(ndot) > fabs(spinVel))) {
	ndot = -spinVel;
    }
    if ((spinVel == 0.0) && (ndot < 0.0)) ndot = 0;
    
    spinVel += ndot;
    if (first) {
	engineReaction = SimEngineUpdateRpm(car, spinVel);
	if (engineReaction != 0.0) {
	    spinVel = engineReaction;
	}
    }
    differential->outAxis[0]->spinVel = differential->outAxis[1]->spinVel = spinVel;

    differential->outAxis[0]->Tq = (differential->outAxis[0]->spinVel - differential->inAxis[0]->spinVel) / SimDeltaTime * differential->outAxis[0]->I;
    differential->outAxis[1]->Tq = (differential->outAxis[1]->spinVel - differential->inAxis[1]->spinVel) / SimDeltaTime * differential->outAxis[1]->I;
}
Esempio n. 2
0
void 
SimDifferentialUpdate(tCar *car, tDifferential *differential, int first)
{
    tdble	DrTq, DrTq0, DrTq1;
    tdble	ndot0, ndot1;
    tdble	spinVel0, spinVel1;
    tdble	inTq0, inTq1;
    tdble	spdRatio, spdRatioMax;
    tdble	deltaSpd, deltaTq;
    tdble	BrTq;
    tdble	engineReaction;
    tdble	meanv;

    if (differential->type == DIFF_SPOOL) {
	updateSpool(car, differential, first);
	return;
    }

    DrTq = differential->in.Tq;

    spinVel0 = differential->inAxis[0]->spinVel;
    spinVel1 = differential->inAxis[1]->spinVel;
    
    inTq0 = differential->inAxis[0]->Tq;
    inTq1 = differential->inAxis[1]->Tq;

    spdRatio = fabs(spinVel0 + spinVel1);
    if (spdRatio != 0) {
	spdRatio = fabs(spinVel0 - spinVel1) / spdRatio;

	switch (differential->type) {
	case DIFF_FREE:
		// I would think that the following is what a FREE
		// differential should look like, with both wheels
		// independent and linked through a spider gear.
		//
		// The reaction from each wheel is transmitted back to the
		// spider gear. If both wheels react equally, then the
		// spider gear does not turn. If one of the wheel is
		// immobile, so that DrTq/2=inTq0 for example, then the
		// reaction does not act against the drivetrain, but since
		// the spider gear can turn freely, it acts on the other wheel.
		// 
		// This system is equivalent to a rotating gear attached
		// in between two parallel surfaces, with DrTq being
		// equivalent to a force acting in the center of the
		// gear. If one surface is fixed, only the other surface
		// moves and all the force is 'transferred' to the moving
		// surface. Or, the way I like to think of it, the
		// immobile surface reacts with an equal and opposite
		// force[1] that cancels DrTq/2 exactly and which is
		// transmitted directly with the rotating gear to the
		// other, free, surface.
		//
		//
		// A lot of explanation for 3 lines of code..  TODO: Check
		// what bias would mean in such a system. Would it be
		// implemented between the spider and the wheels?  Or
		// between the spider and the drivetrain? If the latter
		// then it meanst the spider would always be turning, even
		// under an even load. I think in this case it is safest
		// to ignore it completely because it is frequently used
		// in cars with just FWD or RWD, and very frequently in
		// just the front part of 4WD cars, while the default
		// differential bias setting is 0.1...
		//
		// [1] For an object to remain at rest, all forces acting
		// on it must sum to 0.
			
		{
			float spiderTq = inTq1 - inTq0;
			DrTq0 = DrTq*0.5f + spiderTq;
			DrTq1 = DrTq*0.5f - spiderTq;
		}
	    break;
	case DIFF_LIMITED_SLIP:
	    if (DrTq > differential->lockInputTq) {
		updateSpool(car, differential, first);
		return;
	    }
	    spdRatioMax = differential->dSlipMax - DrTq * differential->dSlipMax / differential->lockInputTq;
	    if (spdRatio > spdRatioMax) {
		deltaSpd = (spdRatio - spdRatioMax) * fabs(spinVel0 + spinVel1) / 2.0;
		if (spinVel0 > spinVel1) {
		    spinVel0 -= deltaSpd;
		    spinVel1 += deltaSpd;
		} else {
		    spinVel0 += deltaSpd;
		    spinVel1 -= deltaSpd;
		}
	    }
	    if (spinVel0 > spinVel1) {
		DrTq1 = DrTq * (0.5 + differential->bias);
		DrTq0 = DrTq * (0.5 - differential->bias);
	    } else {
		DrTq1 = DrTq * (0.5 - differential->bias);
		DrTq0 = DrTq * (0.5 + differential->bias);
	    }
	    break;
	case DIFF_VISCOUS_COUPLER:
	    if (spinVel0 >= spinVel1) {
		DrTq0 = DrTq * differential->dTqMin;
		DrTq1 = DrTq * (1 - differential->dTqMin);
	    } else {
		deltaTq = differential->dTqMin + (1.0 - exp(-fabs(differential->viscosity * spinVel0 - spinVel1))) /
						  differential->viscomax * differential->dTqMax;
		DrTq0 = DrTq * deltaTq;
		DrTq1 = DrTq * (1 - deltaTq);
	    }
	
	    break;
	default: /* NONE ? */
	    DrTq0 = DrTq1 = 0;
	    break;
	}
    } else {
	DrTq0 = DrTq / 2.0;
	DrTq1 = DrTq / 2.0;
    }


    ndot0 = SimDeltaTime * (DrTq0 - inTq0) / differential->outAxis[0]->I;
    spinVel0 += ndot0;
    ndot1 = SimDeltaTime * (DrTq1 - inTq1) / differential->outAxis[1]->I;
    spinVel1 += ndot1;

    BrTq = - SIGN(spinVel0) * differential->inAxis[0]->brkTq;
    ndot0 = SimDeltaTime * BrTq / differential->outAxis[0]->I;
    if (((ndot0 * spinVel0) < 0.0) && (fabs(ndot0) > fabs(spinVel0))) {
	ndot0 = -spinVel0;
    }
    if ((spinVel0 == 0.0) && (ndot0 < 0.0)) ndot0 = 0;
    spinVel0 += ndot0;
	
    BrTq = - SIGN(spinVel1) * differential->inAxis[1]->brkTq;
    ndot1 = SimDeltaTime * BrTq / differential->outAxis[1]->I;
    if (((ndot1 * spinVel1) < 0.0) && (fabs(ndot1) > fabs(spinVel1))) {
	ndot1 = -spinVel1;
    }
    if ((spinVel1 == 0.0) && (ndot1 < 0.0)) ndot1 = 0;
    spinVel1 += ndot1;

    if (first) {
	meanv = (spinVel0 + spinVel1) / 2.0;
	engineReaction = SimEngineUpdateRpm(car, meanv);
	if (meanv != 0.0) {
	    engineReaction = engineReaction / meanv;
	    if (engineReaction != 0.0) {
		spinVel1 *= engineReaction;
		spinVel0 *= engineReaction;
	    }
	}
    }

    differential->outAxis[0]->spinVel = spinVel0;
    differential->outAxis[1]->spinVel = spinVel1;

    differential->outAxis[0]->Tq = (differential->outAxis[0]->spinVel - differential->inAxis[0]->spinVel) / SimDeltaTime * differential->outAxis[0]->I;
    differential->outAxis[1]->Tq = (differential->outAxis[1]->spinVel - differential->inAxis[1]->spinVel) / SimDeltaTime * differential->outAxis[1]->I;
    
}
Esempio n. 3
0
void
SimUpdate(tSituation *s, double deltaTime)
{
	int i;
	int ncar;
	tCarElt *carElt;
	tCar *car;
	
	SimDeltaTime = (tdble) deltaTime;
	for (ncar = 0; ncar < s->_ncars; ncar++) {
		SimCarTable[ncar].collision = 0;
		SimCarTable[ncar].blocked = 0;
	}
	
	for (ncar = 0; ncar < s->_ncars; ncar++) {
		car = &(SimCarTable[ncar]);
		carElt = car->carElt;
	
		if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
			RemoveCar(car, s);
			continue;
		} else if (((s->_maxDammage) && (car->dammage > s->_maxDammage)) ||
			(car->fuel == 0) ||
			(car->carElt->_state & RM_CAR_STATE_ELIMINATED))  {
			RemoveCar(car, s);
			if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
				continue;
			}
		}
	
		if (s->_raceState & RM_RACE_PRESTART && 
				(car->carElt->_skillLevel < 3 || !(s->_features & RM_FEATURE_PENALTIES))) {
			car->ctrl->brakeCmd = 1.0;
			car->ctrl->clutchCmd = 1.0;
		}
	
		CHECK(car);
		ctrlCheck(car);
		CHECK(car);
		SimSteerUpdate(car);
		CHECK(car);
		SimGearboxUpdate(car);
		CHECK(car);
		SimEngineUpdateTq(car);
		CHECK(car);
	
		if (!(s->_raceState & RM_RACE_PRESTART) || car->carElt->_skillLevel == 3) {
	
			SimCarUpdateWheelPos(car);
			CHECK(car);
			SimBrakeSystemUpdate(car);
			CHECK(car);
			SimAeroUpdate(car, s);
			CHECK(car);
			for (i = 0; i < 2; i++){
				SimWingUpdate(car, i, s);
			}
			CHECK(car);
			for (i = 0; i < 4; i++){
				SimWheelUpdateRide(car, i);
			}
			CHECK(car);
			for (i = 0; i < 2; i++){
				SimAxleUpdate(car, i);
			}
			CHECK(car);
			for (i = 0; i < 4; i++){
				SimWheelUpdateForce(car, i);
			}
			CHECK(car);
			SimTransmissionUpdate(car);
			CHECK(car);
			SimWheelUpdateRotation(car);
			CHECK(car);
			SimCarUpdate(car, s);
			CHECK(car);
		} else {
			SimTransmissionUpdate(car);
			SimEngineUpdateRpm(car, 0.0);
		}
	}
	
	SimCarCollideCars(s);
	
	/* printf ("%f - ", s->currentTime); */
	
	for (ncar = 0; ncar < s->_ncars; ncar++) {
		car = &(SimCarTable[ncar]);
		CHECK(car);
		carElt = car->carElt;
	
		if (carElt->_state & RM_CAR_STATE_NO_SIMU) {
			continue;
		}
	
		CHECK(car);
		SimCarUpdate2(car, s); /* telemetry */
	
		/* copy back the data to carElt */
	
		carElt->pub.DynGC = car->DynGC;
		carElt->pub.DynGCg = car->DynGCg;
		sgMakeCoordMat4(carElt->pub.posMat, carElt->_pos_X, carElt->_pos_Y, carElt->_pos_Z - carElt->_statGC_z,
				(float) RAD2DEG(carElt->_yaw), (float) RAD2DEG(carElt->_roll), (float) RAD2DEG(carElt->_pitch));
		carElt->_trkPos = car->trkPos;
		for (i = 0; i < 4; i++) {
			carElt->priv.wheel[i].relPos = car->wheel[i].relPos;
			carElt->_wheelSeg(i) = car->wheel[i].trkPos.seg;
			carElt->_brakeTemp(i) = car->wheel[i].brake.temp;
			carElt->pub.corner[i] = car->corner[i].pos;
		}
		carElt->_gear = car->transmission.gearbox.gear;
		carElt->_enginerpm = car->engine.rads;
		carElt->_fuel = car->fuel;
		carElt->priv.collision |= car->collision;
		carElt->_dammage = car->dammage;
	}
}