
/* Generated by Interface Builder */

#import <appkit/nextstd.h>
#import "Car_main.h"
#import "Motor.h"
#import "Transmission.h"
#import "defs.h"
#import "DataView.h"
#import "Battery.h"
#import "Cycle.h"

@implementation Motor

- init
{
    [super init];
    motor = self;
    return self;
}

- read:(NXTypedStream *)stream
{
    [super read:stream];
    NXReadTypes(stream,"fffff",&crossover,&efficiency,&mass,&max,&regenerationEfficiency);
    NXReadArray(stream,"f",6,highCoefficients);
    NXReadArray(stream,"f",6,lowCoefficients);
    return self;
}

- write:(NXTypedStream *)stream
{
    [super write:stream];
    NXWriteTypes(stream,"fffff",&crossover,&efficiency,&mass,&max,&regenerationEfficiency);
    NXWriteArray(stream,"f",6,highCoefficients);
    NXWriteArray(stream,"f",6,lowCoefficients);
    return self;
}

- (float)crossover
{
    return crossover;
}

- setCrossover:(float)aNumber
{
    crossover = aNumber;
    return self;
}

- (float)efficiency
{
    return efficiency;
}

- setEfficiency:(float)aNumber
{
    efficiency = aNumber;
    return self;
}

- (float *)highCoefficients
{
    return highCoefficients;
}

- setHighCoefficients:(float *)coefficients
{
int i;

    for ( i = 0 ; i < 6 ; i++ )
        highCoefficients[i] = coefficients[i];
    return self;
}

- (float *)lowCoefficients
{
    return lowCoefficients;
}

- setLowCoefficients:(float *)coefficients
{
int i;

    for ( i = 0 ; i < 6 ; i++ )
        lowCoefficients[i] = coefficients[i];
    return self;
}

- (float)mass
{
    return mass;
}

- setMass:(float)aNumber
{
    mass = aNumber;
    return self;
}

- (float)max
{
    return max;
}

- setMax:(float)aNumber
{
    max = aNumber;
    return self;
}

- (float)regenerationEfficiency
{
    return regenerationEfficiency;
}

- setRegenerationEfficiency:(float)aNumber
{
    regenerationEfficiency = aNumber;
    return self;
}

/******************************************************************************************************************************
 *    This is actually the only useful part of this object.  It is called when the simulation is run.   Note that the motor   *
 *    Will hand out as much negative (stopping) power is asked for.  This is definitely not right.                            *
 *    On second thought, this whole method needs to be rewritten.                                                             *
 ******************************************************************************************************************************/
- powerRequired:(float)power
{
float angVelocity;
float torqueRequired;
float torqueAvailable;
float powerToRequest;
float powerAvailable;
float outputTorque;
float rpm;
    
    angVelocity = [transmission inputSpeed];
    rpm = angVelocity * 60 / (2 * PI);

    if ( angVelocity == 0 )		// This is just a kludge we're using because some formulae won't work with the
        angVelocity = 0.01;		// velocity 0. ( That is, the car is trying to accelerate from a standstill. )
					// It is difficult to calculate a power with no velocity.
    if ( power > 0 )
        {
        torqueRequired = power / angVelocity;						// Calculate the torque required
        if ( rpm <= crossover )								// Calculate available torque
            torqueAvailable = evaluatePolynomial(lowCoefficients,6,rpm );  		// Remember the map is in rpm.
        else 
            torqueAvailable = evaluatePolynomial(highCoefficients,6,rpm);
        powerToRequest = MIN(torqueAvailable,torqueRequired) * angVelocity / efficiency; 
        powerAvailable = [battery powerRequested:powerToRequest forTime:[cycle timeStep]];  // Check with battery
        outputTorque = powerAvailable * efficiency / angVelocity;			// Determine output torque
        }
    else if ( power < 0 )
        {
        powerToRequest = power * regenerationEfficiency;	// Regeneration going on with efficiency.
        [battery powerRequested:powerToRequest forTime:[cycle timeStep]];	// Send power to battery
        outputTorque = power / angVelocity;	//All the negative power needed will be given.
        }
    else if ( power == 0 )
        {
        outputTorque = 0;
        }

/******************************************************************************************************************************
 *    Here is where power is passed on to the transmission.                                                                   *
 ******************************************************************************************************************************/
    [transmission motorInput:outputTorque];
    return self;
}

@end
