#include "gtl_math_intg.h" namespace gtl { namespace math { intg::intg(gtl::analog_data* parent, bool is_hidden) : gtl::analog_data(parent, is_hidden) , _taps(1) // , _delay(1) , _threshold(1e+10) , _autonorm(false) , _autoreset(false) { if(parent == NULL) return; _device = static_cast(analog_data::root()); if(_device) _device->lock_ai(); QString name_base = tr("integrator"); QString name = name_base; int idx = 0; while(parent->is_child_name_exist(name)) { idx++; name = name_base + "_" + QString::number(idx); } set_name(name); init(); if(_device) _device->unlock_ai(); } intg::~intg() { delete _delays; } int intg::taps() const { return _taps; } void intg::reset() { if(_device) _device->lock_ai(); for( int i = 0; i < _taps; i++) _delays->at(i) = 0; if(_device) _device->unlock_ai(); } void intg::set_taps(int value) { if( value > 0 && value != _taps) { _taps = value; init(); } } // int intg::delay() const // { // return _delay; // } // void intg::set_delay(int value) // { // if( value > 0 && value != _delay) // { // _delay = value; // init(); // } // } void intg::set_data(iterator begin, iterator end) { clear(); std::copy(begin, end, std::back_inserter(*this)); //to do... process(this->begin(), this->end()); gtl::analog_data::set_data(this->begin(), this->end()); } void intg::init() { if(_device) _device->lock_ai(); if(_delays) delete _delays; _delays = new std::vector(_taps); if(_device) _device->unlock_ai(); } void intg::process(iterator begin, iterator end) { if(_autoreset && (abs(_delays->back()) > _threshold)) reset(); int size = std::distance(begin, end); qreal dt = 1./get_rate(); for( int i = 0; i < size; i++) { // Обратный метод Эйлера : https://docs.exponenta.ru/simulink/slref/discretetimeintegrator.html qreal value = *(begin + i)*dt; for(int t = 0; t < _taps; t++) { value += _delays->at(t); _delays->at(t) = value; } *(begin + i) = value; } return; } qreal intg::threshold() const { return _threshold; } void intg::set_threshold(qreal newThreshold) { if (qFuzzyCompare(_threshold, newThreshold)) return; _threshold = newThreshold; emit threshold_changed(); } bool intg::autonorm() const { return _autonorm; } void intg::set_autonorm(bool newAuto_norm) { if (_autonorm == newAuto_norm) return; _autonorm = newAuto_norm; emit autonorm_changed(); } bool intg::autoreset() const { return _autoreset; } void intg::set_autoreset(bool newAuto_reset) { if (_autoreset == newAuto_reset) return; _autoreset = newAuto_reset; emit autoreset_changed(); } } }