80 lines
2.6 KiB
Python
80 lines
2.6 KiB
Python
"""Motion Detection example
|
|
This example shows how to use the CSI framework to connect to a FeitCSI host and
|
|
detect changes in the environment
|
|
"""
|
|
|
|
from queue import Queue
|
|
|
|
import numpy as np
|
|
import numpy.typing as npt
|
|
|
|
from where_fi.application import CSIApplication
|
|
from where_fi.collection.ingest import RealtimeCSIProducer
|
|
|
|
# Connect to a FeitCSI host
|
|
app = CSIApplication(visualise_raw=True)
|
|
|
|
|
|
# Stores historical data for each receiving antenna, for each subcarrier
|
|
historical: dict[tuple[int, int], Queue[np.complex64]] = {}
|
|
|
|
MAGN_THRESHOLD = 20
|
|
PHASE_THRESHOLD = 0.5
|
|
QUEUE_SIZE = 20
|
|
|
|
|
|
@app.on_process
|
|
def _(sample: npt.NDArray[np.complex64]) -> None:
|
|
"""
|
|
Process the CSI data and detect changes in the environment.
|
|
|
|
This function is called by the framework at a fixed interval, with the latest CSI
|
|
sample received.
|
|
|
|
It is used to detect changes in the environment caused by motion, by comparing each
|
|
entry in the matrix with a moving average
|
|
"""
|
|
change = False
|
|
for antenna in range(sample.shape[1]):
|
|
for subcarrier in range(sample.shape[0]):
|
|
# Get the current subcarrier data
|
|
current = sample[subcarrier, antenna, 0]
|
|
|
|
# Get the historical data for this antenna and subcarrier
|
|
if (antenna, subcarrier) not in historical:
|
|
historical[(antenna, subcarrier)] = Queue(maxsize=QUEUE_SIZE)
|
|
historical_data = historical[(antenna, subcarrier)]
|
|
|
|
# Calculate the average of the historical data for this antenna and
|
|
# subcarrier
|
|
mean = np.mean(historical_data.queue)
|
|
|
|
# If we have enough historical data, compare it with the current data
|
|
if historical_data.full():
|
|
historical_data.get()
|
|
|
|
# Add the current sample to the historical data
|
|
historical_data.put(current)
|
|
|
|
# Compare the current data with the historical data
|
|
if (
|
|
np.abs(mean - current) > MAGN_THRESHOLD
|
|
or np.abs(np.angle(mean) - np.angle(current)) > PHASE_THRESHOLD
|
|
):
|
|
print(
|
|
f"Change detected in antenna {antenna}, subcarrier {subcarrier}: "
|
|
f"magn: {np.abs(mean - current)}, angle: {np.abs(np.angle(mean) - np.angle(current))}"
|
|
)
|
|
change = True
|
|
if change:
|
|
print("Motion detected!")
|
|
else:
|
|
print("No motion detected!")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# Start the application
|
|
print("Starting app")
|
|
app.set_producer(RealtimeCSIProducer())
|
|
app.start()
|