View Javadoc
1   /*
2    * Copyright (C) 2016 Alberto Irurueta Carro (alberto@irurueta.com)
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package com.irurueta.ar.slam;
17  
18  import com.irurueta.geometry.Quaternion;
19  
20  /**
21   * Processes data to estimate calibration for absolute orientation with constant
22   * velocity model SLAM estimator.
23   * This class must be used while gathering data for a system being kept constant
24   * (under no motion).
25   */
26  public class AbsoluteOrientationConstantVelocityModelSlamCalibrator extends
27          AbsoluteOrientationBaseSlamCalibrator<AbsoluteOrientationConstantVelocityModelSlamCalibrationData> {
28  
29      /**
30       * Last sample of angular speed along x-axis.
31       */
32      private double lastAngularSpeedX;
33  
34      /**
35       * Last sample of angular speed along y-axis.
36       */
37      private double lastAngularSpeedY;
38  
39      /**
40       * Last sample of angular speed along z-axis.
41       */
42      private double lastAngularSpeedZ;
43  
44      /**
45       * Last timestamp of a full sample expressed in nanoseconds since the epoch
46       * time.
47       */
48      private long lastTimestampNanos = -1;
49  
50      /**
51       * Last sample of absolute orientation.
52       */
53      private Quaternion lastOrientation = new Quaternion();
54  
55      /**
56       * Variation of orientation respect to last sample.
57       */
58      private final Quaternion deltaOrientation = new Quaternion();
59  
60      /**
61       * Constructor.
62       */
63      public AbsoluteOrientationConstantVelocityModelSlamCalibrator() {
64          super(AbsoluteOrientationConstantVelocityModelSlamEstimator.CONTROL_LENGTH);
65      }
66  
67      /**
68       * Resets calibrator.
69       */
70      @Override
71      public void reset() {
72          super.reset();
73          lastOrientation = new Quaternion();
74          lastAngularSpeedX = lastAngularSpeedY = lastAngularSpeedZ = 0.0;
75          lastTimestampNanos = -1;
76      }
77  
78      /**
79       * Obtains the number of state parameters in associated SLAM estimator.
80       *
81       * @return number of state parameters.
82       */
83      @Override
84      protected int getEstimatorStateLength() {
85          return AbsoluteOrientationConstantVelocityModelSlamEstimator.STATE_LENGTH;
86      }
87  
88      /**
89       * Gets a new instance containing calibration data estimated by this
90       * calibrator.
91       *
92       * @return a new calibration data instance.
93       */
94      @Override
95      public AbsoluteOrientationConstantVelocityModelSlamCalibrationData getCalibrationData() {
96          final var result = new AbsoluteOrientationConstantVelocityModelSlamCalibrationData();
97          getCalibrationData(result);
98          return result;
99      }
100 
101     /**
102      * Processes a full sample of accelerometer and gyroscope data to compute
103      * statistics such as mean and covariance of variations.
104      */
105     @SuppressWarnings("DuplicatedCode")
106     @Override
107     protected void processFullSample() {
108         if (listener != null) {
109             listener.onFullSampleReceived(this);
110         }
111 
112         final var timestamp = getMostRecentTimestampNanos();
113         if (lastTimestampNanos < 0) {
114             // first time receiving control data we cannot determine its
115             // variation
116             lastOrientation.fromQuaternion(accumulatedOrientation);
117 
118             lastAngularSpeedX = accumulatedAngularSpeedSampleX;
119             lastAngularSpeedY = accumulatedAngularSpeedSampleY;
120             lastAngularSpeedZ = accumulatedAngularSpeedSampleZ;
121 
122             lastTimestampNanos = timestamp;
123 
124             if (listener != null) {
125                 listener.onFullSampleProcessed(this);
126             }
127 
128             return;
129         }
130 
131         accumulatedOrientation.normalize();
132 
133         lastOrientation.inverse(deltaOrientation);
134         deltaOrientation.combine(accumulatedOrientation);
135         deltaOrientation.normalize();
136 
137         final var deltaAngularSpeedX = accumulatedAngularSpeedSampleX - lastAngularSpeedX;
138         final var deltaAngularSpeedY = accumulatedAngularSpeedSampleY - lastAngularSpeedY;
139         final var deltaAngularSpeedZ = accumulatedAngularSpeedSampleZ - lastAngularSpeedZ;
140         final var deltaTimestamp = (timestamp - lastTimestampNanos) * NANOS_TO_SECONDS;
141 
142         sample[0] = deltaOrientation.getA();
143         sample[1] = deltaOrientation.getB();
144         sample[2] = deltaOrientation.getC();
145         sample[3] = deltaOrientation.getD();
146         sample[4] = accumulatedAccelerationSampleX * deltaTimestamp;
147         sample[5] = accumulatedAccelerationSampleY * deltaTimestamp;
148         sample[6] = accumulatedAccelerationSampleZ * deltaTimestamp;
149         sample[7] = deltaAngularSpeedX;
150         sample[8] = deltaAngularSpeedY;
151         sample[9] = deltaAngularSpeedZ;
152         updateSample();
153 
154         lastOrientation.combine(deltaOrientation);
155         lastAngularSpeedX = accumulatedAngularSpeedSampleX;
156         lastAngularSpeedY = accumulatedAngularSpeedSampleY;
157         lastAngularSpeedZ = accumulatedAngularSpeedSampleZ;
158 
159         lastTimestampNanos = timestamp;
160 
161         if (listener != null) {
162             listener.onFullSampleProcessed(this);
163         }
164     }
165 }