1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

hooks: rewrite a bunch of hooks to the new signal list method

This commit is contained in:
Steffen Vogel 2019-03-09 00:32:59 +01:00
parent df6317d593
commit 4229531cf1
6 changed files with 361 additions and 164 deletions

View file

@ -33,7 +33,7 @@ set(HOOK_SRC
limit_rate.c
scale.c
fix.c
# cast.c
cast.c
average.c
dump.c
dp.c

View file

@ -29,43 +29,129 @@
#include <villas/hook.h>
#include <villas/plugin.h>
#include <villas/sample.h>
#include <villas/bitset.h>
struct average {
int mask;
int offset;
struct bitset mask;
struct vlist signal_names;
};
static int average_init(struct hook *h)
{
int ret;
struct average *a = (struct average *) h->_vd;
ret = vlist_init(&a->signal_names);
if (ret)
return ret;
ret = bitset_init(&a->mask, 128);
if (ret)
return ret;
bitset_clear_all(&a->mask);
return 0;
}
static int average_destroy(struct hook *h)
{
int ret;
struct average *a = (struct average *) h->_vd;
ret = vlist_destroy(&a->signal_names, NULL, true);
if (ret)
return ret;
ret = bitset_destroy(&a->mask);
if (ret)
return ret;
return 0;
}
static int average_prepare(struct hook *h)
{
int ret;
struct average *a = (struct average *) h->_vd;
struct signal *avg_sig;
/* Setup mask */
for (size_t i = 0; i < vlist_length(&a->signal_names); i++) {
char *signal_name = (char *) vlist_at_safe(&a->signal_names, i);
int index = vlist_lookup_index(&a->signal_names, signal_name);
if (index < 0)
return -1;
bitset_set(&a->mask, index);
}
/* Add averaged signal */
avg_sig = signal_create("average", NULL, SIGNAL_TYPE_FLOAT);
if (!avg_sig)
return -1;
ret = vlist_insert(&h->signals, a->offset, avg_sig);
if (ret)
return ret;
return 0;
}
static int average_parse(struct hook *h, json_t *cfg)
{
struct average *p = (struct average *) h->_vd;
struct average *a = (struct average *) h->_vd;
int ret;
size_t i;
json_error_t err;
json_t *json_signals, *json_signal;
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: i }",
"offset", &p->offset,
"mask", &p->mask
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: o }",
"offset", &a->offset,
"signals", &json_signals
);
if (ret)
jerror(&err, "Failed to parse configuration of hook '%s'", hook_type_name(h->_vt));
if (!json_is_array(json_signals))
error("Setting 'signals' of hook '%s' must be a list of signal names", hook_type_name(h->_vt));
json_array_foreach(json_signals, i, json_signal) {
switch (json_typeof(json_signal)) {
case JSON_STRING:
vlist_push(&a->signal_names, strdup(json_string_value(json_signal)));
break;
case JSON_INTEGER:
bitset_set(&a->mask, json_integer_value(json_signal));
break;
default:
error("Invalid value for setting 'signals' in hook '%s'", hook_type_name(h->_vt));
}
}
return 0;
}
static int average_process(struct hook *h, struct sample *smps[], unsigned *cnt)
{
struct average *p = (struct average *) h->_vd;
struct average *a = (struct average *) h->_vd;
for (int i = 0; i < *cnt; i++) {
struct sample *smp = smps[i];
double sum = 0;
double avg, sum = 0;
int n = 0;
for (int k = 0; k < smp->length; k++) {
if (!(p->mask & (1 << k)))
if (!bitset_test(&a->mask, k))
continue;
switch (sample_format(smps[i], k)) {
switch (sample_format(smp, k)) {
case SIGNAL_TYPE_INTEGER:
sum += smp->data[k].i;
break;
@ -84,7 +170,9 @@ static int average_process(struct hook *h, struct sample *smps[], unsigned *cnt)
n++;
}
smp->data[p->offset].f = sum / n;
avg = n == 0 ? 0 : sum / n;
sample_data_insert(smp, (union signal_data *) &avg, a->offset, 1);
smp->signals = &h->signals;
}
return 0;
@ -99,6 +187,9 @@ static struct plugin p = {
.priority = 99,
.parse = average_parse,
.process = average_process,
.init = average_init,
.init_signals = average_prepare,
.destroy = average_destroy,
.size = sizeof(struct average)
}
};

View file

@ -29,38 +29,58 @@
#include <villas/hook.h>
#include <villas/plugin.h>
#include <villas/node.h>
#include <villas/path.h>
#include <villas/sample.h>
struct cast {
int index;
int signal_index;
char *signal_name;
enum signal_type new_type;
char *new_name;
char *new_unit;
};
static int cast_init(struct hook *h)
static int cast_prepare(struct hook *h)
{
int ret;
struct signal *orig_sig, *new_sig;
struct cast *c = (struct cast *) h->_vd;
struct vlist *orig_signals;
if (h->node)
orig_signals = &h->node->in.signals;
else if (h->path)
orig_signals = &h->path->signals;
else
return -1;
if (c->signal_name) {
c->signal_index = vlist_lookup_index(&h->signals, c->signal_name);
if (c->signal_index < 0)
return -1;
}
struct signal *orig_sig = vlist_at(orig_signals, i);
struct signal *new_sig = signal_copy(orig_sig);
char *name, *unit;
enum signal_type type;
orig_sig = vlist_at_safe(&h->signals, c->signal_index);
type = c->new_type != SIGNAL_TYPE_AUTO ? c->new_type : orig_sig->type;
name = c->new_name ? c->new_name : orig_sig->name;
unit = c->new_unit ? c->new_unit : orig_sig->unit;
new_sig = signal_create(name, unit, type);
vlist_set(&h->signals, c->signal_index, new_sig);
signal_decref(orig_sig);
return 0;
}
static int cast_destroy(struct hook *h)
{
int ret;
struct cast *c = (struct cast *) h->_vd;
if (c->signal_name)
free(c->signal_name);
if (c->new_name)
free(c->new_name);
if (c->new_unit)
free(c->new_unit);
return 0;
}
@ -68,67 +88,50 @@ static int cast_parse(struct hook *h, json_t *cfg)
{
int ret;
struct cast *c = (struct cast *) h->_vd;
struct signal *sig;
size_t i;
json_error_t err;
int index = -1;
const char *name = NULL;
json_t *json_signal;
const char *new_name = NULL;
const char *new_unit = NULL;
const char *new_format = NULL;
const char *new_type = NULL;
ret = json_unpack_ex(cfg, &err, "{ s?: s, s?: i, s?: s, s?: s, s?: s }",
"name", &name,
"index", &index,
"new_format", &new_format,
ret = json_unpack_ex(cfg, &err, 0, "{ s: o, s?: s, s?: s, s?: s }",
"signal", &json_signal,
"new_type", &new_type,
"new_name", &new_name,
"new_unit", &new_unit
);
if (ret)
return ret;
/* Find matching original signal descriptor */
if (index >= 0 && name != NULL)
return -1;
switch (json_typeof(json_signal)) {
case JSON_STRING:
c->signal_name = strdup(json_string_value(json_signal));
break;
if (index < 0 && name == NULL)
return -1;
case JSON_INTEGER:
c->signal_name = NULL;
c->signal_index = json_integer_value(json_signal);
break;
sig = name
? vlist_lookup(&c->signals, name)
: vlist_at_safe(&c->signals, index);
if (!sig)
return -1;
default:
error("Invalid value for setting 'signal' in hook '%s'", hook_type_name(h->_vt));
}
/* Cast to new format */
if (new_format) {
enum signal_type fmt;
fmt = signal_type_from_str(new_format);
if (fmt == SIGNAL_TYPE_INVALID)
if (new_type) {
c->new_type = signal_type_from_str(new_type);
if (c->new_type == SIGNAL_TYPE_INVALID)
return -1;
sig->type = fmt;
}
else
c->new_type = SIGNAL_TYPE_AUTO; // We use this constant to indicate that we dont want to change the type
/* Set new name */
if (new_name) {
if (sig->name)
free(sig->name);
if (new_name)
c->new_name = strdup(new_name);
sig->name = strdup(new_name);
}
/* Set new unit */
if (new_unit) {
if (sig->unit)
free(sig->unit);
sig->unit = strdup(new_unit);
}
if (new_unit)
c->new_unit = strdup(new_unit);
return 0;
}
@ -140,15 +143,13 @@ static int cast_process(struct hook *h, struct sample *smps[], unsigned *cnt)
for (int i = 0; i < *cnt; i++) {
struct sample *smp = smps[i];
for (int j = 0; j < smp->length; j++) {
struct signal *orig_sig = vlist_at(smp->signals, j);
struct signal *new_sig = vlist_at(&c->signals, j);
struct signal *orig_sig = vlist_at(smp->signals, c->signal_index);
struct signal *new_sig = vlist_at(&h->signals, c->signal_index);
signal_data_cast(&smp->data[j], orig_sig, new_sig);
}
signal_data_cast(&smp->data[c->signal_index], orig_sig, new_sig);
/* Replace signal descriptors of sample */
smp->signals = &c->signals;
smp->signals = &h->signals;
}
return 0;
@ -161,8 +162,8 @@ static struct plugin p = {
.hook = {
.flags = HOOK_NODE_READ | HOOK_PATH,
.priority = 99,
.init = cast_init,
.destroy = cast_destroy,
.init_signals = cast_prepare,
.parse = cast_parse,
.process = cast_process,
.size = sizeof(struct cast)

View file

@ -36,7 +36,10 @@
#define J _Complex_I
struct dp {
int index;
char *signal_name;
int signal_index;
int offset;
int inverse;
double f0;
@ -48,30 +51,31 @@ struct dp {
int fharmonics_len;
struct window window;
struct vlist *signals;
};
static void dp_step(struct dp *d, double *in, float complex *out)
{
int n = d->window.steps;
double r = 0.9999999999;
double complex om, corr;
double newest = *in;
double oldest = window_update(&d->window, newest);
for (int i = 0; i < d->fharmonics_len; i++) {
double pi_fharm = 2.0 * M_PI * d->fharmonics[i];
om = 2.0 * M_PI * J * d->fharmonics[i] / n;
/* Recursive update */
d->coeffs[i] = (d->coeffs[i] + (newest - oldest)) * cexp(pi_fharm);
//d->coeffs[i] = cexp(om) * (d->coeffs[i] + (newest - oldest));
d->coeffs[i] = d->coeffs[i] * r * cexp(om) - powf(r, n) * oldest + newest;
/* Correction for stationary phasor */
double complex correction = cexp(pi_fharm * (d->t - (d->window.steps + 1)));
double complex result = 2.0 / d->window.steps * d->coeffs[i] / correction;
corr = cexp(-om * (d->t - (d->window.steps + 1)));
out[i] = (2.0 / d->window.steps) * (d->coeffs[i] * corr);
/* DC component */
if (i == 0)
result /= 2.0;
out[i] = result;
if (d->fharmonics[i] == 0)
out[i] /= 2.0;
}
}
@ -96,7 +100,6 @@ static int dp_start(struct hook *h)
struct dp *d = (struct dp *) h->_vd;
d->t = 0;
d->signals = NULL;
for (int i = 0; i < d->fharmonics_len; i++)
d->coeffs[i] = 0;
@ -138,6 +141,9 @@ static int dp_destroy(struct hook *h)
free(d->fharmonics);
free(d->coeffs);
if (d->signal_name)
free(d->signal_name);
return 0;
}
@ -147,13 +153,13 @@ static int dp_parse(struct hook *h, json_t *cfg)
int ret;
json_error_t err;
json_t *json_harmonics, *json_harmonic;
json_t *json_harmonics, *json_harmonic, *json_signal;
size_t i;
double rate = -1, dt = -1;
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s: F, s?: F, s?: F, s: o, s?: b }",
"index", &d->index,
ret = json_unpack_ex(cfg, &err, 0, "{ s: o, s: F, s?: F, s?: F, s: o, s?: b }",
"signal", &json_signal,
"f0", &d->f0,
"dt", &dt,
"rate", &rate,
@ -173,6 +179,20 @@ static int dp_parse(struct hook *h, json_t *cfg)
if (!json_is_array(json_harmonics))
error("Setting 'harmonics' of hook '%s' must be a list of integers", plugin_name(h->_vt));
switch (json_typeof(json_signal)) {
case JSON_STRING:
d->signal_name = strdup(json_string_value(json_signal));
break;
case JSON_INTEGER:
d->signal_name = NULL;
d->signal_index = json_integer_value(json_signal);
break;
default:
error("Invalid value for setting 'signal' in hook '%s'", hook_type_name(h->_vt));
}
d->fharmonics_len = json_array_size(json_harmonics);
d->fharmonics = alloc(d->fharmonics_len * sizeof(double));
d->coeffs = alloc(d->fharmonics_len * sizeof(double complex));
@ -183,7 +203,79 @@ static int dp_parse(struct hook *h, json_t *cfg)
if (!json_is_integer(json_harmonic))
error("Setting 'harmonics' of hook '%s' must be a list of integers", plugin_name(h->_vt));
d->fharmonics[i] = d->f0 * json_integer_value(json_harmonic);
d->fharmonics[i] = json_integer_value(json_harmonic);
}
return 0;
}
static int dp_prepare(struct hook *h)
{
int ret;
struct dp *d = (struct dp *) h->_vd;
char *new_sig_name;
struct signal *orig_sig, *new_sig;
if (d->signal_name) {
d->signal_index = vlist_lookup_index(&h->signals, d->signal_name);
if (d->signal_index < 0)
return -1;
}
if (d->inverse) {
/* Remove complex-valued coefficient signals */
for (int i = 0; i < d->fharmonics_len; i++) {
orig_sig = vlist_at_safe(&h->signals, d->signal_index + i);
if (!orig_sig)
return -1;
/** @todo: SIGNAL_TYPE_AUTO is bad here */
if (orig_sig->type != SIGNAL_TYPE_COMPLEX && orig_sig->type != SIGNAL_TYPE_AUTO)
return -1;
ret = vlist_remove(&h->signals, d->signal_index + i);
if (ret)
return -1;
signal_decref(orig_sig);
}
/* Add new real-valued reconstructed signals */
new_sig = signal_create("dp", "idp", SIGNAL_TYPE_FLOAT);
if (!new_sig)
return -1;
ret = vlist_insert(&h->signals, d->offset, new_sig);
if (ret)
return -1;
}
else {
orig_sig = vlist_at_safe(&h->signals, d->signal_index);
if (!orig_sig)
return -1;
/** @todo: SIGNAL_TYPE_AUTO is bad here */
if (orig_sig->type != SIGNAL_TYPE_FLOAT && orig_sig->type != SIGNAL_TYPE_AUTO)
return -1;
ret = vlist_remove(&h->signals, d->signal_index);
if (ret)
return -1;
for (int i = 0; i < d->fharmonics_len; i++) {
new_sig_name = strf("%s_harm%d", orig_sig->name, i);
new_sig = signal_create(new_sig_name, orig_sig->unit, SIGNAL_TYPE_COMPLEX);
if (!new_sig)
return -1;
ret = vlist_insert(&h->signals, d->offset + i, new_sig);
if (ret)
return -1;
}
signal_decref(orig_sig);
}
return 0;
@ -196,50 +288,29 @@ static int dp_process(struct hook *h, struct sample *smps[], unsigned *cnt)
for (unsigned j = 0; j < *cnt; j++) {
struct sample *smp = smps[j];
if (d->index > smp->length)
if (d->signal_index > smp->length)
continue;
if (!d->signals) {
struct signal *orig_sig, *new_sig;
if (d->inverse) {
double signal;
float complex *coeffs = &smp->data[d->signal_index].z;
d->signals = alloc(sizeof(struct vlist));
d->signals->state = STATE_DESTROYED;
dp_istep(d, coeffs, &signal);
vlist_copy(d->signals, smp->signals);
sample_data_remove(smp, d->signal_index, d->fharmonics_len);
sample_data_insert(smp, (union signal_data *) &signal, d->offset, 1);
}
else {
double signal = smp->data[d->signal_index].f;
float complex coeffs[d->fharmonics_len];
orig_sig = vlist_at(smp->signals, d->index);
if (!orig_sig)
return -1;
dp_step(d, &signal, coeffs);
if (d->inverse) {
if (orig_sig->type != SIGNAL_TYPE_COMPLEX)
return -1;
}
else {
if (orig_sig->type != SIGNAL_TYPE_FLOAT)
return -1;
}
new_sig = signal_copy(orig_sig);
if (!new_sig)
return -1;
if (d->inverse)
new_sig->type = SIGNAL_TYPE_FLOAT;
else
new_sig->type = SIGNAL_TYPE_COMPLEX;
int ret = vlist_set(d->signals, d->index, new_sig);
if (ret)
return ret;
sample_data_remove(smp, d->signal_index, 1);
sample_data_insert(smp, (union signal_data *) coeffs, d->offset, d->fharmonics_len);
}
smp->signals = d->signals;
if (d->inverse)
dp_istep(d, &smp->data[d->index].z, &smp->data[d->index].f);
else
dp_step(d, &smp->data[d->index].f, &smp->data[d->index].z);
smp->signals = &h->signals;
}
d->t += d->dt;
@ -252,9 +323,10 @@ static struct plugin p = {
.description = "Transform to/from dynamic phasor domain",
.type = PLUGIN_TYPE_HOOK,
.hook = {
.flags = HOOK_PATH,
.flags = HOOK_PATH | HOOK_NODE_READ | HOOK_NODE_WRITE,
.priority = 99,
.init = dp_init,
.init_signals = dp_prepare,
.destroy = dp_destroy,
.start = dp_start,
.stop = dp_stop,

View file

@ -56,18 +56,7 @@ static int print_start(struct hook *h)
struct print *p = (struct print *) h->_vd;
int ret;
struct vlist *signals;
if (h->node)
signals = &h->node->in.signals;
else if (h->path)
signals = &h->path->signals;
else
signals = NULL;
ret = signals
? io_init(&p->io, p->format, signals, SAMPLE_HAS_ALL)
: io_init_auto(&p->io, p->format, DEFAULT_SAMPLE_LENGTH, SAMPLE_HAS_ALL);
ret = io_init(&p->io, p->format, &h->signals, SAMPLE_HAS_ALL);
if (ret)
return ret;

View file

@ -31,63 +31,105 @@
#include <villas/sample.h>
struct scale {
char *signal_name;
int signal_index;
double scale;
double offset;
};
static int scale_init(struct hook *h)
{
struct scale *p = (struct scale *) h->_vd;
struct scale *s = (struct scale *) h->_vd;
p->scale = 1;
p->offset = 0;
s->scale = 1;
s->offset = 0;
return 0;
}
static int scale_prepare(struct hook *h)
{
struct scale *s = (struct scale *) h->_vd;
if (s->signal_name) {
s->signal_index = vlist_lookup_index(&h->signals, s->signal_name);
if (s->signal_index < 0)
return -1;
}
return 0;
}
static int scale_destroy(struct hook *h)
{
struct scale *s = (struct scale *) h->_vd;
if (s->signal_name)
free(s->signal_name);
return 0;
}
static int scale_parse(struct hook *h, json_t *cfg)
{
struct scale *p = (struct scale *) h->_vd;
struct scale *s = (struct scale *) h->_vd;
int ret;
json_t *json_signal;
json_error_t err;
ret = json_unpack_ex(cfg, &err, 0, "{ s?: F, s?: F }",
"scale", &p->scale,
"offset", &p->offset
ret = json_unpack_ex(cfg, &err, 0, "{ s?: F, s?: F, s: o }",
"scale", &s->scale,
"offset", &s->offset,
"signal", &json_signal
);
if (ret)
jerror(&err, "Failed to parse configuration of hook '%s'", hook_type_name(h->_vt));
switch (json_typeof(json_signal)) {
case JSON_STRING:
s->signal_name = strdup(json_string_value(json_signal));
break;
case JSON_INTEGER:
s->signal_name = NULL;
s->signal_index = json_integer_value(json_signal);
break;
default:
error("Invalid value for setting 'signal' in hook '%s'", hook_type_name(h->_vt));
}
return 0;
}
static int scale_process(struct hook *h, struct sample *smps[], unsigned *cnt)
{
struct scale *p = (struct scale *) h->_vd;
struct scale *s = (struct scale *) h->_vd;
for (int i = 0; i < *cnt; i++) {
for (int k = 0; k < smps[i]->length; k++) {
struct sample *smp = smps[i];
int k = s->signal_index;
switch (sample_format(smps[i], k)) {
case SIGNAL_TYPE_INTEGER:
smps[i]->data[k].i = smps[i]->data[k].i * p->scale + p->offset;
break;
switch (sample_format(smp, k)) {
case SIGNAL_TYPE_INTEGER:
smp->data[k].i = smp->data[k].i * s->scale + s->offset;
break;
case SIGNAL_TYPE_FLOAT:
smps[i]->data[k].f = smps[i]->data[k].f * p->scale + p->offset;
break;
case SIGNAL_TYPE_FLOAT:
smp->data[k].f = smp->data[k].f * s->scale + s->offset;
break;
case SIGNAL_TYPE_COMPLEX:
smps[i]->data[k].z = smps[i]->data[k].z * p->scale + p->offset;
break;
case SIGNAL_TYPE_COMPLEX:
smp->data[k].z = smp->data[k].z * s->scale + s->offset;
break;
case SIGNAL_TYPE_BOOLEAN:
smps[i]->data[k].b = smps[i]->data[k].b * p->scale + p->offset;
break;
case SIGNAL_TYPE_BOOLEAN:
smp->data[k].b = smp->data[k].b * s->scale + s->offset;
break;
default: { }
}
default: { }
}
}
@ -102,6 +144,8 @@ static struct plugin p = {
.flags = HOOK_PATH,
.priority = 99,
.init = scale_init,
.init_signals = scale_prepare,
.destroy = scale_destroy,
.parse = scale_parse,
.process = scale_process,
.size = sizeof(struct scale)