Added real time signal viewer
This commit is contained in:
parent
24b9a24b04
commit
c7045a81e9
@ -7,6 +7,7 @@ set(lasp_dsp_files
|
||||
lasp_window.cpp
|
||||
lasp_fft.cpp
|
||||
lasp_rtaps.cpp
|
||||
lasp_rtsignalviewer.cpp
|
||||
lasp_avpowerspectra.cpp
|
||||
lasp_biquadbank.cpp
|
||||
lasp_thread.cpp
|
||||
|
@ -19,6 +19,10 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Real time spectral estimator using Welch method of spectral
|
||||
* estimation.
|
||||
*/
|
||||
class RtAps : public ThreadedInDataHandler {
|
||||
|
||||
std::unique_ptr<Filter> _filterPrototype;
|
||||
|
104
src/lasp/dsp/lasp_rtsignalviewer.cpp
Normal file
104
src/lasp/dsp/lasp_rtsignalviewer.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/* #define DEBUGTRACE_ENABLED */
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_rtsignalviewer.h"
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using Lck = std::scoped_lock<std::mutex>;
|
||||
using rte = std::runtime_error;
|
||||
|
||||
RtSignalViewer::RtSignalViewer(StreamMgr &mgr, const d approx_time_hist,
|
||||
const us resolution, const us channel)
|
||||
: ThreadedInDataHandler(mgr), _approx_time_hist(approx_time_hist),
|
||||
_resolution(resolution), _channel(channel) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
|
||||
if (approx_time_hist <= 0) {
|
||||
throw rte("Invalid time history. Should be > 0");
|
||||
}
|
||||
if (resolution <= 1) {
|
||||
throw rte("Invalid resolution. Should be > 1");
|
||||
}
|
||||
}
|
||||
|
||||
bool RtSignalViewer::inCallback_threaded(const DaqData &data) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
|
||||
Lck lck(_sv_mtx);
|
||||
|
||||
/// Push new data in time buffer, scaled by sensitivity
|
||||
_tb.push(data.toFloat(_channel) / _sens(_channel));
|
||||
|
||||
_dat.col(0) += _nsamples_per_point / _fs;
|
||||
/// Required number of samples for a new 'point'
|
||||
while (_tb.size() > _nsamples_per_point) {
|
||||
// Roll forward time column
|
||||
_dat.col(0) += _nsamples_per_point / _fs;
|
||||
vd newvals = _tb.pop(_nsamples_per_point);
|
||||
d newmax = newvals.max();
|
||||
d newmin = newvals.min();
|
||||
|
||||
vd mincol = _dat.col(1);
|
||||
vd maxcol = _dat.col(2);
|
||||
_dat(arma::span(0, _resolution-2),1) = mincol(arma::span(1, _resolution-1));
|
||||
_dat(arma::span(0, _resolution-2),2) = maxcol(arma::span(1, _resolution-1));
|
||||
_dat(_resolution-1, 1) = newmin;
|
||||
_dat(_resolution-1, 2) = newmax;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RtSignalViewer::~RtSignalViewer() {
|
||||
Lck lck(_sv_mtx);
|
||||
stop();
|
||||
}
|
||||
void RtSignalViewer::reset(const Daq *daq) {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
Lck lck(_sv_mtx);
|
||||
|
||||
// Reset time buffer
|
||||
_tb.reset();
|
||||
|
||||
if (daq) {
|
||||
_fs = daq->samplerate();
|
||||
|
||||
/// Update sensitivity values
|
||||
_sens.resize(daq->neninchannels());
|
||||
us i = 0;
|
||||
for (const auto &ch : daq->enabledInChannels()) {
|
||||
_sens[i] = ch.sensitivity;
|
||||
i++;
|
||||
}
|
||||
|
||||
/// The number of samples per point, based on which minmax are computed
|
||||
_nsamples_per_point =
|
||||
std::max<us>(static_cast<us>(_approx_time_hist / _resolution * _fs), 1);
|
||||
|
||||
const d dt_points = _nsamples_per_point / _fs;
|
||||
const d tend = dt_points * _resolution;
|
||||
|
||||
// Initialize data array
|
||||
_dat.resize(_resolution, 3);
|
||||
_dat.col(0) = arma::linspace(0, tend, _resolution);
|
||||
_dat.col(1).zeros();
|
||||
_dat.col(2).zeros();
|
||||
|
||||
} else {
|
||||
_sens.zeros();
|
||||
_fs = 0;
|
||||
_dat.reset();
|
||||
}
|
||||
}
|
||||
|
||||
dmat RtSignalViewer::getCurrentValue() const {
|
||||
|
||||
DEBUGTRACE_ENTER;
|
||||
Lck lck(_sv_mtx);
|
||||
return _dat;
|
||||
}
|
93
src/lasp/dsp/lasp_rtsignalviewer.h
Normal file
93
src/lasp/dsp/lasp_rtsignalviewer.h
Normal file
@ -0,0 +1,93 @@
|
||||
// lasp_threadedaps.h
|
||||
//
|
||||
// Author: J.A. de Jong - ASCEE
|
||||
//
|
||||
// Description: Real Time Signal Viewer.
|
||||
#pragma once
|
||||
#include "lasp_avpowerspectra.h"
|
||||
#include "lasp_filter.h"
|
||||
#include "lasp_mathtypes.h"
|
||||
#include "lasp_threadedindatahandler.h"
|
||||
#include "lasp_timebuffer.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
/**
|
||||
* \addtogroup dsp
|
||||
* @{
|
||||
*
|
||||
* \addtogroup rt
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Real time signal viewer. Shows envelope of the signal based on amount
|
||||
* of history shown.
|
||||
*/
|
||||
class RtSignalViewer : public ThreadedInDataHandler {
|
||||
|
||||
/**
|
||||
* @brief Storage for sensitivity values
|
||||
*/
|
||||
vd _sens;
|
||||
|
||||
/**
|
||||
* @brief Storage for time samples
|
||||
*/
|
||||
TimeBuffer _tb;
|
||||
|
||||
/**
|
||||
* @brief The amount of time history to show
|
||||
*/
|
||||
const d _approx_time_hist;
|
||||
/**
|
||||
* @brief The number of points to show
|
||||
*/
|
||||
const us _resolution;
|
||||
|
||||
/**
|
||||
* @brief The channel to show
|
||||
*/
|
||||
const us _channel;
|
||||
|
||||
us _nsamples_per_point;
|
||||
d _fs;
|
||||
|
||||
dmat _dat;
|
||||
|
||||
/**
|
||||
* @brief Mutex only for _signalviewer.
|
||||
*/
|
||||
mutable std::mutex _sv_mtx;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param mgr Stream manager
|
||||
* @param approx_time_hist The *approximate* time history to show. The exact
|
||||
* time history will be calculated such that there fits an integer number of
|
||||
* samples in a single 'point'.
|
||||
* @param resolution Number of time points
|
||||
* @param channel The channel number
|
||||
*/
|
||||
RtSignalViewer(StreamMgr &mgr, const d approx_time_hist, const us resolution,
|
||||
const us channel);
|
||||
|
||||
~RtSignalViewer();
|
||||
|
||||
/**
|
||||
* @brief Returns a 2D array, with:
|
||||
* - first column: time instances.
|
||||
* - second column: minimum value of signal
|
||||
* - third column: maximum value of signal
|
||||
*
|
||||
*/
|
||||
dmat getCurrentValue() const;
|
||||
|
||||
bool inCallback_threaded(const DaqData &) override final;
|
||||
void reset(const Daq *) override final;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
@ -1,11 +1,12 @@
|
||||
/* #define DEBUGTRACE_ENABLED */
|
||||
#include <armadillo>
|
||||
#include "arma_npy.h"
|
||||
#include "debugtrace.hpp"
|
||||
#include "lasp_ppm.h"
|
||||
#include "lasp_rtaps.h"
|
||||
#include "lasp_rtsignalviewer.h"
|
||||
#include "lasp_streammgr.h"
|
||||
#include "lasp_threadedindatahandler.h"
|
||||
#include <armadillo>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <pybind11/pybind11.h>
|
||||
@ -185,11 +186,10 @@ void init_datahandler(py::module &m) {
|
||||
ppm.def(py::init<StreamMgr &>());
|
||||
|
||||
ppm.def("getCurrentValue", [](const PPMHandler &ppm) {
|
||||
|
||||
std::tuple<vd, arma::uvec> tp = ppm.getCurrentValue();
|
||||
|
||||
return py::make_tuple(ColToNpy<d>(std::get<0>(tp)),
|
||||
ColToNpy<arma::uword>(std::get<1>(tp)));
|
||||
ColToNpy<arma::uword>(std::get<1>(tp)));
|
||||
});
|
||||
|
||||
/// Real time Aps
|
||||
@ -216,6 +216,20 @@ void init_datahandler(py::module &m) {
|
||||
|
||||
rtaps.def("getCurrentValue", [](RtAps &rt) {
|
||||
ccube val = rt.getCurrentValue();
|
||||
return CubeToNpy<c>(val);
|
||||
return CubeToNpy<c>(val);
|
||||
});
|
||||
|
||||
/// Real time Signal Viewer
|
||||
///
|
||||
py::class_<RtSignalViewer, ThreadedInDataHandler> rtsv(m, "RtSignalViewer");
|
||||
rtsv.def(py::init<StreamMgr &, // StreamMgr
|
||||
const d, // Time history
|
||||
const us, // Resolution
|
||||
const us // Channel number
|
||||
>());
|
||||
|
||||
rtsv.def("getCurrentValue", [](RtSignalViewer &rt) {
|
||||
dmat val = rt.getCurrentValue();
|
||||
return MatToNpy<d>(val);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user