/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.ros.time;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.ros.time.RemoteUptimeClock.LocalUptimeProvider;
import java.util.concurrent.Callable;
/**
* @author damonkohler@google.com (Damon Kohler)
*/
public class RemoteUptimeClockTest {
private double localUptime;
private double remoteUptime;
private double delta;
private double drift;
private double driftSensitivity;
private double errorReductionCoefficientSensitivity;
private int latencyOutlierFilterSampleSize;
private double latencyOutlierFilterThreshold;
@Before
public void setup() {
localUptime = 0;
remoteUptime = 0;
}
private RemoteUptimeClock newRemoteUptimeClock() {
RemoteUptimeClock remoteUptimeClock =
new RemoteUptimeClock(new LocalUptimeProvider() {
@Override
public double getSeconds() {
moveTimeForward(delta, drift);
return localUptime;
}
}, new Callable<Double>() {
@Override
public Double call() throws Exception {
return remoteUptime;
}
}, driftSensitivity, errorReductionCoefficientSensitivity, latencyOutlierFilterSampleSize,
latencyOutlierFilterThreshold);
return remoteUptimeClock;
}
private void moveTimeForward(double delta, double drift) {
localUptime += delta;
remoteUptime += delta / drift;
}
@Test
public void testUnityDrift() throws Exception {
delta = 7;
drift = 1;
driftSensitivity = 1;
errorReductionCoefficientSensitivity = 1;
latencyOutlierFilterSampleSize = 1;
latencyOutlierFilterThreshold = 1.5;
RemoteUptimeClock remoteUptimeClock = newRemoteUptimeClock();
remoteUptimeClock.calibrate(10, 0);
for (int i = 0; i < 10000; i++) {
remoteUptimeClock.update();
assertEquals(1, remoteUptimeClock.getDrift(), 1e-6);
}
assertEquals(0, remoteUptimeClock.getErrorReductionCoefficient(), 1e-9);
}
@Test
public void testDrift() throws Exception {
delta = 31;
drift = 2;
driftSensitivity = 1;
errorReductionCoefficientSensitivity = 1;
latencyOutlierFilterSampleSize = 1;
latencyOutlierFilterThreshold = 1.5;
RemoteUptimeClock remoteUptimeClock = newRemoteUptimeClock();
remoteUptimeClock.calibrate(10, 0);
for (int i = 0; i < 10000; i++) {
remoteUptimeClock.update();
assertEquals(2, remoteUptimeClock.getDrift(), 1e-6);
}
assertEquals(0, remoteUptimeClock.getErrorReductionCoefficient(), 1e-9);
}
@Test
public void testConvergence() {
delta = 7;
drift = 2;
driftSensitivity = 1;
errorReductionCoefficientSensitivity = 1;
latencyOutlierFilterSampleSize = 1;
latencyOutlierFilterThreshold = 1.5;
RemoteUptimeClock remoteUptimeClock = newRemoteUptimeClock();
remoteUptimeClock.calibrate(10, 0);
// Remote clock jumps.
remoteUptime += 71;
// We update less often.
delta = 31;
// Calibrated drift was wrong.
drift = 6;
for (int i = 0; i < 3; i++) {
remoteUptimeClock.update();
}
assertEquals(6, remoteUptimeClock.getDrift(), 1e-6);
for (int i = 0; i < 11; i++) {
remoteUptimeClock.update();
assertEquals(6, remoteUptimeClock.getDrift(), 1e-6);
}
assertEquals(0, remoteUptimeClock.getErrorReductionCoefficient(), 1e-9);
}
@Test
public void testConvergenceSensitivity() {
delta = 7;
drift = 2;
driftSensitivity = 0.5;
errorReductionCoefficientSensitivity = 0.5;
latencyOutlierFilterSampleSize = 1;
latencyOutlierFilterThreshold = 1.5;
RemoteUptimeClock remoteUptimeClock = newRemoteUptimeClock();
remoteUptimeClock.calibrate(10, 0);
// Calibrated drift was wrong.
drift = 2.1;
for (int i = 0; i < 11; i++) {
remoteUptimeClock.update();
}
assertEquals(2.1, remoteUptimeClock.getDrift(), 1e-4);
assertEquals(0, remoteUptimeClock.getErrorReductionCoefficient(), 1e-3);
}
}