Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Person sensor #10

Merged
merged 5 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Finish API surface + cleanup
  • Loading branch information
adrianstevens committed Jan 7, 2024
commit b8a7bd2e4a8a0db964434a6060dcdd3b6efed1ce
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ public partial class PersonSensor : II2cPeripheral
/// </summary>
public int MAX_IDS_COUNT => 7;

private readonly int HEADER_LENGTH = 4;
private readonly int DATA_LENGTH = 40;
private byte[] readBuffer = default!;
private readonly byte[] readBuffer;
private readonly II2cCommunications i2cComms;


Expand All @@ -35,21 +36,75 @@ public partial class PersonSensor : II2cPeripheral
public PersonSensor(II2cBus i2cBus, byte address = 0x62)
{
i2cComms = new I2cCommunications(i2cBus, address, DATA_LENGTH);
Initialize();
readBuffer = new byte[DATA_LENGTH];
}

void Initialize()
/// <summary>
/// Sets the capture mode of the sensor
/// </summary>
/// <param name="enable">Continuous if true</param>
public void SetContinuousMode(bool enable)
{
readBuffer = new byte[DATA_LENGTH];
i2cComms.WriteRegister((byte)Commands.MODE, (byte)(enable ? 0x0 : 0x1));
}

/// <summary>
/// Reads data from the sensor
/// Sets the Person Sensor to single-shot mode for inference.
/// </summary>
private byte[] Read()
public void SetSingleShotMode()
{
i2cComms.Read(readBuffer);
return readBuffer;
i2cComms.WriteRegister((byte)Commands.SINGLE_SHOT, 0x1);
}

/// <summary>
/// Sets the debug mode for the Person Sensor.
/// </summary>
/// <param name="enable">True to enable debug mode, False to disable.</param>
public void SetDebugMode(bool enable)
{
i2cComms.WriteRegister((byte)Commands.DEBUG_MODE, (byte)(enable ? 0x1 : 0x0));
}

/// <summary>
/// Enables or disables the ID model for the Person Sensor.
/// </summary>
/// <param name="enable">True to enable the ID model, False to disable.
/// With this flag set to False, only bounding boxes are captured.</param>
public void SetEnableId(bool enable)
{
i2cComms.WriteRegister((byte)Commands.ENABLE_ID, (byte)(enable ? 0x1 : 0x0));
}

/// <summary>
/// Sets whether to persist recognized IDs even when unpowered for the Person Sensor.
/// </summary>
/// <param name="enable">True to store recognized IDs even when unpowered, False otherwise.</param>
public void SetPersistIds(bool enable)
{
i2cComms.WriteRegister((byte)Commands.PERSIST_IDS, (byte)(enable ? 0x1 : 0x0));
}

/// <summary>
/// Initiates wiping recognized IDs from storage for the Person Sensor.
/// </summary>
public void SetEraseIds()
{
i2cComms.WriteRegister((byte)Commands.ERASE_IDS, 0x1);
}

/// <summary>
/// Initiates calibration for the next identified frame as a specific person ID (0 to 7) for the Person Sensor.
/// </summary>
/// <param name="id">The person ID to calibrate.</param>
/// <exception cref="Exception">Thrown if the specified ID exceeds the maximum number of IDs.</exception>
public void SetCalibrateId(byte id)
{
if (id > MAX_IDS_COUNT)
{
throw new Exception($"ID ({id}) exceeds the maximum number of IDs ({MAX_IDS_COUNT})");
}

i2cComms.WriteRegister((byte)Commands.CALIBRATE_ID, id);
}

/// <summary>
Expand All @@ -58,8 +113,8 @@ private byte[] Read()
/// <returns>The structured sensor data.</returns>
public PersonSensorResults GetSensorData()
{
var data = Read();
return ParseSensorResults(data);
i2cComms.Read(readBuffer);
return ParseSensorResults(readBuffer);
}

/// <summary>
Expand All @@ -70,13 +125,25 @@ public PersonSensorResults GetSensorData()
public PersonSensorResults ParseSensorResults(byte[] data)
{
PersonSensorResults results = new();
results.Header = data.Take(5).ToArray();
results.NumberOfFaces = data[5];
results.Header = data.Take(HEADER_LENGTH).ToArray();

results.NumberOfFaces = (sbyte)data[HEADER_LENGTH];

if (results.NumberOfFaces < 0)
{
throw new Exception($"Number of faces detected ({results.NumberOfFaces}) is less than zero");
}

if (results.NumberOfFaces > MAX_FACE_COUNT)
{
throw new Exception($"Number of faces detected ({results.NumberOfFaces}) exceeds the maximum number of faces ({MAX_FACE_COUNT})");
}

results.FaceData = new PersonFace[MAX_FACE_COUNT];

for (int i = 0; i < MAX_FACE_COUNT; ++i)
{
var faceStartIndex = 6 + i * 8;
var faceStartIndex = i * 8 + HEADER_LENGTH + 1;
results.FaceData[i] = new PersonFace
{
BoxConfidence = data[faceStartIndex],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,42 @@
{
public partial class PersonSensor
{
/// <summary>
/// Enumeration of configuration commands for the Person Sensor.
/// </summary>
enum Commands : byte
{
/// <summary>
/// Mode configuration command. Default: 0x01 (continuous).
/// </summary>
MODE = 0x01,
/// <summary>
/// Enable/Disable ID model configuration command. Default: 0x00 (False).
/// With this flag set to False, only capture bounding boxes.
/// </summary>
ENABLE_ID = 0x02,
/// <summary>
/// Single-shot inference configuration command. Default: 0x00.
/// Trigger a single-shot inference. Only works if the sensor is in standby mode.
/// </summary>
SINGLE_SHOT = 0x03,
/// <summary>
/// Calibrate the next identified frame as person N, from 0 to 7.
/// If two frames pass with no person, this label is discarded. Default: 0x00.
/// </summary>
CALIBRATE_ID = 0x04,
/// <summary>
/// Store any recognized IDs even when unpowered configuration command. Default: 0x01 (True).
/// </summary>
PERSIST_IDS = 0x05,
/// <summary>
/// Wipe any recognized IDs from storage configuration command. Default: 0x00.
/// </summary>
ERASE_IDS = 0x06,
/// <summary>
/// Debug mode configuration command. Default: 0x01 (True).
/// Whether to enable the LED indicator on the sensor.
/// </summary>
DEBUG_MODE = 0x07,
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ public class PersonSensorResults
/// <summary>
/// Header information of the data packet.
/// </summary>
public byte[] Header { get; set; }
public byte[] Header { get; set; } = default!;

/// <summary>
/// Number of faces detected.
/// </summary>
public byte NumberOfFaces { get; set; }
public sbyte NumberOfFaces { get; set; }

/// <summary>
/// Information about detected faces.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,19 @@ public override Task Run()
var sensorData = personSensor.GetSensorData();
DisplaySensorData(sensorData);

Thread.Sleep(2000);
Thread.Sleep(1500);
}
}

private void DisplaySensorData(PersonSensorResults sensorData)
{
Console.WriteLine("********");
Console.WriteLine($"{sensorData.NumberOfFaces} faces found");
if (sensorData.NumberOfFaces == 0)
{
Console.WriteLine("No faces found");
return;
}

for (int i = 0; i < sensorData.NumberOfFaces && i < 4; ++i)
for (int i = 0; i < sensorData.NumberOfFaces; ++i)
{
var face = sensorData.FaceData[i];
Console.Write($"Face #{i}: ");
Expand Down