Latest changes without errors
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. } } }