/******************************************************* * * DESCRIPTION: Signal classes * * AUTHOR: Mariana C. D'Abreu * * EMAIL: mdabreu@dc.uba.ar * ********************************************************/ #include "signal.h" #include "strutil.h" #include "mathincl.h" #include "realprec.h" /******************************************************************* * Defaults initialization: *******************************************************************/ const RealValue Signal::DefaultOffset = DEF_OFFSET; const RealValue Signal::DefaultStartTime = DEF_STRTIME; /******************************************************************* * Function: *******************************************************************/ Signal *Signal::create( const string &signalName ) { Signal *signal; string sname = lowerCase( signalName ); if ( sname == "constant" ) { signal = new ConstantSignal(); } else if ( sname == "step" ) { signal = new StepSignal(); } else if ( sname == "sine" ) { signal = new SineSignal(); } else if ( sname == "ramp" ) { signal = new RampSignal(); } else if ( sname == "expsine" ) { signal = new ExpSineSignal(); } else if ( sname == "exponential" ) { signal = new ExponentialSignal(); } else if ( sname == "pulse" ) { signal = new PulseSignal(); } else { SignalException e; e.addText( "Signal " + signalName + " not supported!" ); throw e; } return signal; } /******************************************************************* * Function: *******************************************************************/ RealValue Signal::der( STime t ) const { if ( !isDerivable() ) { SignalException e ; e.addText( "Signal not derivable!" ); throw e; } return derivative( t ); } /******************************************************************* * Function: *******************************************************************/ const string Signal::paramName( const unsigned int index ) const { if ( ( (int)index < 1 ) || (int)index > this->paramCount() ) { SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } return pName( index ); } /******************************************************************* * Function: ********************************************************************/ const RealValue Signal::paramValue( const unsigned int index ) const { if ( (int)index < 1 || (int)index > this->paramCount() ) { SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } return pValue( index ); } /******************************************************************* * Function: *******************************************************************/ Signal &Signal::setParam ( const unsigned int index, const RealValue &value ) { if ( (int)index < 1 || (int)index > this->paramCount() ) { SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } return set( index, value ); } /******************************************************************* * Function: *******************************************************************/ string Signal::info() const { string info; info = "Name : " + name() + "\n"; for (int i=1; i <= paramCount(); i++ ) { info += paramName( i ) + " = " + paramValue( i ) + "\n"; } return info; } /************************************* * * Clase para Senales concretas * *************************************/ /************************************* * Constant signal *************************************/ const RealValue ConstantSignal::DefaultConstant = 1; /************************************* * Step signal *************************************/ const RealValue StepSignal::DefaultHeight = 1; /******************************************************************* * Function: *******************************************************************/ const string StepSignal::pName ( const unsigned int index ) const { if( index == 1 ) return "height"; SignalException e; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: *******************************************************************/ const RealValue StepSignal::pValue( const unsigned int index ) const { if( index == 1 ) return height; SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ Signal &StepSignal::set( const unsigned int index, const RealValue &value ) { if ( index == 1 ) height = value; return *this; } /******************************************************************* * Function: ********************************************************************/ RealValue StepSignal::derivative( const STime t ) const { SignalException e ; e.addText( "Signal not derivable!" ); throw e; } /************************************* * Sine signal *************************************/ const RealValue SineSignal::DefaultAmplitude = 1; const RealValue SineSignal::DefaultPhase = 0; const RealValue SineSignal::DefaultWaveFreq = 1; /******************************************************************* * Constructor ********************************************************************/ SineSignal::SineSignal() :Signal() { amplitude = DefaultAmplitude; phase = DefaultPhase; wavefreq = DefaultWaveFreq; } /******************************************************************* * Constructor ********************************************************************/ SineSignal::SineSignal( const RealValue &litude, const RealValue &phase, const RealValue &wavefreq, const double offset, const double strTime ) :Signal( offset, strTime ) { this->amplitude = amplitude; this->phase = phase; this->wavefreq = wavefreq; } /******************************************************************* * Function: ********************************************************************/ RealValue SineSignal::s( const STime t ) const { RealValue aret = amplitude * sin( 2 * M_PI * wavefreq * t + phase ); return ( offset + ( t < startTime ? 0 : aret ) ); } /******************************************************************* * Function: ********************************************************************/ const string SineSignal::pName ( const unsigned int index ) const { switch ( index ) { case 1: return "amplitude"; case 2: return "phase"; case 3: return "wavefreq"; } SignalException e; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ const RealValue SineSignal::pValue( const unsigned int index ) const { switch ( index ) { case 1: return amplitude; case 2: return phase; case 3: return wavefreq; } SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ Signal &SineSignal::set( const unsigned int index, const RealValue &value ) { switch ( index ) { case 1: amplitude = value; break; case 2: phase = value; break; case 3: wavefreq = value; break; } return *this; } /******************************************************************* * Function: ********************************************************************/ RealValue SineSignal::derivative( const STime t ) const { RealValue d = 2 * M_PI * wavefreq; return ( amplitude * cos( d * t + phase ) * d ); } /************************************* * Ramp signal *************************************/ const RealValue RampSignal::DefaultHeight = 1; const RealValue RampSignal::DefaultDuration = 1; /******************************************************************* * Constructor ********************************************************************/ RampSignal::RampSignal() :Signal() { height = DefaultHeight; duration = DefaultDuration; } /******************************************************************* * Constructor ********************************************************************/ RampSignal::RampSignal( const RealValue &height, const RealValue &duration, const double offset, const double strTime ) :Signal( offset, strTime ) { this->height = height; this->duration = duration; } /******************************************************************* * Function: ********************************************************************/ RealValue RampSignal::s( const STime t ) const { if ( t < startTime ) { return offset; } else { if ( t < startTime + duration ) { return ( offset + ( height / duration * ( t - startTime ) ) ); } else { return ( offset + height ); } } } /******************************************************************* * Function: ********************************************************************/ const string RampSignal::pName ( const unsigned int index ) const { switch ( index ) { case 1: return "height"; case 2: return "duration"; } SignalException e; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ const RealValue RampSignal::pValue( const unsigned int index ) const { switch ( index ) { case 1: return height; case 2: return duration; } SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ Signal &RampSignal::set( const unsigned int index, const RealValue &value ) { switch ( index ) { case 1: height = value; break; case 2: duration = value; break; } return *this; } /******************************************************************* * Function: ********************************************************************/ RealValue RampSignal::derivative( const STime t ) const { SignalException e ; e.addText( "Signal not derivable!" ); throw e; } /************************************* * ExpSine signal *************************************/ const RealValue ExpSineSignal::DefaultAmplitude = 1; const RealValue ExpSineSignal::DefaultPhase = 0; const RealValue ExpSineSignal::DefaultWaveFreq = 2; const RealValue ExpSineSignal::DefaultDamping = 1; /******************************************************************* * Constructor ********************************************************************/ ExpSineSignal::ExpSineSignal() :Signal() { amplitude = DefaultAmplitude; phase = DefaultPhase; wavefreq = DefaultWaveFreq; damping = DefaultDamping; } /******************************************************************* * Constructor ********************************************************************/ ExpSineSignal::ExpSineSignal( const RealValue &, const RealValue &phase, const RealValue &wavefreq, const RealValue & damping, const double offset, const double strTime ) :Signal( offset, strTime ) { this->amplitude = amp; this->phase = phase; this->wavefreq = wavefreq; this->damping = damping; } /******************************************************************* * Function: ********************************************************************/ RealValue ExpSineSignal::s( const STime t ) const { RealValue aret = amplitude * exp( -t * damping ) * sin( 2 * M_PI * wavefreq * t + phase ); return ( offset + ( t < startTime ? 0 : aret ) ); } /******************************************************************* * Function: ********************************************************************/ const string ExpSineSignal::pName ( const unsigned int index ) const { switch ( index ) { case 1: return "amplitude"; case 2: return "phase"; case 3: return "wavefreq"; case 4: return "damping"; } SignalException e; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ const RealValue ExpSineSignal::pValue( const unsigned int index ) const { switch ( index ) { case 1: return amplitude; case 2: return phase; case 3: return wavefreq; case 4: return damping; } SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ Signal &ExpSineSignal::set( const unsigned int index, const RealValue &value ) { switch ( index ) { case 1: amplitude = value; break; case 2: phase = value; break; case 3: wavefreq = value; break; case 4: damping = value; } return *this; } /******************************************************************* * Function: ********************************************************************/ RealValue ExpSineSignal::derivative( const STime t ) const { RealValue d = 2 * M_PI * wavefreq; return ( amplitude * exp( -t * damping ) * -damping * cos( d * t + phase ) * d ); } /************************************* * Exponential signal *************************************/ const RealValue ExponentialSignal::DefaultHeight = 1; const RealValue ExponentialSignal::DefaultRiseTime = 0.5; const RealValue ExponentialSignal::DefaultRiseTimeConst = 0.1; const RealValue ExponentialSignal::DefaultFallTimeConst = 0.1; /******************************************************************* * Constructor ********************************************************************/ ExponentialSignal::ExponentialSignal() :Signal() { height = DefaultHeight; riseTime = DefaultRiseTime; riseTimeConst = DefaultRiseTimeConst; fallTimeConst = DefaultFallTimeConst; } /******************************************************************* * Constructor ********************************************************************/ ExponentialSignal::ExponentialSignal( const RealValue &height, const RealValue &rTime, const RealValue &rTimeConst, const RealValue &fallTime, const double offset, const double strTime ) :Signal( offset, strTime ) { this->height = height; this->riseTime = rTime; this->riseTimeConst = rTimeConst; this->fallTimeConst = fallTime; } /******************************************************************* * Function: ********************************************************************/ RealValue ExponentialSignal::s( const STime t ) const { RealValue y = height * ( 1 - exp( -riseTime/riseTimeConst ) ); if ( t < startTime ) { return offset; } else { if ( t < startTime + riseTime ) { return ( offset + ( height * ( 1 - exp( - ( t - startTime ) / riseTimeConst ) ) ) ); } else { return ( offset + ( y * exp( -( t - startTime - riseTime ) / fallTimeConst ) ) ); } } } /******************************************************************* * Function: ********************************************************************/ const string ExponentialSignal::pName ( const unsigned int index ) const { switch ( index ) { case 1: return "height"; case 2: return "riseTime"; case 3: return "riseTimeConst"; case 4: return "fallTimeConst"; } SignalException e; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ const RealValue ExponentialSignal::pValue( const unsigned int index ) const { switch ( index ) { case 1: return height; case 2: return riseTime; case 3: return riseTimeConst; case 4: return fallTimeConst; } SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ Signal &ExponentialSignal::set( const unsigned int index, const RealValue &value ) { switch ( index ) { case 1: height = value; break; case 2: riseTime = value; break; case 3: riseTimeConst = value; break; case 4: fallTimeConst = value; } return *this; } /******************************************************************* * Function: ********************************************************************/ RealValue ExponentialSignal::derivative( const STime t ) const { SignalException e ; e.addText( "Signal not derivable!" ); throw e; } /************************************* * Pulse signal *************************************/ const RealValue PulseSignal::DefaultAmplitude = 1; const RealValue PulseSignal::DefaultWidth = 50; const RealValue PulseSignal::DefaultPeriod = 1; /******************************************************************* * Constructor ********************************************************************/ PulseSignal::PulseSignal() :Signal() { amplitude = DefaultAmplitude; period = DefaultPeriod; width = period * DefaultWidth/100; } /******************************************************************* * Constructor ********************************************************************/ PulseSignal::PulseSignal( const RealValue &, const RealValue &width, const RealValue &period, const double offset, const double strTime ) :Signal( offset, strTime ) { this->amplitude = amp; this->period = period; this->width = width; } /******************************************************************* * Function: ********************************************************************/ RealValue PulseSignal::s( const STime t ) const { return ( offset + ( ( t < startTime ) || ( t >= ( periodInit( t ) + width ) ) ? 0 : amplitude ) ); } /******************************************************************* * Function: ********************************************************************/ const string PulseSignal::pName ( const unsigned int index ) const { switch ( index ) { case 1: return "amplitude"; case 2: return "period"; case 3: return "width"; } SignalException e; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ const RealValue PulseSignal::pValue( const unsigned int index ) const { switch ( index ) { case 1: return amplitude; case 2: return period; case 3: return width; } SignalException e ; e.addText( "Invalid param index: " + index ); throw e; } /******************************************************************* * Function: ********************************************************************/ Signal &PulseSignal::set( const unsigned int index, const RealValue &value ) { switch ( index ) { case 1: amplitude = value; break; case 2: period = value; width = period * width/100; break; case 3: width = period * value/100; break; } return *this; } /******************************************************************* * Function: ********************************************************************/ RealValue PulseSignal::derivative( const STime t ) const { SignalException e ; e.addText( "Signal not derivable!" ); throw e; } /******************************************************************* * Function: ********************************************************************/ RealValue PulseSignal::periodInit( const STime t ) const { if ( period == 0 ) { SignalException e ; e.addText( "Invalid period value!" ); throw e; } RealValue precision = RealPrecision::Tol.precision(); RealValue pinit = ( startTime + t )/ period; RealValue lpinit = (long long)( ceil( pinit / precision ) * precision ); lpinit = lpinit * period; return lpinit; }