New version of quadcopter software written to OO principles

Dependencies:   mbed MODSERIAL filter mbed-rtos ConfigFile PID PPM FreeIMU_external_magnetometer TinyGPS

Sensors/Sensors.cpp

Committer:
joe4465
Date:
2015-05-08
Revision:
4:9ffbf9101992
Parent:
3:4823d6750629

File content as of revision 4:9ffbf9101992:

#include "Sensors.h"

Sensors::Sensors(Status& status, ConfigFileWrapper& configFileWrapper, PinName gpsPinTx, PinName gpsPinRx, PinName i2cSda, PinName i2cScl, PinName lidarInterrupt) : _status(status)
{
    _gpsValues = Gps::Value();
    _position = Position();
    _startingPosition = Position();
    _altitude = Altitude();
    
    //Initialise IMU
    _imu = new Imu(configFileWrapper);
    _imu->zeroGyro();
    
    //Initialise GPS
    _gps = new Gps(gpsPinTx, gpsPinRx);
    
    //Initialise Lidar
    _lidar = new LidarLitePwm(lidarInterrupt);
    
    
    //Initialise kalman
    _altitudeKalmanFilter = new Kalman(1, 1, 1, 0);
    //_xPosKalmanFilter = new Kalman(0.1, 500, 1, 0);
    //_yPosKalmanFilter = new Kalman(0.1, 500, 1, 0);*/
    
    DEBUG("Sensors initialised\r\n");
}

Sensors::~Sensors(){}

void Sensors::update()
{
    //Update GPS
    updateGpsValues();
    
    //Update Altitude
    updateAltitude();
    
    //Update Position
    //updatePosition();
}

Imu::Rate Sensors::getRate()
{
    return _rate;
}

Imu::Angle Sensors::getAngle()
{
    return _angle;
}

Gps::Value Sensors::getGpsValues()
{
    return _position.gpsPosition;
}

Sensors::Altitude Sensors::getAltitude()
{
    return _altitude;   
}

Sensors::Position Sensors::getPosition()
{
    return _position;   
}

Imu::Velocity Sensors::getImuVelocity()
{
    return _imu->getVelocity();
}

Imu::Acceleration Sensors::getImuAcceleration()
{
    return _imu->getAcceleration();
}

void Sensors::updateImu()
{
    _angle = _imu->getAngle();
    _rate = _imu->getRate();
}

void Sensors::updateGpsValues()
{
    _position.gpsPosition = _gps->getValues();
}

void Sensors::updateAltitude()
{
    _altitude.lidar = getLidarAltitude();  //cm
    _altitude.barometer = _imu->getAltitude(); //cm
    _altitude.gps = _gpsValues.altitude; //m
    
    //Get IMU velocity
    double time = (1.0 / ((double)FLIGHT_CONTROLLER_FREQUENCY / 10.00)); // In seconds
    Imu::Velocity velocity = _imu->getVelocity(time);
    
    //Compute predicted altitude
    double predictedAltitude = _altitude.computed + velocity.z;
    
    //Compute predicted change in altitude
    double predictedChange = 1;
    if(_altitude.computed != 0) predictedChange = predictedAltitude / _altitude.computed;
    
    //Compute estimated altitude
    float altitude = 0;
    if(_altitude.computed < 20 * 100) altitude = _altitude.lidar;
    else altitude = _altitude.barometer;
    double estimatedAltitude = _altitudeKalmanFilter->update(predictedChange, altitude);
    
    //Compute estimated velocity
    velocity.z = estimatedAltitude - _altitude.computed;
    
    //Reset IMU velocity to estimated velocity
    _imu->setCurrentVelocity(velocity);
    
    //Save new altitude
    _altitude.computed = estimatedAltitude;
    
    //printf("%1.6f, %1.6f, %1.6f\r\n", predictedAltitude, _altitude.lidar, _altitude.computed);
}


void Sensors::updatePosition()
{
    /*
    //Get IMU velocity
    Imu::Velocity velocity = _imu->getVelocity();
    
    //Compute predicted positions
    double predictedXPos = _position.computedX + velocity.x;
    double predictedYPos = _position.computedY + velocity.y;
    
    //Compute predicted change in positions
    double predictedXChange = 1;
    double predictedYChange = 1;
    if(_position.computedX != 0) predictedXChange = predictedXPos / _position.computedX;
    if(_position.computedY != 0) predictedYChange = predictedYPos / _position.computedY;
    
    //Calc difference between current and starting GPS location
    //Assume pointed north for now
    Gps::Difference difference = _gps->getDifference(_startingPosition.gpsPosition, _position.gpsPosition);
    
    //printf("x vel %f, x diff %f, ", velocity.x, difference.x);
    //printf("y vel %f, y diff %f, ", velocity.y, difference.y);
    
    //Compute estimated position
    double estimatedXPos = _xPosKalmanFilter->update(predictedXChange, difference.x);
    double estimatedYPos = _yPosKalmanFilter->update(predictedYChange, difference.y);
    
    //Compute estimated velocity
    velocity.x = estimatedXPos - _position.computedX;
    velocity.y = estimatedYPos - _position.computedY;
    
    //Reset IMU velocity to estimated velocity
    _imu->setCurrentVelocity(velocity);
    
    //Save new position
    _position.computedX = estimatedXPos;
    _position.computedY = estimatedYPos;
    
    printf("Pos X %1.6f Pos Y %1.6f\r\n", _position.computedX, _position.computedY);*/
}

void Sensors::zeroGyro()
{
    _imu->zeroGyro();
}

void Sensors::zeroBarometer()
{
    _imu->zeroBarometer();
}

void Sensors::zeroPos()
{
    _startingPosition.gpsPosition.latitude = getGpsValues().latitude;
    _startingPosition.gpsPosition.longitude = getGpsValues().longitude;
    
    //Get IMU velocity
    Imu::Velocity velocity = _imu->getVelocity();
    
    //Set x y to 0
    velocity.x = 0;
    velocity.y = 0;
 
   //Reset IMU velocity to estimated velocity
    _imu->setCurrentVelocity(velocity);   
}

void Sensors::enable(bool enable)
{
    _imu->enable(enable);
}

int Sensors::getLidarAltitude()
{
    Imu::Angle angles = getAngle();
    int rawAltitude = _lidar->read();
    
    float correctedAltitude = rawAltitude * cos(toRadian(angles.roll)) * cos(toRadian(-angles.pitch));  
    /*
    double oppAng = 0;
    double multiplier = 0;  
    int pitchAltitude = 0;
    int rollAltitude = 0;
    
    //Calulate pitch altitude
    oppAng = 90 - abs(angles.pitch);
    multiplier = sin(oppAng*PI/180);
    pitchAltitude = multiplier * rawAltitude;
    
    //Calulate roll altitude
    oppAng = 90 - abs(angles.roll);
    multiplier = sin(oppAng*PI/180);
    rollAltitude = multiplier * rawAltitude;
    
    return (pitchAltitude + rollAltitude)/ 2;*/
    return correctedAltitude;
}

void Sensors::zeroAccel()
{
    _imu->zeroAccel();
}

double Sensors::toRadian(double deg)
{
    return (deg * PI / 180);
}