-
Notifications
You must be signed in to change notification settings - Fork 1
/
sensors.py
219 lines (180 loc) · 6.98 KB
/
sensors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
"""
sensors.py contains the class representations of the ACS device's sensors.
Note that all initial values are 0.
Also, each sensor allows for spoofing. To spoof the sensor, pass a pandas
dataframe corresponding to an output CSV (with appropriate titles). The
sensor class will then not bother reading from the physical sensor and
instead return the value from the dataframe.
"""
import time
import adafruit_adxl34x
import adafruit_bno055
import adafruit_mpl3115a2
import adafruit_bmp3xx
class Accelerometer:
"""
The Accelerometer class represents the ADXL343 accelerometer.
"""
def __init__(self, i2c, spoof=None):
self.spoof = spoof
if self.spoof is not None:
self.acceleration_acce_x_gen = iter((0, *spoof["ADXL_Acceleration_X"]))
self.acceleration_acce_y_gen = iter((0, *spoof["ADXL_Acceleration_Y"]))
self.acceleration_acce_z_gen = iter((0, *spoof["ADXL_Acceleration_Z"]))
return
self.accelerometer = adafruit_adxl34x.ADXL343(i2c)
self.accelerometer.range = adafruit_adxl34x.Range.RANGE_16_G
self._acceleration_acce = (0, 0, 0)
@property
def acceleration_acce(self):
if self.spoof is not None:
return (
next(self.acceleration_acce_x_gen),
next(self.acceleration_acce_y_gen),
next(self.acceleration_acce_z_gen)
)
value = self.accelerometer.acceleration
if value[0] is not None:
self._acceleration_acce = value
return self._acceleration_acce
class Altimeter:
"""
The Altimeter class represents the MPL3115A2 altimeter.
"""
def __init__(self, i2c, zero=True, sea_level_pressure=101000, spoof=None):
self.spoof = spoof
if self.spoof is not None:
self.altitude_gen = iter((0, *spoof["Altitude"]))
return
self.altimeter = adafruit_mpl3115a2.MPL3115A2(i2c)
self._altitude = 0
if zero:
self._zero()
else:
self.altimeter.sealevel_pressure = int(sea_level_pressure)
def _zero(self):
n = 100
sea_sum = 0
for _ in range(n):
sea_sum += self.altimeter.pressure
time.sleep(0.01)
self.altimeter.sealevel_pressure = int(sea_sum * 100 / n)
@property
def altitude(self):
if self.spoof is not None:
return next(self.altitude_gen)
value = self.altimeter.altitude
if value is not None:
self._altitude = value
return self._altitude
class Altimeter_BMP390:
"""
The Altimeter class represents the BMP390 altimeter.
"""
def __init__(self, i2c, zero=True, sea_level_pressure=101000, spoof=None):
self.spoof = spoof
if self.spoof is not None:
try:
self.altitude_gen = iter((0, *spoof["BMP_Altitude"]))
except:
self.altitude_gen = iter((0, *spoof["Altitude"]))
return
self.altimeter = adafruit_bmp3xx.BMP3XX_I2C(i2c)
self.altimeter.pressure_oversampling = 4
self._altitude = 0
if zero:
self._zero()
else:
self.altimeter.sea_level_pressure = int(sea_level_pressure)
def _zero(self):
n = 100
sea_sum = 0
for _ in range(n):
sea_sum += self.altimeter.pressure
time.sleep(0.01)
self.altimeter.sea_level_pressure = int(sea_sum/n)
@property
def altitude(self):
if self.spoof is not None:
return next(self.altitude_gen)
value = self.altimeter.altitude
if value is not None:
self._altitude = value
return self._altitude
class IMU:
"""
The IMU class represents the BNO055 inertial measurement unit.
Note that after reviewing the source code of all the sensors, I
determined that the IMU is the only one capable of software failure,
which manifests in returning (None, None, None) for a reading. We
account for this by only updating the reading if value[0] is not None.
"""
def __init__(self, i2c, spoof=None):
self.spoof = spoof
if self.spoof is not None:
self.acceleration_imu_x_gen = iter((0, *spoof["IMU_Acceleration_X"]))
self.acceleration_imu_y_gen = iter((0, *spoof["IMU_Acceleration_Y"]))
self.acceleration_imu_z_gen = iter((0, *spoof["IMU_Acceleration_Z"]))
self.linacceleration_imu_x_gen = iter((0, *spoof["Linear_Acceleration_X"]))
self.linacceleration_imu_y_gen = iter((0, *spoof["Linear_Acceleration_Y"]))
self.linacceleration_imu_z_gen = iter((0, *spoof["Linear_Acceleration_Z"]))
self.eulerangle_imu_x_gen = iter((0, *spoof["Euler_Angle_X"]))
self.eulerangle_imu_y_gen = iter((0, *spoof["Euler_Angle_Y"]))
self.eulerangle_imu_z_gen = iter((0, *spoof["Euler_Angle_Z"]))
self.gravity_imu_x_gen = iter((0, *spoof["Gravity_X"]))
self.gravity_imu_y_gen = iter((0, *spoof["Gravity_Y"]))
self.gravity_imu_z_gen = iter((0, *spoof["Gravity_Z"]))
return
self.imu = adafruit_bno055.BNO055_I2C(i2c)
self._acceleration_imu = (0, 0, 0)
self._linacceleration_imu = (0, 0, 0)
self._eulerangle_imu = (0, 0, 0)
self._gravity_imu = (0, 0, 0)
@property
def acceleration_imu(self):
if self.spoof is not None:
return (
next(self.acceleration_imu_x_gen),
next(self.acceleration_imu_y_gen),
next(self.acceleration_imu_z_gen)
)
value = self.imu.acceleration
if value[0] is not None:
self._acceleration_imu = value
return self._acceleration_imu
@property
def linacceleration_imu(self):
if self.spoof is not None:
return (
next(self.linacceleration_imu_x_gen),
next(self.linacceleration_imu_y_gen),
next(self.linacceleration_imu_z_gen)
)
value = self.imu.linear_acceleration
if value[0] is not None:
self._linacceleration_imu = value
return self._linacceleration_imu
@property
def eulerangle_imu(self):
if self.spoof is not None:
return (
next(self.eulerangle_imu_x_gen),
next(self.eulerangle_imu_y_gen),
next(self.eulerangle_imu_z_gen)
)
value = self.imu.euler
if value[0] is not None:
self._eulerangle_imu = value
return self._eulerangle_imu
@property
def gravity_imu(self):
if self.spoof is not None:
return (
next(self.gravity_imu_x_gen),
next(self.gravity_imu_y_gen),
next(self.gravity_imu_z_gen)
)
value = self.imu.gravity
if value[0] is not None:
self._gravity_imu = value
return self._gravity_imu