View Javadoc
1   /*
2    * Copyright (C) 2020 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.navigation.inertial.calibration;
17  
18  import com.irurueta.units.Acceleration;
19  import com.irurueta.units.AccelerationConverter;
20  import com.irurueta.units.AccelerationUnit;
21  
22  import java.io.Serial;
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.List;
26  import java.util.Objects;
27  
28  /**
29   * Contains a collection of items containing body kinematics
30   * measurements ordered by the timestamp when the measurement was made.
31   * Measurements within a sequence will be made while the device is
32   * being moved.
33   * Samples between sequences will be ignored because it will be assumed
34   * that the device will be static.
35   * Hence, during static periods, only the mean accelerations will be measured.
36   * The mean accelerations during static periods will approximately match the
37   * gravity versor expressed in body coordinates.
38   *
39   * @param <T> a type of {@link TimedBodyKinematics}.
40   */
41  public class BodyKinematicsSequence<T extends TimedBodyKinematics> implements Serializable, Cloneable {
42  
43      /**
44       * Serialization version. This is used to ensure compatibility of deserialization of permanently stored serialized
45       * instances.
46       */
47      @Serial
48      private static final long serialVersionUID = 0L;
49  
50      /**
51       * List of items.
52       * If items are provided unsorted, they are reordered by timestamp on
53       * getter method.
54       */
55      private ArrayList<T> items;
56  
57      /**
58       * Contains sorted list of items.
59       * This list is kept for performance reasons to reduce the amount of
60       * required sorting.
61       */
62      private ArrayList<T> sortedItems;
63  
64      /**
65       * X-coordinate of mean specific force during the static period happening
66       * right before this sequence was measured. Expressed in meters per
67       * squared second (m/s^2).
68       */
69      private double beforeMeanFx;
70  
71      /**
72       * Y-coordinate of mean specific force during the static period happening
73       * right before this sequence was measured. Expressed in meters per
74       * squared second (m/s^2).
75       */
76      private double beforeMeanFy;
77  
78      /**
79       * Z-coordinate of mean specific force during the static period happening
80       * right before this sequence was measured. Expressed in meters per
81       * squared second (m/s^2).
82       */
83      private double beforeMeanFz;
84  
85      /**
86       * X-coordinate of mean specific force during the static period happening
87       * right after this sequence was measured. Expressed in meters per squared
88       * second (m/s^2).
89       */
90      private double afterMeanFx;
91  
92      /**
93       * Y-coordinate of mean specific force during the static period happening
94       * right after this sequence was measured. Expressed in meters per squared
95       * second (m/s^2).
96       */
97      private double afterMeanFy;
98  
99      /**
100      * Z-coordinate of mean specific force during the static period happening
101      * right after this sequence was measured. Expressed in meters per squared
102      * second (m/s^2).
103      */
104     private double afterMeanFz;
105 
106     /**
107      * Constructor.
108      */
109     public BodyKinematicsSequence() {
110     }
111 
112     /**
113      * Constructor.
114      *
115      * @param items list of items containing body kinematics to be kept into
116      *              this sequence.
117      */
118     public BodyKinematicsSequence(final List<T> items) {
119         setItems(items);
120     }
121 
122     /**
123      * Constructor.
124      *
125      * @param beforeMeanFx x-coordinate of mean specific force during the static
126      *                     period happening right before this sequence was measured.
127      *                     Expressed in meters per squared second (m/s^2).
128      * @param beforeMeanFy y-coordinate of mean specific force during the static
129      *                     period happening right before this sequence was measured.
130      *                     Expressed in meters per squared second (m/s^2).
131      * @param beforeMeanFz z-coordinate of mean specific force during the static
132      *                     period happening right before this sequence was measured.
133      *                     Expressed in meters per squared second (m/s^2).
134      * @param afterMeanFx  x-coordinate of mean specific force during the static
135      *                     period happening right after this sequence was measured.
136      *                     Expressed in meters per squared second (m/s^2).
137      * @param afterMeanFy  y-coordinate of mean specific force during the static
138      *                     period happening right after this sequence was measured.
139      *                     Expressed in meters per squared second (m/s^2).
140      * @param afterMeanFz  z-coordinate of mean specific force during the static
141      *                     period happening right after this sequence was measured.
142      *                     Expressed in meters per squared second (m/s^2).
143      */
144     public BodyKinematicsSequence(
145             final double beforeMeanFx, final double beforeMeanFy, final double beforeMeanFz,
146             final double afterMeanFx, final double afterMeanFy, final double afterMeanFz) {
147         setBeforeMeanSpecificForceCoordinates(beforeMeanFx, beforeMeanFy, beforeMeanFz);
148         setAfterMeanSpecificForceCoordinates(afterMeanFx, afterMeanFy, afterMeanFz);
149     }
150 
151     /**
152      * Constructor.
153      *
154      * @param beforeMeanSpecificForceX x-coordinate of mean specific force during
155      *                                 the static period happening right before this
156      *                                 sequence was measured.
157      * @param beforeMeanSpecificForceY y-coordinate of mean specific force during
158      *                                 the static period happening right before this
159      *                                 sequence was measured.
160      * @param beforeMeanSpecificForceZ z-coordinate of mean specific force during
161      *                                 the static period happening right before this
162      *                                 sequence was measured.
163      * @param afterMeanSpecificForceX  x-coordinate of mean specific force during
164      *                                 the static period happening right after this
165      *                                 sequence was measured.
166      * @param afterMeanSpecificForceY  y-coordinate of mean specific force during
167      *                                 the static period happening right after this
168      *                                 sequence was measured.
169      * @param afterMeanSpecificForceZ  z-coordinate of mean specific force during
170      *                                 the static period happening right after this
171      *                                 sequence was measured.
172      */
173     public BodyKinematicsSequence(
174             final Acceleration beforeMeanSpecificForceX,
175             final Acceleration beforeMeanSpecificForceY,
176             final Acceleration beforeMeanSpecificForceZ,
177             final Acceleration afterMeanSpecificForceX,
178             final Acceleration afterMeanSpecificForceY,
179             final Acceleration afterMeanSpecificForceZ) {
180         setBeforeMeanSpecificForceCoordinates(
181                 beforeMeanSpecificForceX, beforeMeanSpecificForceY, beforeMeanSpecificForceZ);
182         setAfterMeanSpecificForceCoordinates(
183                 afterMeanSpecificForceX, afterMeanSpecificForceY, afterMeanSpecificForceZ);
184     }
185 
186     /**
187      * @param items        list of items containing body kinematics to be kept into
188      *                     this sequence.
189      * @param beforeMeanFx x-coordinate of mean specific force during the static
190      *                     period happening right before this sequence was measured.
191      *                     Expressed in meters per squared second (m/s^2).
192      * @param beforeMeanFy y-coordinate of mean specific force during the static
193      *                     period happening right before this sequence was measured.
194      *                     Expressed in meters per squared second (m/s^2).
195      * @param beforeMeanFz z-coordinate of mean specific force during the static
196      *                     period happening right before this sequence was measured.
197      *                     Expressed in meters per squared second (m/s^2).
198      * @param afterMeanFx  x-coordinate of mean specific force during the static
199      *                     period happening right after this sequence was measured.
200      *                     Expressed in meters per squared second (m/s^2).
201      * @param afterMeanFy  y-coordinate of mean specific force during the static
202      *                     period happening right after this sequence was measured.
203      *                     Expressed in meters per squared second (m/s^2).
204      * @param afterMeanFz  z-coordinate of mean specific force during the static
205      *                     period happening right after this sequence was measured.
206      *                     Expressed in meters per squared second (m/s^2).
207      */
208     public BodyKinematicsSequence(
209             final List<T> items, final double beforeMeanFx, final double beforeMeanFy, final double beforeMeanFz,
210             final double afterMeanFx, final double afterMeanFy, final double afterMeanFz) {
211         this(items);
212         setBeforeMeanSpecificForceCoordinates(beforeMeanFx, beforeMeanFy, beforeMeanFz);
213         setAfterMeanSpecificForceCoordinates(afterMeanFx, afterMeanFy, afterMeanFz);
214     }
215 
216     /**
217      * Constructor.
218      *
219      * @param items                    list of items containing body kinematics to be kept into
220      *                                 this sequence.
221      * @param beforeMeanSpecificForceX x-coordinate of mean specific force during
222      *                                 the static period happening right before this
223      *                                 sequence was measured.
224      * @param beforeMeanSpecificForceY y-coordinate of mean specific force during
225      *                                 the static period happening right before this
226      *                                 sequence was measured.
227      * @param beforeMeanSpecificForceZ z-coordinate of mean specific force during
228      *                                 the static period happening right before this
229      *                                 sequence was measured.
230      * @param afterMeanSpecificForceX  x-coordinate of mean specific force during
231      *                                 the static period happening right after this
232      *                                 sequence was measured.
233      * @param afterMeanSpecificForceY  y-coordinate of mean specific force during
234      *                                 the static period happening right after this
235      *                                 sequence was measured.
236      * @param afterMeanSpecificForceZ  z-coordinate of mean specific force during
237      *                                 the static period happening right after this
238      *                                 sequence was measured.
239      */
240     public BodyKinematicsSequence(
241             final List<T> items,
242             final Acceleration beforeMeanSpecificForceX,
243             final Acceleration beforeMeanSpecificForceY,
244             final Acceleration beforeMeanSpecificForceZ,
245             final Acceleration afterMeanSpecificForceX,
246             final Acceleration afterMeanSpecificForceY,
247             final Acceleration afterMeanSpecificForceZ) {
248         this(items);
249         setBeforeMeanSpecificForceCoordinates(
250                 beforeMeanSpecificForceX, beforeMeanSpecificForceY, beforeMeanSpecificForceZ);
251         setAfterMeanSpecificForceCoordinates(
252                 afterMeanSpecificForceX, afterMeanSpecificForceY, afterMeanSpecificForceZ);
253     }
254 
255     /**
256      * Constructor.
257      *
258      * @param input instance to copy data from.
259      */
260     public BodyKinematicsSequence(final BodyKinematicsSequence<T> input) {
261         copyFrom(input);
262     }
263 
264     /**
265      * Gets items in this sequence ordered by ascending timestamp.
266      *
267      * @param result instance where sorted items will be stored.
268      * @return true if sorted items could be retrieved, false if no items
269      * are available.
270      */
271     public boolean getSortedItems(final List<T> result) {
272         // already sorted items are available.
273         if (sortedItems != null) {
274             result.clear();
275             result.addAll(sortedItems);
276             return true;
277         }
278 
279         if (items != null) {
280             sortedItems = new ArrayList<>(items);
281             sortedItems.sort((o1, o2) -> {
282                 final var t1 = o1.getTimestampSeconds();
283                 final var t2 = o2.getTimestampSeconds();
284                 return Double.compare(t1, t2);
285             });
286 
287             result.clear();
288             result.addAll(sortedItems);
289             return true;
290         }
291 
292         return false;
293     }
294 
295     /**
296      * Gets items in this sequence ordered by ascending timestamp.
297      *
298      * @return a new list containing sorted items or null if sorted items
299      * could not be retrieved..
300      */
301     public List<T> getSortedItems() {
302         final var result = new ArrayList<T>();
303         if (getSortedItems(result)) {
304             return result;
305         } else {
306             return null;
307         }
308     }
309 
310     /**
311      * Sets list of items containing body kinematics to be kept into this
312      * sequence.
313      *
314      * @param items items to be kept.
315      */
316     public void setItems(final List<T> items) {
317         if (items instanceof ArrayList) {
318             this.items = (ArrayList<T>) items;
319         } else {
320             this.items = new ArrayList<>(items);
321         }
322         sortedItems = null;
323     }
324 
325     /**
326      * Gets number of items in this sequence.
327      *
328      * @return number of items in this sequence.
329      */
330     public int getItemsCount() {
331         return items != null ? items.size() : 0;
332     }
333 
334     /**
335      * Gets x-coordinate of mean specific force during the static period
336      * happening right before this sequence was measured. Expressed in
337      * meters per squared second (m/s^2).
338      *
339      * @return x-coordinate of mean specific force.
340      */
341     public double getBeforeMeanFx() {
342         return beforeMeanFx;
343     }
344 
345     /**
346      * Sets x-coordinate of mean specific force during the static period
347      * happening right before this sequence was measured. Expressed in
348      * meters per squared second (m/s^2).
349      *
350      * @param beforeMeanFx x-coordinate of mean specific force.
351      */
352     public void setBeforeMeanFx(final double beforeMeanFx) {
353         this.beforeMeanFx = beforeMeanFx;
354     }
355 
356     /**
357      * Gets y-coordinate of mean specific force during the static period
358      * happening right before this sequence was measured. Expressed in
359      * meters per squared second (m/s^2).
360      *
361      * @return y-coordinate of mean specific force.
362      */
363     public double getBeforeMeanFy() {
364         return beforeMeanFy;
365     }
366 
367     /**
368      * Sets y-coordinate of mean specific force during the static period
369      * happening right before this sequence was measured. Expressed in
370      * meters per squared second (m/s^2).
371      *
372      * @param beforeMeanFy y-coordinate of mean specific force.
373      */
374     public void setBeforeMeanFy(final double beforeMeanFy) {
375         this.beforeMeanFy = beforeMeanFy;
376     }
377 
378     /**
379      * Gets z-coordinate of mean specific force during the static period
380      * happening right before this sequence was measured. Expressed in
381      * meters per squared second (m/s^2).
382      *
383      * @return z-coordinate of mean specific force.
384      */
385     public double getBeforeMeanFz() {
386         return beforeMeanFz;
387     }
388 
389     /**
390      * Sets z-coordinate of mean specific force during the static period
391      * happening right before this sequence was measured. Expressed in
392      * meters per squared second (m/s^2).
393      *
394      * @param beforeMeanFz z-coordinate of mean specific force.
395      */
396     public void setBeforeMeanFz(final double beforeMeanFz) {
397         this.beforeMeanFz = beforeMeanFz;
398     }
399 
400     /**
401      * Sets coordinates of mean specific force during the static period
402      * happening right before this sequence was measured. Expressed in
403      * meters per squared second (m/s^2).
404      *
405      * @param beforeMeanFx x-coordinate of mean specific force.
406      * @param beforeMeanFy y-coordinate of mean specific force.
407      * @param beforeMeanFz z-coordinate of mean specific force.
408      */
409     public void setBeforeMeanSpecificForceCoordinates(
410             final double beforeMeanFx, final double beforeMeanFy, final double beforeMeanFz) {
411         this.beforeMeanFx = beforeMeanFx;
412         this.beforeMeanFy = beforeMeanFy;
413         this.beforeMeanFz = beforeMeanFz;
414     }
415 
416     /**
417      * Gets x-coordinate of mean specific force during the static period
418      * happening right before this sequence was measured.
419      *
420      * @param result x-coordinate of mean specific force.
421      */
422     public void getBeforeMeanSpecificForceX(final Acceleration result) {
423         result.setValue(beforeMeanFx);
424         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
425     }
426 
427     /**
428      * Gets x-coordinate of mean specific force during the static period
429      * happening right before this sequence was measured.
430      *
431      * @return x-coordinate of mean specific force.
432      */
433     public Acceleration getBeforeMeanSpecificForceX() {
434         return new Acceleration(beforeMeanFx, AccelerationUnit.METERS_PER_SQUARED_SECOND);
435     }
436 
437     /**
438      * Sets x-coordinate of mean specific force during the static period
439      * happening right before this sequence was measured.
440      *
441      * @param beforeMeanSpecificForceX x-coordinate of mean specific force.
442      */
443     public void setBeforeMeanSpecificForceX(final Acceleration beforeMeanSpecificForceX) {
444         beforeMeanFx = convertAcceleration(beforeMeanSpecificForceX);
445     }
446 
447     /**
448      * Gets y-coordinate of mean specific force during the static period
449      * happening right before this sequence was measured.
450      *
451      * @param result y-coordinate of mean specific force.
452      */
453     public void getBeforeMeanSpecificForceY(final Acceleration result) {
454         result.setValue(beforeMeanFy);
455         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
456     }
457 
458     /**
459      * Gets y-coordinate of mean specific force during the static period
460      * happening right before this sequence was measured.
461      *
462      * @return y-coordinate of mean specific force.
463      */
464     public Acceleration getBeforeMeanSpecificForceY() {
465         return new Acceleration(beforeMeanFy, AccelerationUnit.METERS_PER_SQUARED_SECOND);
466     }
467 
468     /**
469      * Sets y-coordinate of mean specific force during the static period
470      * happening right before this sequence was measured.
471      *
472      * @param beforeMeanSpecificForceY y-coordinate of mean specific force.
473      */
474     public void setBeforeMeanSpecificForceY(final Acceleration beforeMeanSpecificForceY) {
475         beforeMeanFy = convertAcceleration(beforeMeanSpecificForceY);
476     }
477 
478     /**
479      * Gets z-coordinate of mean specific force during the static period
480      * happening right before this sequence was measured.
481      *
482      * @param result z-coordinate of mean specific force.
483      */
484     public void getBeforeMeanSpecificForceZ(final Acceleration result) {
485         result.setValue(beforeMeanFz);
486         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
487     }
488 
489     /**
490      * Gets z-coordinate of mean specific force during the static period
491      * happening right before this sequence was measured.
492      *
493      * @return z-coordinate of mean specific force.
494      */
495     public Acceleration getBeforeMeanSpecificForceZ() {
496         return new Acceleration(beforeMeanFz, AccelerationUnit.METERS_PER_SQUARED_SECOND);
497     }
498 
499     /**
500      * Sets z-coordinate of mean specific force during the static period
501      * happening right before this sequence was measured.
502      *
503      * @param beforeMeanSpecificForceZ z-coordinate of mean specific force.
504      */
505     public void setBeforeMeanSpecificForceZ(final Acceleration beforeMeanSpecificForceZ) {
506         beforeMeanFz = convertAcceleration(beforeMeanSpecificForceZ);
507     }
508 
509     /**
510      * Sets coordinates of mean specific force during the static period
511      * happening right before this sequence was measured.
512      *
513      * @param beforeMeanSpecificForceX x-coordinate of mean specific force.
514      * @param beforeMeanSpecificForceY y-coordinate of mean specific force.
515      * @param beforeMeanSpecificForceZ z-coordinate of mean specific force.
516      */
517     public void setBeforeMeanSpecificForceCoordinates(
518             final Acceleration beforeMeanSpecificForceX, final Acceleration beforeMeanSpecificForceY,
519             final Acceleration beforeMeanSpecificForceZ) {
520         setBeforeMeanSpecificForceX(beforeMeanSpecificForceX);
521         setBeforeMeanSpecificForceY(beforeMeanSpecificForceY);
522         setBeforeMeanSpecificForceZ(beforeMeanSpecificForceZ);
523     }
524 
525     /**
526      * Gets x-coordinate of mean specific force during the static period
527      * happening right after this sequence was measured. Expressed in
528      * meters per squared second (m/s^2).
529      *
530      * @return x-coordinate of mean specific force.
531      */
532     public double getAfterMeanFx() {
533         return afterMeanFx;
534     }
535 
536     /**
537      * Sets x-coordinate of mean specific force during the static period
538      * happening right after this sequence was measured. Expressed in
539      * meters per squared second (m/s^2).
540      *
541      * @param afterMeanFx x-coordinate of mean specific force.
542      */
543     public void setAfterMeanFx(final double afterMeanFx) {
544         this.afterMeanFx = afterMeanFx;
545     }
546 
547     /**
548      * Gets y-coordinate of mean specific force during the static period
549      * happening right after this sequence was measured. Expressed in
550      * meters per squared second (m/s^2).
551      *
552      * @return y-coordinate of mean specific force.
553      */
554     public double getAfterMeanFy() {
555         return afterMeanFy;
556     }
557 
558     /**
559      * Sets y-coordinate of mean specific force during the static period
560      * happening right after this sequence was measured. Expressed in
561      * meters per squared second (m/s^2).
562      *
563      * @param afterMeanFy y-coordinate of mean specific force.
564      */
565     public void setAfterMeanFy(final double afterMeanFy) {
566         this.afterMeanFy = afterMeanFy;
567     }
568 
569     /**
570      * Gets z-coordinate of mean specific force during the static period
571      * happening right after this sequence was measured. Expressed in
572      * meters per squared second (m/s^2).
573      *
574      * @return z-coordinate of mean specific force.
575      */
576     public double getAfterMeanFz() {
577         return afterMeanFz;
578     }
579 
580     /**
581      * Sets z-coordinate of mean specific force during the static period
582      * happening right after this sequence was measured. Expressed in
583      * meters per squared second (m/s^2).
584      *
585      * @param afterMeanFz z-coordinate of mean specific force.
586      */
587     public void setAfterMeanFz(final double afterMeanFz) {
588         this.afterMeanFz = afterMeanFz;
589     }
590 
591     /**
592      * Sets coordinates of mean specific force during the static period
593      * happening right after this sequence was measured. Expressed in
594      * meters per squared second (m/s^2).
595      *
596      * @param afterMeanFx x-coordinate of mean specific force.
597      * @param afterMeanFy y-coordinate of mean specific force.
598      * @param afterMeanFz z-coordinate of mean specific force.
599      */
600     public void setAfterMeanSpecificForceCoordinates(
601             final double afterMeanFx, final double afterMeanFy, final double afterMeanFz) {
602         this.afterMeanFx = afterMeanFx;
603         this.afterMeanFy = afterMeanFy;
604         this.afterMeanFz = afterMeanFz;
605     }
606 
607     /**
608      * Gets x-coordinate of mean specific force during the static period
609      * happening right after this sequence was measured.
610      *
611      * @param result x-coordinate of mean specific force.
612      */
613     public void getAfterMeanSpecificForceX(final Acceleration result) {
614         result.setValue(afterMeanFx);
615         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
616     }
617 
618     /**
619      * Gets x-coordinate of mean specific force during the static period
620      * happening right after this sequence was measured.
621      *
622      * @return x-coordinate of mean specific force.
623      */
624     public Acceleration getAfterMeanSpecificForceX() {
625         return new Acceleration(afterMeanFx, AccelerationUnit.METERS_PER_SQUARED_SECOND);
626     }
627 
628     /**
629      * Sets x-coordinate of mean specific force during the static period
630      * happening right after this sequence was measured.
631      *
632      * @param afterMeanSpecificForceX x-coordinate of mean specific force.
633      */
634     public void setAfterMeanSpecificForceX(final Acceleration afterMeanSpecificForceX) {
635         afterMeanFx = convertAcceleration(afterMeanSpecificForceX);
636     }
637 
638     /**
639      * Gets y-coordinate of mean specific force during the static period
640      * happening right after this sequence was measured.
641      *
642      * @param result y-coordinate of mean specific force.
643      */
644     public void getAfterMeanSpecificForceY(final Acceleration result) {
645         result.setValue(afterMeanFy);
646         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
647     }
648 
649     /**
650      * Gets y-coordinate of mean specific force during the static period
651      * happening right after this sequence was measured.
652      *
653      * @return y-coordinate of mean specific force.
654      */
655     public Acceleration getAfterMeanSpecificForceY() {
656         return new Acceleration(afterMeanFy, AccelerationUnit.METERS_PER_SQUARED_SECOND);
657     }
658 
659     /**
660      * Sets y-coordinate of mean specific force during the static period
661      * happening right after this sequence was measured.
662      *
663      * @param afterMeanSpecificForceY y-coordinate of mean specific force.
664      */
665     public void setAfterMeanSpecificForceY(final Acceleration afterMeanSpecificForceY) {
666         afterMeanFy = convertAcceleration(afterMeanSpecificForceY);
667     }
668 
669     /**
670      * Gets z-coordinate of mean specific force during the static period
671      * happening right after this sequence was measured.
672      *
673      * @param result z-coordinate of mean specific force.
674      */
675     public void getAfterMeanSpecificForceZ(final Acceleration result) {
676         result.setValue(afterMeanFz);
677         result.setUnit(AccelerationUnit.METERS_PER_SQUARED_SECOND);
678     }
679 
680     /**
681      * Gets z-coordinate of mean specific force during the static period
682      * happening right after this sequence was measured.
683      *
684      * @return z-coordinate of mean specific force.
685      */
686     public Acceleration getAfterMeanSpecificForceZ() {
687         return new Acceleration(afterMeanFz, AccelerationUnit.METERS_PER_SQUARED_SECOND);
688     }
689 
690     /**
691      * Sets z-coordinate of mean specific force during the static period
692      * happening right after this sequence was measured.
693      *
694      * @param afterMeanSpecificForceZ z-coordinate of mean specific force.
695      */
696     public void setAfterMeanSpecificForceZ(final Acceleration afterMeanSpecificForceZ) {
697         afterMeanFz = convertAcceleration(afterMeanSpecificForceZ);
698     }
699 
700     /**
701      * Sets coordinates of mean specific force during the static period
702      * happening right after this sequence was measured.
703      *
704      * @param afterMeanSpecificForceX x-coordinate of mean specific force.
705      * @param afterMeanSpecificForceY y-coordinate of mean specific force.
706      * @param afterMeanSpecificForceZ z-coordinate of mean specific force.
707      */
708     public void setAfterMeanSpecificForceCoordinates(
709             final Acceleration afterMeanSpecificForceX, final Acceleration afterMeanSpecificForceY,
710             final Acceleration afterMeanSpecificForceZ) {
711         setAfterMeanSpecificForceX(afterMeanSpecificForceX);
712         setAfterMeanSpecificForceY(afterMeanSpecificForceY);
713         setAfterMeanSpecificForceZ(afterMeanSpecificForceZ);
714     }
715 
716     /**
717      * Copies data of provided instance into this instance.
718      *
719      * @param input instance to copy data from.
720      */
721     public void copyFrom(final BodyKinematicsSequence<T> input) {
722         if (input.items != null) {
723             items = cloneList(input.items);
724         } else {
725             items = null;
726         }
727         if (input.sortedItems != null) {
728             sortedItems = cloneList(input.sortedItems);
729         } else {
730             sortedItems = null;
731         }
732 
733         beforeMeanFx = input.beforeMeanFx;
734         beforeMeanFy = input.beforeMeanFy;
735         beforeMeanFz = input.beforeMeanFz;
736 
737         afterMeanFx = input.afterMeanFx;
738         afterMeanFy = input.afterMeanFy;
739         afterMeanFz = input.afterMeanFz;
740     }
741 
742     /**
743      * Copies this instance data into provided instance.
744      *
745      * @param output destination instance where data will be copied to.
746      */
747     public void copyTo(final BodyKinematicsSequence<T> output) {
748         output.copyFrom(this);
749     }
750 
751     /***
752      * Checks if provided instance is a BodyKinematicsSequence2 having exactly
753      * the same contents as this instance.
754      *
755      * @param o object to be compared.
756      * @return true if both objects are considered to be equal, false otherwise.
757      */
758     @Override
759     public boolean equals(Object o) {
760         if (this == o) {
761             return true;
762         }
763         if (o == null || getClass() != o.getClass()) {
764             return false;
765         }
766 
767         final var that = (BodyKinematicsSequence<?>) o;
768         return Double.compare(that.beforeMeanFx, beforeMeanFx) == 0 &&
769                 Double.compare(that.beforeMeanFy, beforeMeanFy) == 0 &&
770                 Double.compare(that.beforeMeanFz, beforeMeanFz) == 0 &&
771                 Double.compare(that.afterMeanFx, afterMeanFx) == 0 &&
772                 Double.compare(that.afterMeanFy, afterMeanFy) == 0 &&
773                 Double.compare(that.afterMeanFz, afterMeanFz) == 0 &&
774                 Objects.equals(items, that.items) &&
775                 Objects.equals(sortedItems, that.sortedItems);
776     }
777 
778     /**
779      * Computes and returns hash code for this instance. Hash codes are almost unique
780      * values that are useful for fast classification and storage of objects in collections.
781      *
782      * @return Hash code.
783      */
784     @Override
785     public int hashCode() {
786         return Objects.hash(items, sortedItems, beforeMeanFx, beforeMeanFy, beforeMeanFz,
787                 afterMeanFx, afterMeanFy, afterMeanFz);
788     }
789 
790     /**
791      * Makes a copy of this instance.
792      *
793      * @return a copy of this instance.
794      * @throws CloneNotSupportedException if clone fails for some reason.
795      */
796     @Override
797     protected Object clone() throws CloneNotSupportedException {
798         //noinspection unchecked
799         final var result = (BodyKinematicsSequence<T>) super.clone();
800         copyTo(result);
801         return result;
802     }
803 
804     /**
805      * Clones a list of {@link TimedBodyKinematics}.
806      *
807      * @param list list to be cloned.
808      * @return cloned list.
809      */
810     @SuppressWarnings("unchecked")
811     private ArrayList<T> cloneList(final List<T> list) {
812         // constructor with list only creates a new list containing the
813         // same instances as the original list.
814         // ArrayList is publicly Cloneable, so we clone it to get copies
815         // of the elements contained within.
816 
817         final var result = new ArrayList<T>();
818         for (final var item : list) {
819             if (item instanceof StandardDeviationTimedBodyKinematics) {
820                 final var newItem = new StandardDeviationTimedBodyKinematics();
821                 newItem.copyFrom(item);
822                 result.add((T) newItem);
823             } else {
824                 final var newItem = new TimedBodyKinematics(item);
825                 result.add((T) newItem);
826             }
827         }
828 
829         return result;
830     }
831 
832     /**
833      * Converts an acceleration instance into its corresponding value
834      * expressed in meters per squared second.
835      *
836      * @param acceleration an acceleration to be converted.
837      * @return converted value.
838      */
839     private static double convertAcceleration(final Acceleration acceleration) {
840         return AccelerationConverter.convert(acceleration.getValue().doubleValue(),
841                 acceleration.getUnit(), AccelerationUnit.METERS_PER_SQUARED_SECOND);
842     }
843 }