CallbackTests, Stability, Activity, and ActivityEnable enums

This commit is contained in:
myles-parfeniuk 2024-11-17 15:01:33 -08:00
parent 6aa1548c2b
commit 6e8b983f59
8 changed files with 309 additions and 39 deletions

View File

@ -241,9 +241,9 @@ It can be used to verify some of the basic features of a BNO08x device.
<p align="right">(<a href="#readme-top">back to top</a>)</p>
### Adding Tests
Tests are implemented with the [esp-idf unity unit testing component](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/unit-tests.html).
Tests are implemented with the [unity unit testing component](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/unit-tests.html).
To add a test, create a new .cpp file, or modify one of the existing ones in `esp32_BNO08x/test/()`.
To add a test, create a new .cpp file, or modify one of the existing ones in `esp32_BNO08x/test/`.
Follow the existing test structure as an example, use the `TEST_CASE(){}` macro.
Any tests added will automatically be detected at build time.

View File

@ -69,7 +69,7 @@ class BNO08x
void enable_tap_detector(uint32_t time_between_reports);
void enable_step_counter(uint32_t time_between_reports);
void enable_stability_classifier(uint32_t time_between_reports);
void enable_activity_classifier(uint32_t time_between_reports, uint32_t activities_to_enable, uint8_t (&activity_confidence_vals)[9]);
void enable_activity_classifier(uint32_t time_between_reports, ActivityClassifierEnable activities_to_enable, uint8_t (&activity_confidence_vals)[9]);
void enable_raw_mems_gyro(uint32_t time_between_reports);
void enable_raw_mems_accelerometer(uint32_t time_between_reports);
void enable_raw_mems_magnetometer(uint32_t time_between_reports);
@ -179,8 +179,8 @@ class BNO08x
uint8_t get_tap_detector();
uint16_t get_step_count();
int8_t get_stability_classifier();
uint8_t get_activity_classifier();
Stability get_stability_classifier();
Activity get_activity_classifier();
// Metadata functions
int16_t get_Q1(uint16_t record_ID);
@ -203,18 +203,6 @@ class BNO08x
static const constexpr uint16_t FRS_RECORD_ID_ROTATION_VECTOR =
0xE30BU; ///< Rotation vector record ID, to be passed in metadata functions like get_Q1()
// Activity classifier bits
static const constexpr uint16_t ACTIVITY_CLASSIFIER_UNKNOWN_EN = (1U << 0U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_IN_VEHICLE_EN = (1U << 1U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_ON_BICYCLE_EN = (1U << 2U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_ON_FOOT_EN = (1U << 3U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_STILL_EN = (1U << 4U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_TILTING_EN = (1U << 5U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_WALKING_EN = (1U << 6U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_RUNNING_EN = (1U << 7U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_ON_STAIRS_EN = (1U << 8U);
static const constexpr uint16_t ACTIVITY_CLASSIFIER_ALL_EN = 0x1FU;
static const constexpr uint8_t TARE_AXIS_ALL = 0x07U; ///< Tare all axes (used with tare now command)
static const constexpr uint8_t TARE_AXIS_Z = 0x04U; ///< Tar yaw axis only (used with tare now command)

View File

@ -7,7 +7,6 @@
#include "stdio.h"
#include "BNO08x.hpp"
/**
* @class BNO08xTestHelper
* @brief BNO08x unit test helper class.
@ -73,8 +72,8 @@ class BNO08xTestHelper
uint16_t raw_mems_gyro_z;
uint16_t step_count;
uint8_t stability_classifier;
uint8_t activity_classifier;
Stability stability_classifier;
Activity activity_classifier;
} imu_report_data_t;
@ -602,8 +601,8 @@ class BNO08xTestHelper
test_imu->tap_detector = TEST_VAL_UINT8;
test_imu->step_count = TEST_VAL_UINT16;
test_imu->stability_classifier = TEST_VAL_UINT8;
test_imu->activity_classifier = TEST_VAL_UINT8;
test_imu->stability_classifier = static_cast<uint16_t>(Stability::UNDEFINED);
test_imu->activity_classifier = static_cast<uint16_t>(Activity::UNDEFINED);
test_imu->mems_raw_accel_X = TEST_VAL_UINT16;
test_imu->mems_raw_accel_Y = TEST_VAL_UINT16;
@ -638,7 +637,67 @@ class BNO08xTestHelper
case BNO08xAccuracy::UNDEFINED:
return "UNDEFINED";
default:
return "UNKNOWN"; // For undefined cases or future-proofing
return "INVALID";
}
};
/**
* @brief Converts Stability enum class object to string.
*
* @param stability Stability object to convert to string.
*
* @return The resulting string conversion.
*/
static const char* BNO08xStability_to_str(Stability stability)
{
switch (stability)
{
case Stability::UNKNOWN:
return "UNKNOWN";
case Stability::ON_TABLE:
return "ON TABLE";
case Stability::STATIONARY:
return "STATIONARY";
case Stability::UNDEFINED:
return "UNDEFINED";
default:
return "INVALID";
}
}
/**
* @brief Converts Activity enum class object to string.
*
* @param activity Activity object to convert to string.
*
* @return The resulting string conversion.
*/
static const char* BNO08xActivity_to_str(Activity activity)
{
switch (activity)
{
case Activity::UNKNOWN:
return "UNKNOWN";
case Activity::IN_VEHICLE:
return "IN VEHICLE";
case Activity::ON_BICYCLE:
return "ON BICYCLE";
case Activity::ON_FOOT:
return "ON FOOT";
case Activity::STILL:
return "STILL";
case Activity::TILTING:
return "TILTING";
case Activity::WALKING:
return "WALKING";
case Activity::RUNNING:
return "RUNNING";
case Activity::ON_STAIRS:
return "ON STAIRS";
case Activity::UNDEFINED:
return "UNDEFINED";
default:
return "INVALID";
}
}
};

View File

@ -13,7 +13,6 @@
#include "unity.h"
#include "BNO08xTestHelper.hpp"
/**
* @class BNO08xTestSuite
* @brief BNO08x unit test launch point class.
@ -38,6 +37,7 @@ class BNO08xTestSuite
run_init_deinit_tests(false);
run_single_report_tests(false);
run_multi_report_tests(false);
run_callback_tests(false);
UNITY_END();
}
@ -86,4 +86,19 @@ class BNO08xTestSuite
print_end_tests_banner("multi_report_tests");
}
static void run_callback_tests(bool call_unity_end_begin = true)
{
print_begin_tests_banner("run_callback_tests");
if (call_unity_end_begin)
UNITY_BEGIN();
unity_run_tests_by_tag("[CallbackTests]", false);
if (call_unity_end_begin)
UNITY_END();
print_end_tests_banner("run_callback_tests");
}
};

View File

@ -30,6 +30,45 @@ enum class BNO08xResetReason
};
using IMUResetReason = BNO08xResetReason; // legacy version compatibility
/// @brief Activity Classifier enable bits passed to enable_activity_classifier()
enum class ActivityClassifierEnable
{
UNKNOWN = (1U << 0U),
IN_VEHICLE = (1U << 1U),
ON_BICYCLE = (1U << 2U),
ON_FOOT = (1U << 3U),
STILL = (1U << 4U),
TILTING = (1U << 5U),
WALKING = (1U << 6U),
RUNNING = (1U << 7U),
ON_STAIRS = (1U << 8U),
ALL = 0x1FU
};
/// @brief Activity states returned from get_activity_classifier()
enum class Activity
{
UNKNOWN = 0, // 0 = unknown
IN_VEHICLE = 1, // 1 = in vehicle
ON_BICYCLE = 2, // 2 = on bicycle
ON_FOOT = 3, // 3 = on foot
STILL = 4, // 4 = still
TILTING = 5, // 5 = tilting
WALKING = 6, // 6 = walking
RUNNING = 7, // 7 = running
ON_STAIRS = 8, // 8 = on stairs
UNDEFINED = 9 // used for unit tests
};
/// @brief Stability states returned from get_stability_classifier()
enum class Stability
{
UNKNOWN = 0, // 0 = unknown
ON_TABLE = 1, // 1 = on table
STATIONARY = 2, // 2 = stationary
UNDEFINED = 3 // used for unit tests
};
/// @brief IMU configuration settings passed into constructor
typedef struct bno08x_config_t
{

View File

@ -2173,10 +2173,12 @@ void BNO08x::enable_stability_classifier(uint32_t time_between_reports)
* @param activity_confidence_vals Returned activity level confidences.
* @return void, nothing to return
*/
void BNO08x::enable_activity_classifier(uint32_t time_between_reports, uint32_t activities_to_enable, uint8_t (&activity_confidence_vals)[9])
void BNO08x::enable_activity_classifier(
uint32_t time_between_reports, ActivityClassifierEnable activities_to_enable, uint8_t (&activity_confidence_vals)[9])
{
activity_confidences = activity_confidence_vals; // Store pointer to array
enable_report(SENSOR_REPORT_ID_PERSONAL_ACTIVITY_CLASSIFIER, time_between_reports, EVT_GRP_RPT_ACTIVITY_CLASSIFIER_BIT, activities_to_enable);
enable_report(SENSOR_REPORT_ID_PERSONAL_ACTIVITY_CLASSIFIER, time_between_reports, EVT_GRP_RPT_ACTIVITY_CLASSIFIER_BIT,
static_cast<uint16_t>(activities_to_enable));
}
/**
@ -3301,9 +3303,9 @@ uint16_t BNO08x::get_step_count()
*
* @return The current stability (0 = unknown, 1 = on table, 2 = stationary)
*/
int8_t BNO08x::get_stability_classifier()
Stability BNO08x::get_stability_classifier()
{
return stability_classifier;
return static_cast<Stability>(stability_classifier);
}
/**
@ -3320,9 +3322,9 @@ int8_t BNO08x::get_stability_classifier()
* 7 = runnning
* 8 = on stairs
*/
uint8_t BNO08x::get_activity_classifier()
Activity BNO08x::get_activity_classifier()
{
return activity_classifier;
return static_cast<Activity>(activity_classifier);
}
/**
@ -3792,9 +3794,9 @@ void BNO08x::data_proc_task()
}
/**
* @brief Launches spi_task and data_proc_task on constructor call.
* @brief Launches spi_task and data_proc_task on constructor call.
*
* @return ESP_OK if tasks successfully created.
* @return ESP_OK if tasks successfully created.
*/
esp_err_t BNO08x::launch_tasks()
{
@ -3834,9 +3836,9 @@ esp_err_t BNO08x::launch_tasks()
}
/**
* @brief Deletes spi_task and data_proc_task safely on deconstructor call.
* @brief Deletes spi_task and data_proc_task safely on deconstructor call.
*
* @return ESP_OK if tasks successfully deleted.
* @return ESP_OK if tasks successfully deleted.
*/
esp_err_t BNO08x::kill_all_tasks()
{

167
test/CallbackTests.cpp Normal file
View File

@ -0,0 +1,167 @@
#include "unity.h"
#include "../include/BNO08xTestHelper.hpp"
TEST_CASE("BNO08x Driver Creation for [CallbackTests] Tests", "[CallbackTests]")
{
const constexpr char* TEST_TAG = "BNO08x Driver Creation for [CallbackTests] Tests";
BNO08x* imu = nullptr;
BNO08xTestHelper::print_test_msg(TEST_TAG, "Creating & initializing BNO08x driver.");
BNO08xTestHelper::create_test_imu();
imu = BNO08xTestHelper::get_test_imu();
// ensure IMU initialized successfully
TEST_ASSERT_EQUAL(true, imu->initialize());
}
TEST_CASE("Callback Receives New Data (Single Report)", "[CallbackTests]")
{
const constexpr char* TEST_TAG = "Callback Receives New Data (Single Report)";
BNO08x* imu = nullptr;
BNO08xTestHelper::imu_report_data_t report_data;
BNO08xTestHelper::imu_report_data_t prev_report_data;
const constexpr uint8_t RX_REPORT_TRIAL_CNT = 5;
const constexpr uint32_t REPORT_PERIOD = 100000UL; // 100ms
bool new_data = false;
char msg_buff[200] = {};
imu = BNO08xTestHelper::get_test_imu();
// reset all data used in report test
BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
BNO08xTestHelper::update_report_data(&report_data);
// register a callback and check for new data within it
imu->register_cb(
[&imu, &new_data, &report_data, &prev_report_data, &msg_buff]()
{
static int cb_execution_cnt = 0;
/* callback code */
cb_execution_cnt++;
// check if new data was received from enabled report(s)
BNO08xTestHelper::update_report_data(&report_data);
if (BNO08xTestHelper::accelerometer_data_is_new(&report_data, &prev_report_data))
{
new_data = true;
sprintf(msg_buff,
"Rx Data Trial %d Success: AngularAccel: aX: %.2lf accel aY: %.2lf accel aZ: "
"%.2lf Accuracy %s",
cb_execution_cnt, report_data.accel_x, report_data.accel_y, report_data.accel_z,
BNO08xTestHelper::BNO08xAccuracy_to_str(report_data.accel_accuracy));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
}
});
BNO08xTestHelper::print_test_msg(TEST_TAG, "Enabling report(s) and checking for new data through subscribed callback.");
imu->enable_accelerometer(REPORT_PERIOD);
for (int i = 0; i < RX_REPORT_TRIAL_CNT; i++)
{
if (imu->data_available())
{
// callbacks should ALWAYS execute before data_available returns true, therefore something has gone wrong if new_data is not set to true
TEST_ASSERT_EQUAL(true, new_data);
// reset all data used in report test
new_data = false;
BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
BNO08xTestHelper::update_report_data(&report_data);
}
}
BNO08xTestHelper::print_test_msg(TEST_TAG, "Test complete, disabling report(s).");
imu->disable_accelerometer();
}
TEST_CASE("Callback Receives New Data (Dual Report)", "[CallbackTests]")
{
const constexpr char* TEST_TAG = "Callback Receives New Data (Dual Report)";
BNO08x* imu = nullptr;
BNO08xTestHelper::imu_report_data_t report_data;
BNO08xTestHelper::imu_report_data_t prev_report_data;
const constexpr uint8_t ENABLED_REPORT_CNT = 2;
const constexpr uint8_t RX_REPORT_TRIAL_CNT = 2 * ENABLED_REPORT_CNT;
const constexpr uint32_t REPORT_PERIOD = 100000UL; // 100ms
bool new_data[2] = {false, false};
char msg_buff[200] = {};
imu = BNO08xTestHelper::get_test_imu();
// reset all data used in report test
BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
BNO08xTestHelper::update_report_data(&report_data);
// register a callback and check for new data within it
imu->register_cb(
[&imu, &new_data, &report_data, &prev_report_data, &msg_buff]()
{
static int cb_execution_cnt = 0;
/* callback code */
cb_execution_cnt++;
// check if new data was received from enabled report(s)
BNO08xTestHelper::update_report_data(&report_data);
if (BNO08xTestHelper::accelerometer_data_is_new(&report_data, &prev_report_data))
{
new_data[0] = true;
sprintf(msg_buff,
"Rx Data Trial %d Success: AngularAccel: aX: %.2lf accel aY: %.2lf accel aZ: "
"%.2lf Accuracy %s",
cb_execution_cnt, report_data.accel_x, report_data.accel_y, report_data.accel_z,
BNO08xTestHelper::BNO08xAccuracy_to_str(report_data.accel_accuracy));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
}
if (BNO08xTestHelper::linear_accelerometer_data_is_new(&report_data, &prev_report_data))
{
new_data[1] = true;
sprintf(msg_buff,
"Rx Data Trial %d Success: LinearAccel: laX: %.2lf laY: %.2lf laZ: "
"%.2lf Accuracy: %s",
(cb_execution_cnt + 1), report_data.lin_accel_x, report_data.lin_accel_y, report_data.lin_accel_z,
BNO08xTestHelper::BNO08xAccuracy_to_str(report_data.lin_accel_accuracy));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
}
});
BNO08xTestHelper::print_test_msg(TEST_TAG, "Enabling report(s) and checking for new data through subscribed callback.");
imu->enable_accelerometer(REPORT_PERIOD);
imu->enable_linear_accelerometer(REPORT_PERIOD);
for (int i = 0; i < RX_REPORT_TRIAL_CNT; i++)
{
if (imu->data_available())
{
// callbacks should ALWAYS execute before data_available returns true
BNO08xTestHelper::reset_all_imu_data_to_test_defaults();
BNO08xTestHelper::update_report_data(&report_data);
}
}
// check that the callback received new data for all reports after all trials have completed
TEST_ASSERT_EQUAL(true, new_data[0]);
TEST_ASSERT_EQUAL(true, new_data[1]);
BNO08xTestHelper::print_test_msg(TEST_TAG, "Test complete, disabling report(s).");
imu->disable_accelerometer();
imu->disable_linear_accelerometer();
}
TEST_CASE("BNO08x Driver Cleanup for [CallbackTests] Tests", "[CallbackTests]")
{
const constexpr char* TEST_TAG = "BNO08x Driver Cleanup for [CallbackTests] Tests";
BNO08xTestHelper::print_test_msg(TEST_TAG, "Destroying BNO08x Driver.");
BNO08xTestHelper::destroy_test_imu();
}

View File

@ -1150,7 +1150,7 @@ TEST_CASE("Enable/Disable Stability Classifier", "[SingleReportEnableDisable]")
// assert that new data from respective report has been received
TEST_ASSERT_EQUAL(true, new_data);
sprintf(msg_buff, "Rx Data Trial %d Success: StabilityClassifier: %d", (i + 1), report_data.stability_classifier);
sprintf(msg_buff, "Rx Data Trial %d Success: StabilityClassifier: %s", (i + 1), BNO08xTestHelper::BNO08xStability_to_str(report_data.stability_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
@ -1180,7 +1180,7 @@ TEST_CASE("Enable/Disable Stability Classifier", "[SingleReportEnableDisable]")
// assert that no new data from respective report has been received
TEST_ASSERT_NOT_EQUAL(true, new_data);
sprintf(msg_buff, "No Rx Data Trial %d Success: StabilityClassifierDefault: %d", (i + 1), report_data.stability_classifier);
sprintf(msg_buff, "No Rx Data Trial %d Success: StabilityClassifierDefault: %s", (i + 1), BNO08xTestHelper::BNO08xStability_to_str(report_data.stability_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
@ -1214,7 +1214,7 @@ TEST_CASE("Enable/Disable Activity Classifier", "[SingleReportEnableDisable]")
BNO08xTestHelper::print_test_msg(TEST_TAG, "Report enabled testing phase started.");
/*enable respective report to test and ensure it reports new data */
imu->enable_activity_classifier(5*REPORT_PERIOD, BNO08x::ACTIVITY_CLASSIFIER_ALL_EN, activity_confidence_vals);
imu->enable_activity_classifier(5*REPORT_PERIOD, ActivityClassifierEnable::ALL, activity_confidence_vals);
for (int i = 0; i < RX_REPORT_TRIAL_CNT; i++)
{
@ -1232,7 +1232,7 @@ TEST_CASE("Enable/Disable Activity Classifier", "[SingleReportEnableDisable]")
// assert that new data from respective report has been received
TEST_ASSERT_EQUAL(true, new_data);
sprintf(msg_buff, "Rx Data Trial %d Success: ActivityClassifier: %d", (i + 1), report_data.activity_classifier);
sprintf(msg_buff, "Rx Data Trial %d Success: ActivityClassifier: %s", (i + 1), BNO08xTestHelper::BNO08xActivity_to_str(report_data.activity_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);
@ -1262,7 +1262,7 @@ TEST_CASE("Enable/Disable Activity Classifier", "[SingleReportEnableDisable]")
// assert that no new data from respective report has been received
TEST_ASSERT_NOT_EQUAL(true, new_data);
sprintf(msg_buff, "No Rx Data Trial %d Success: ActivityClassifierDefault: %d", (i + 1), report_data.activity_classifier);
sprintf(msg_buff, "No Rx Data Trial %d Success: ActivityClassifierDefault: %s", (i + 1), BNO08xTestHelper::BNO08xActivity_to_str(report_data.activity_classifier));
BNO08xTestHelper::print_test_msg(TEST_TAG, msg_buff);