Adjust refclock filter parameters

Drop only about 40 percent of samples, change default length to 64,
require at least 4 samples between polls (or full filter for lengths
below 4).
This commit is contained in:
Miroslav Lichvar 2010-02-24 12:02:53 +01:00
parent 7fb0598b50
commit fc1514db04
3 changed files with 50 additions and 17 deletions

View file

@ -2287,9 +2287,11 @@ driver name and the number of the refclock are used as refid. Each
refclock has to use an unique refid.
@item filter
This option sets the length of the median filter which is used to
reduce noise. With each poll about half of the stored samples are
reduce noise. With each poll about 40 percent of the stored samples is
discarded and one final sample is calculated as average of the
remaining samples. The default is 15.
remaining samples. If the length is 4 or above, at least 4 samples
have to be collected between polls. For lengths below 4, the filter
has to be full. The default is 64.
@item rate
PPS signal frequency (in Hz). This option only controls how the
received pulses are aligned. To actually receive more than one

2
conf.c
View file

@ -448,7 +448,7 @@ parse_refclock(const char *line)
poll = 4;
dpoll = 0;
filter_length = 15;
filter_length = 64;
pps_rate = 0;
offset = 0.0;
delay = 1e-9;

View file

@ -210,9 +210,6 @@ RCL_AddRefclock(RefclockParameters *params)
inst->pps_rate = 0;
}
if (inst->driver_poll > inst->poll)
inst->driver_poll = inst->poll;
if (params->ref_id)
inst->ref_id = params->ref_id;
else {
@ -222,6 +219,22 @@ RCL_AddRefclock(RefclockParameters *params)
inst->ref_id = ref[0] << 24 | ref[1] << 16 | ref[2] << 8 | ref[3];
}
if (inst->driver->poll) {
int max_samples;
if (inst->driver_poll > inst->poll)
inst->driver_poll = inst->poll;
max_samples = 1 << (inst->poll - inst->driver_poll);
if (max_samples < params->filter_length) {
if (max_samples < 4) {
LOG(LOGS_WARN, LOGF_Refclock, "Setting filter length for %s to %d",
UTI_RefidToString(inst->ref_id), max_samples);
}
params->filter_length = max_samples;
}
}
if (inst->driver->init)
if (!inst->driver->init(inst)) {
LOG_FATAL(LOGF_Refclock, "refclock %s initialisation failed", params->driver_name);
@ -691,28 +704,46 @@ filter_select_samples(struct MedianFilter *filter)
if (filter->used < 1)
return 0;
/* for lengths below 4 require full filter,
for 4 and above require at least 4 samples */
if ((filter->length < 4 && filter->used != filter->length) ||
(filter->length >= 4 && filter->used < 4))
return 0;
selected = filter->selected;
for (i = 1, min_dispersion = filter->samples[0].dispersion; i < filter->used; i++) {
if (min_dispersion > filter->samples[i].dispersion)
min_dispersion = filter->samples[i].dispersion;
if (filter->used > 4) {
/* select samples with dispersion better than 1.5 * minimum */
for (i = 1, min_dispersion = filter->samples[0].dispersion; i < filter->used; i++) {
if (min_dispersion > filter->samples[i].dispersion)
min_dispersion = filter->samples[i].dispersion;
}
for (i = j = 0; i < filter->used; i++) {
if (filter->samples[i].dispersion <= 1.5 * min_dispersion)
selected[j++] = i;
}
} else {
j = 0;
}
/* select samples with dispersion better than 1.5 * minimum */
for (i = j = 0; i < filter->used; i++) {
if (filter->samples[i].dispersion <= 1.5 * min_dispersion)
selected[j++] = i;
}
if (j < 4) {
/* select all samples */
assert(j > 0);
for (j = 0; j < filter->used; j++)
selected[j] = j;
}
/* and sort their indices by offset */
tmp_sorted_array = filter->samples;
qsort(selected, j, sizeof (int), sample_compare);
/* select half of the samples closest to the median */
/* select 60 percent of the samples closest to the median */
if (j > 2) {
from = (j + 2) / 4;
from = j / 5;
if (from < 1)
from = 1;
to = j - from;
} else {
from = 0;