Latest changes without errors

Dependents:   SNOCC_V1 SNOCC_V2

VCODATA.cpp

Committer:
gstedile
Date:
2017-04-23
Revision:
8:8b37dcdc2b36
Parent:
7:302b432beab9
Child:
9:c17042fc1c98

File content as of revision 8:8b37dcdc2b36:

/* VCO DATA Library
 * Copyright (c) 2008-2010, sford
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "VCODATA.h"

//#include <math.h>


/*############################################################################
##############################################################################*/



//---------------------------------------------------------------------------------------------------------------------------------------
/* CONSTRUCTORES: */

VCODATA::VCODATA(NAVDATA InitData, int Vel_Max){
            vel_max= Vel_Max;                       // Velocidad máxima.
            DeltaV=1;
            InitData.paddata();                     // Inicializamos el vector LAST_NAV_DATA con valores default. Las constantes Klong, Klat; Ksen y ZH no se modifican.           
            NAV_DATA = new NAVDATA[vel_max+1];      // Array de "vel_max+1" elementos tipo NAVDATA. Posicion 101 para el Objeto a validar.
            for (int i=0;i<=vel_max;i+=1)            
            this->NAV_DATA[i]= InitData;            // Inicializa NAV_DATA[]. Carga el array repitiendo Initdata en todas las posiciones.
}

VCODATA::VCODATA(const VCODATA &VCOOBJ){                     // Cosntructor copia.
            vel_max=VCOOBJ.vel_max;
            DeltaV=1;
            NAV_DATA = new NAVDATA[vel_max+1];      // Array de "vel_max+1" elementos tipo NAVDATA. Posicion 101 para el Objeto a validar.
            for (int i=0;i<=vel_max;i+=1)            
            this->NAV_DATA[i]= VCOOBJ.NAV_DATA[i];  // Copio todos los objetos NAV_DATA del VCOOBJ a este.
            }   
            

//---------------------------------------------------------------------------------------------------------------------------------------
//store_data (NAVDATA LastData): Almacena el objeto LastData

void VCODATA::store_data (NAVDATA LastData){
        
       if (fabs(this->NAV_DATA[vel_max].LAST_NAV_DATA[speed_p] - LastData.LAST_NAV_DATA[speed_p])< this->DeltaV){
                
            this->merge_data(LastData);    // Combina los datos del actual con el anterior y los deja en la posicion [vel_max].
            this->NAV_DATA[int(LastData.LAST_NAV_DATA[speed_p])] = this->NAV_DATA[vel_max]; // Carga el objeto en NAV_DATA tomando como índice a la parte entera de la velocidad.          
        }
       else this->NAV_DATA[vel_max]=LastData;   // Cargo el entrante en la posicion [vel_max], reemplazando al anterior.
  
} 
               
               
            



//---------------------------------------------------------------------------------------------------------------------------------------
/* get_VCO(): Obtiene la Velocidad Crucero Optima (VCO)*/

int VCODATA::get_VCO(){
    int GET_Min=0;
    enum find {NO, SI, POSIBLE};
    int Ratio_Min=6;    // Entorno de evaluación de Máximos / Mínimos.
    int n_events_eps=0; // Cantidad de valores de v menores al Minimo (o mayores al Máximo) dentro del entorno Ratio_Min para evaluar validez de Minimo (o Maximo segun sea el caso).
    int n_events_critical=3; //Cantidad de ocurrencias para considerar la invalidéz del mínimo (o máximo) hallado;
    float ConsMin=100;       // Consumo mínimo inicial.
    float ConsMAX=0;         // Consumo máximo inicial.
    int VCO=-1;  
    find GET_MAX=NO;
    
    for (int vel=0;vel<vel_max;vel++){
        if(GET_MAX==SI){                        // Si halle el maximo y 
            if(GET_Min == 0){                   // no encontré el Minimo. (Aun no halle la VCO)
                if (this->NAV_DATA[vel].LAST_NAV_DATA[cons_mile_p]<=ConsMin){   //La curva sigue decreciendo
                    ConsMin=this->NAV_DATA[vel].LAST_NAV_DATA[cons_mile_p];    
                }
                else{
                    int eps_m=1;
                    for (int eps=1; eps < Ratio_Min;eps++){
                        if (this->NAV_DATA[vel+eps].LAST_NAV_DATA[cons_mile_p]<=ConsMin) {//hay valores menores al minimo hallado en un entorno de v?
                            n_events_eps++;  
                            ConsMin=this->NAV_DATA[vel+eps].LAST_NAV_DATA[cons_mile_p];
                            eps_m=eps;
                        }
                    }
                    if (n_events_eps >= n_events_critical) vel=vel+eps_m;    // falso minimo (hay muchos valores menores al minimo hallado)
                                                                             // nueva ubicación del minimo                       
                    else {
                            GET_Min=1;
                            VCO=vel-1;
                    }    
                }
            }
        }
                                   
        else{
                if (this->NAV_DATA[vel].LAST_NAV_DATA[cons_mile_p]>=ConsMAX){   //La curva sigue creciendo o se mantiene cte.
                    ConsMAX=this->NAV_DATA[vel].LAST_NAV_DATA[cons_mile_p]; 
                    GET_MAX=POSIBLE;   
                }
                else{
                    if (GET_MAX==POSIBLE){
                    int eps_m=1;
                    for (int eps=1; eps<Ratio_Min;eps++){
                        if (this->NAV_DATA[vel+eps].LAST_NAV_DATA[cons_mile_p]>ConsMAX) {//hay valores mayores al maximo hallado en un entorno de v?
                            n_events_eps++;  
                            ConsMAX=this->NAV_DATA[vel+eps].LAST_NAV_DATA[cons_mile_p];
                            eps_m=eps;
                            }
                        }
                        if (n_events_eps > n_events_critical) vel=vel+eps_m;    // falso maximo (hay muchos valores mayores al maximo hallado)
                                                                                // nueva ubicación del maximo                       
                        else GET_MAX=SI;
                     }   
        }
        } 
                    
    }
    
    //return (VCO);  
    return (int(ConsMAX*100));                  
}

//---------------------------------------------------------------------------------------------------------------------------------------
//interpolate(): Interpola los valores de consumo para completar la curva.

void VCODATA::interpolate(){
    int x_P1=0;//this->get_next_P(0);
    int x_P2=this->get_next_P(x_P1);
    while (x_P2>0 ) {            // Puntos validos? (Si es no válido get_next devuelve -1).
            if ( x_P2>x_P1+1) this->interp_x1_x2(x_P1, x_P2);  // Interpola entre los 2 puntos dados.
            x_P1=x_P2;
            x_P2=this->get_next_P(x_P2);
            }
}
    
//---------------------------------------------------------------------------------------------------------------------------------------
//get_next_P(int x_value): Retorna la ordenada del siguiente valor recolectado, que no es resultado de la interpolacion.
              
int VCODATA::get_next_P(int x_value){
    int i=1;
    int j=i+x_value;
    while (j<=vel_max){
        if ( this->NAV_DATA[j].LAST_NAV_DATA[cons_mile_p] <=0 || this->NAV_DATA[j].LAST_NAV_DATA[cons_interpolated] == 1) j++;  // Avanzar mientras haya valores ya interpolados, nulos, o -1 (caso de distancia recorrida nula-->0 milla)
        else break;
        } 
        if (j>vel_max)return(-1);                         // Llego al final sin hallar punto válido.
        else return(j);          
    }   
                  
//---------------------------------------------------------------------------------------------------------------------------------------
//interp_x1_x2(int x1,int x2): Interpola la matríz de datos tomando puntos de la recta que pasa por x1 y x2 
                                
void VCODATA::interp_x1_x2(int x1,int x2){
    float step=(this->NAV_DATA[x2].LAST_NAV_DATA[cons_mile_p] - this->NAV_DATA[x1].LAST_NAV_DATA[cons_mile_p])/(x2-x1);  // Pendiente: A
    for (int i=x1+1; i<x2; i++){ 
        this->NAV_DATA[i].LAST_NAV_DATA[cons_mile_p]= (i-x1)*step + this->NAV_DATA[x1].LAST_NAV_DATA[cons_mile_p];     // Y= Ax + B     
        this->NAV_DATA[i].LAST_NAV_DATA[cons_interpolated]=1;
        }
     }                               

//---------------------------------------------------------------------------------------------------------------------------------------
//merge_data(NAVDATA LastVector): Modifica los valores del array LAST_NAV_DATA del objeto almacenado en la ultima posicion de NAV_DATA, 
// combinándolos con LastVector.


void VCODATA::merge_data(NAVDATA LastVector){
                // El ultimo vector se guarda para validar el siguiente. El mismo ya contiene los promedios. Puede evaluarse dejar siempre los últimos valores en vez del promedio.
                // El valor que se almacena en la matriz, siempre es el promedio del último vector guardado con el recientemente ingresado.
                this->NAV_DATA[vel_max].LAST_NAV_DATA[longitude_f]=LastVector.LAST_NAV_DATA[longitude_f];                     
                this->NAV_DATA[vel_max].LAST_NAV_DATA[latitude_f]=LastVector.LAST_NAV_DATA[latitude_f];
                this->NAV_DATA[vel_max].LAST_NAV_DATA[time_f]=LastVector.LAST_NAV_DATA[time_f];             
                this->NAV_DATA[vel_max].LAST_NAV_DATA[distance_p]+=LastVector.LAST_NAV_DATA[distance_p];           
                this->NAV_DATA[vel_max].LAST_NAV_DATA[speed_p]=(this->NAV_DATA[vel_max].LAST_NAV_DATA[speed_p] + LastVector.LAST_NAV_DATA[speed_p])/2; //Promedio de velocidades;                          
                this->NAV_DATA[vel_max].LAST_NAV_DATA[consumption_f]=LastVector.LAST_NAV_DATA[consumption_f];        
                this->NAV_DATA[vel_max].LAST_NAV_DATA[consumption_p]+=LastVector.LAST_NAV_DATA[consumption_p];        
                this->NAV_DATA[vel_max].LAST_NAV_DATA[cons_mile_p]= (LastVector.LAST_NAV_DATA[cons_mile_p]+this->NAV_DATA[vel_max].LAST_NAV_DATA[cons_mile_p])/2; //Promedio-->Evaluar recalcular en base a los otros datos.         
                this->NAV_DATA[vel_max].LAST_NAV_DATA[cons_hour_p]=(LastVector.LAST_NAV_DATA[cons_hour_p]+this->NAV_DATA[vel_max].LAST_NAV_DATA[cons_hour_p])/2; //Promedio-->Evaluar recalcular en base a los otros datos. ;          
                this->NAV_DATA[vel_max].LAST_NAV_DATA[cons_interpolated]=0;
}

//---------------------------------------------------------------------------------------------------------------------------------------
// smooth(int n_dots,VCODATA SMOOTH_MTRX): Suaviza la curva discreta, promediando n puntos del entorno de cada punto.
// SMOOTH_MTRX es una copia de esta matríz (this) la cual resultará suavizada.
 
void VCODATA::smooth(int n_dots,VCODATA &REFERENCE_MTRX){   
                int n_int=int (n_dots/2);              
                int n_dif_l=0;                      // Valor para sesgar el entorno de promediado, respecto de la posicion actual, en caso de n par.
                if ((n_dots%n_int)==0)n_dif_l=1;    // si n es par entonces tomo una muestra menos del lado derecho. Elijo esta forma porque
                                                    // al discretizar la curva hemos redondeado hacia abajo los valores de velocidad; esto significa que el 
                                                    // valor de consumo asociado a una velocidad fue desplazado hacia la izquierda, por lo tanto, promediandolo
                                                    // con valores corresp. a velocidades con cierto sesgo hacia izquierda, mejora la representación y mas aún 
                                                    // con respecto al caso opuesto. Debe pensarse estadisticamente teniendo en cuenta que
                                                    // la media de cada periodo de velocidades se encuentra en el medio del período. Ejemplo:
                                                    // |      c1                        c3    
                                                    // |            cm12     
                                                    // |                      c2
                                                    // |__x1________xm12_x2__________x3     vemos que el valor real de velocidad de xm12 es mas cercano a x2 que el real de c2.
                for (int j=0;j<vel_max;j++){
                    float sum_cons=0;
                    int n_samp=0;
                    this->NAV_DATA[j]=REFERENCE_MTRX.NAV_DATA[j]; // Copia de objetos NAVDATA
                    for (int i=-n_int;i<=n_int-n_dif_l;i++){// si es impar va desde (n-1)/2 muestras a la izq, la propia muestra y (n-1)/2 muestras a la deracha.
                                                            // si es par reduce una muestra a la derecha. (n/2) a izq, la propia y n/2-1 a derecha.
                        if (j+i>=0 && j+i<vel_max){          // para excluir valores de velocidad fuera de rango. (extremos)
                            n_samp++;
                            sum_cons+= REFERENCE_MTRX.NAV_DATA[i+j].LAST_NAV_DATA[cons_mile_p];   
                            }
                    }    
                    if (n_samp>0){
                        
                        this->NAV_DATA[j].LAST_NAV_DATA[cons_mile_p]= sum_cons/n_samp;
                        this->NAV_DATA[j].LAST_NAV_DATA[cons_interpolated]=2;  // 2: Valor promediado.
                        }

                        
                }        
}