1 /*
2  * Copyright (C) 2024 The Android Open Source Project
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 
17 package com.android.ranging.generic.ranging;
18 
19 import com.android.sensor.Estimate;
20 import com.android.sensor.Status;
21 
22 import com.google.auto.value.AutoValue;
23 
24 /**
25  * Fusion data represents a fusion of data received from ranging technologies and data received from
26  * other sensors such as ArCore and IMU.
27  */
28 @AutoValue
29 public abstract class FusionData {
30 
31     /** Returns distance result from fusion in meters. */
getFusionRange()32     public abstract double getFusionRange();
33 
34     /** Returns standard dev error for distance range. */
getFusionRangeErrorStdDev()35     public abstract double getFusionRangeErrorStdDev();
36 
37     /**
38      * Returns the std dev of the error in the estimate of the beacon's position relative to the
39      * user.
40      */
getFusionEstimatedBeaconPositionErrorStdDevM()41     public abstract double getFusionEstimatedBeaconPositionErrorStdDevM();
42 
43     /** Returns bearing result from fusion in radians. */
getFusionBearing()44     public abstract double getFusionBearing();
45 
46     /** Returns standard dev error for bearing. */
getFusionBearingErrorStdDev()47     public abstract double getFusionBearingErrorStdDev();
48 
49     /** Returns the state of ArCore. */
getArCoreState()50     public abstract ArCoreState getArCoreState();
51 
52     /** Returns a builder for {@link FusionData}. */
builder()53     public static Builder builder() {
54         return new AutoValue_FusionData.Builder();
55     }
56 
57     /** Builder for {@link FusionData}. */
58     @AutoValue.Builder
59     public abstract static class Builder {
setFusionRange(double value)60         public abstract Builder setFusionRange(double value);
61 
setFusionRangeErrorStdDev(double value)62         public abstract Builder setFusionRangeErrorStdDev(double value);
63 
setFusionBearing(double value)64         public abstract Builder setFusionBearing(double value);
65 
setFusionBearingErrorStdDev(double value)66         public abstract Builder setFusionBearingErrorStdDev(double value);
67 
setFusionEstimatedBeaconPositionErrorStdDevM(double value)68         public abstract Builder setFusionEstimatedBeaconPositionErrorStdDevM(double value);
69 
setArCoreState(ArCoreState arCoreState)70         public abstract Builder setArCoreState(ArCoreState arCoreState);
71 
build()72         public abstract FusionData build();
73     }
74 
fromFusionAlgorithmEstimate(Estimate estimate)75     public static FusionData fromFusionAlgorithmEstimate(Estimate estimate) {
76         return FusionData.builder()
77                 .setFusionRange(estimate.getRangeM())
78                 .setFusionRangeErrorStdDev(estimate.getRangeErrorStdDevM())
79                 .setFusionBearing(estimate.getBearingRad())
80                 .setFusionBearingErrorStdDev(estimate.getBearingErrorStdDevRad())
81                 .setArCoreState(convertToArCoreStateFromStatus(estimate.getStatus()))
82                 .setFusionEstimatedBeaconPositionErrorStdDevM(
83                         estimate.getEstimatedBeaconPositionErrorStdDevM())
84                 .build();
85     }
86 
convertToArCoreStateFromStatus(Status status)87     private static ArCoreState convertToArCoreStateFromStatus(Status status) {
88         switch (status) {
89             case OK:
90                 return ArCoreState.OK;
91             case RECOVERING_FROM_FAILURE_DUE_TO_INSUFFICIENT_LIGHT:
92                 return ArCoreState.POOR_LIGHTNING;
93             case RECOVERING_FROM_FAILURE_DUE_TO_EXCESSIVE_MOTION:
94                 return ArCoreState.EXCESSIVE_MOTION;
95             case RECOVERING_FROM_FAILURE_DUE_TO_INSUFFICIENT_FEATURES:
96                 return ArCoreState.INSUFFICIENT_FEATURES;
97             case RECOVERING_FROM_FAILURE_DUE_TO_CAMERA_UNAVAILABILITY:
98                 return ArCoreState.CAMERA_UNAVAILABLE;
99             case ESTIMATE_NOT_AVAILABLE:
100             case RECOVERING:
101             case RECOVERING_FROM_FAILURE_DUE_TO_BAD_ODOMETRY_STATE:
102             case ODOMETRY_ERROR:
103             case BEACON_MOVING_ERROR:
104             case CONFIGURATION_ERROR:
105             case SENSOR_PERMISSION_DENIED_ERROR:
106             case UNKNOWN_ERROR:
107                 return ArCoreState.BAD_STATE;
108         }
109         return ArCoreState.BAD_STATE;
110     }
111 
112     /** State of ArCore */
113     public enum ArCoreState {
114         OK,
115         BAD_STATE,
116         POOR_LIGHTNING,
117         EXCESSIVE_MOTION,
118         INSUFFICIENT_FEATURES,
119         CAMERA_UNAVAILABLE,
120         NOT_ENABLED
121     }
122 }
123