refclock: add maxdispersion option
This can be used to prevent accumulation of samples with estimated dispersion above given limit. By default, this limit is disabled.
This commit is contained in:
parent
e147f2f11e
commit
b745b6d546
4 changed files with 23 additions and 4 deletions
|
@ -2599,6 +2599,10 @@ sources. The default is 1e-9 (1 nanosecond).
|
||||||
@item precision
|
@item precision
|
||||||
Refclock precision (in seconds). The default is 1e-6 (1 microsecond)
|
Refclock precision (in seconds). The default is 1e-6 (1 microsecond)
|
||||||
for SHM refclock, and 1e-9 (1 nanosecond) for SOCK, PPS and PHC refclocks.
|
for SHM refclock, and 1e-9 (1 nanosecond) for SOCK, PPS and PHC refclocks.
|
||||||
|
@item maxdispersion
|
||||||
|
Maximum allowed dispersion for filtered samples (in seconds). Samples
|
||||||
|
with larger estimated dispersion are ignored. By default, this limit
|
||||||
|
is disabled.
|
||||||
@item prefer
|
@item prefer
|
||||||
Prefer this source over sources without prefer option.
|
Prefer this source over sources without prefer option.
|
||||||
@item noselect
|
@item noselect
|
||||||
|
|
7
conf.c
7
conf.c
|
@ -593,7 +593,7 @@ parse_refclock(char *line)
|
||||||
{
|
{
|
||||||
int i, n, poll, dpoll, filter_length, pps_rate;
|
int i, n, poll, dpoll, filter_length, pps_rate;
|
||||||
uint32_t ref_id, lock_ref_id;
|
uint32_t ref_id, lock_ref_id;
|
||||||
double offset, delay, precision;
|
double offset, delay, precision, max_dispersion;
|
||||||
char *p, *cmd, *name, *param;
|
char *p, *cmd, *name, *param;
|
||||||
unsigned char ref[5];
|
unsigned char ref[5];
|
||||||
SRC_SelectOption sel_option;
|
SRC_SelectOption sel_option;
|
||||||
|
@ -609,6 +609,7 @@ parse_refclock(char *line)
|
||||||
offset = 0.0;
|
offset = 0.0;
|
||||||
delay = 1e-9;
|
delay = 1e-9;
|
||||||
precision = 0.0;
|
precision = 0.0;
|
||||||
|
max_dispersion = 0.0;
|
||||||
ref_id = 0;
|
ref_id = 0;
|
||||||
lock_ref_id = 0;
|
lock_ref_id = 0;
|
||||||
sel_option = SRC_SelectNormal;
|
sel_option = SRC_SelectNormal;
|
||||||
|
@ -667,6 +668,9 @@ parse_refclock(char *line)
|
||||||
} else if (!strcasecmp(cmd, "precision")) {
|
} else if (!strcasecmp(cmd, "precision")) {
|
||||||
if (sscanf(line, "%lf%n", &precision, &n) != 1)
|
if (sscanf(line, "%lf%n", &precision, &n) != 1)
|
||||||
break;
|
break;
|
||||||
|
} else if (!strcasecmp(cmd, "maxdispersion")) {
|
||||||
|
if (sscanf(line, "%lf%n", &max_dispersion, &n) != 1)
|
||||||
|
break;
|
||||||
} else if (!strcasecmp(cmd, "noselect")) {
|
} else if (!strcasecmp(cmd, "noselect")) {
|
||||||
n = 0;
|
n = 0;
|
||||||
sel_option = SRC_SelectNoselect;
|
sel_option = SRC_SelectNoselect;
|
||||||
|
@ -693,6 +697,7 @@ parse_refclock(char *line)
|
||||||
refclock_sources[i].offset = offset;
|
refclock_sources[i].offset = offset;
|
||||||
refclock_sources[i].delay = delay;
|
refclock_sources[i].delay = delay;
|
||||||
refclock_sources[i].precision = precision;
|
refclock_sources[i].precision = precision;
|
||||||
|
refclock_sources[i].max_dispersion = max_dispersion;
|
||||||
refclock_sources[i].sel_option = sel_option;
|
refclock_sources[i].sel_option = sel_option;
|
||||||
refclock_sources[i].ref_id = ref_id;
|
refclock_sources[i].ref_id = ref_id;
|
||||||
refclock_sources[i].lock_ref_id = lock_ref_id;
|
refclock_sources[i].lock_ref_id = lock_ref_id;
|
||||||
|
|
15
refclock.c
15
refclock.c
|
@ -57,6 +57,7 @@ struct MedianFilter {
|
||||||
int last;
|
int last;
|
||||||
int avg_var_n;
|
int avg_var_n;
|
||||||
double avg_var;
|
double avg_var;
|
||||||
|
double max_var;
|
||||||
struct FilterSample *samples;
|
struct FilterSample *samples;
|
||||||
int *selected;
|
int *selected;
|
||||||
double *x_data;
|
double *x_data;
|
||||||
|
@ -100,7 +101,7 @@ static void slew_samples(struct timeval *raw, struct timeval *cooked, double dfr
|
||||||
static void add_dispersion(double dispersion, void *anything);
|
static void add_dispersion(double dispersion, void *anything);
|
||||||
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
|
static void log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int pulse, double raw_offset, double cooked_offset, double dispersion);
|
||||||
|
|
||||||
static void filter_init(struct MedianFilter *filter, int length);
|
static void filter_init(struct MedianFilter *filter, int length, double max_dispersion);
|
||||||
static void filter_fini(struct MedianFilter *filter);
|
static void filter_fini(struct MedianFilter *filter);
|
||||||
static void filter_reset(struct MedianFilter *filter);
|
static void filter_reset(struct MedianFilter *filter);
|
||||||
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
|
static double filter_get_avg_sample_dispersion(struct MedianFilter *filter);
|
||||||
|
@ -245,7 +246,7 @@ RCL_AddRefclock(RefclockParameters *params)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
filter_init(&inst->filter, params->filter_length);
|
filter_init(&inst->filter, params->filter_length, params->max_dispersion);
|
||||||
|
|
||||||
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
|
inst->source = SRC_CreateNewInstance(inst->ref_id, SRC_REFCLOCK, params->sel_option, NULL);
|
||||||
|
|
||||||
|
@ -622,7 +623,7 @@ log_sample(RCL_Instance instance, struct timeval *sample_time, int filtered, int
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
filter_init(struct MedianFilter *filter, int length)
|
filter_init(struct MedianFilter *filter, int length, double max_dispersion)
|
||||||
{
|
{
|
||||||
if (length < 1)
|
if (length < 1)
|
||||||
length = 1;
|
length = 1;
|
||||||
|
@ -634,6 +635,7 @@ filter_init(struct MedianFilter *filter, int length)
|
||||||
/* set first estimate to system precision */
|
/* set first estimate to system precision */
|
||||||
filter->avg_var_n = 0;
|
filter->avg_var_n = 0;
|
||||||
filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
|
filter->avg_var = LCL_GetSysPrecisionAsQuantum() * LCL_GetSysPrecisionAsQuantum();
|
||||||
|
filter->max_var = max_dispersion * max_dispersion;
|
||||||
filter->samples = MallocArray(struct FilterSample, filter->length);
|
filter->samples = MallocArray(struct FilterSample, filter->length);
|
||||||
filter->selected = MallocArray(int, filter->length);
|
filter->selected = MallocArray(int, filter->length);
|
||||||
filter->x_data = MallocArray(double, filter->length);
|
filter->x_data = MallocArray(double, filter->length);
|
||||||
|
@ -861,6 +863,13 @@ filter_get_sample(struct MedianFilter *filter, struct timeval *sample_time, doub
|
||||||
d = sqrt(var);
|
d = sqrt(var);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* drop the sample if variance is larger than allowed maximum */
|
||||||
|
if (filter->max_var > 0.0 && var > filter->max_var) {
|
||||||
|
DEBUG_LOG(LOGF_Refclock, "filter dispersion too large disp=%.9f max=%.9f",
|
||||||
|
sqrt(var), sqrt(filter->max_var));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
prev_avg_var = filter->avg_var;
|
prev_avg_var = filter->avg_var;
|
||||||
|
|
||||||
/* update exponential moving average of the variance */
|
/* update exponential moving average of the variance */
|
||||||
|
|
|
@ -43,6 +43,7 @@ typedef struct {
|
||||||
double offset;
|
double offset;
|
||||||
double delay;
|
double delay;
|
||||||
double precision;
|
double precision;
|
||||||
|
double max_dispersion;
|
||||||
SRC_SelectOption sel_option;
|
SRC_SelectOption sel_option;
|
||||||
} RefclockParameters;
|
} RefclockParameters;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue