Updating Linear Acceleration sensor as per fusion sensor restructuring 38/39538/2
authorAnkur <ankur29.garg@samsung.com>
Mon, 18 May 2015 12:12:58 +0000 (17:42 +0530)
committerMu-Woong Lee <muwoong.lee@samsung.com>
Wed, 27 May 2015 14:21:23 +0000 (07:21 -0700)
Tested on rd-pq device with tizen 2.4 repo

Change-Id: I989940c47b8673e9f607c229e44188759659934f

src/linear_accel/linear_accel_sensor.cpp
src/linear_accel/linear_accel_sensor.h

index fe2d608..c967ce2 100755 (executable)
@@ -33,6 +33,8 @@
 
 #define SENSOR_NAME "LINEAR_ACCEL_SENSOR"
 #define SENSOR_TYPE_LINEAR_ACCEL       "LINEAR_ACCEL"
+#define SENSOR_TYPE_GRAVITY            "GRAVITY"
+#define SENSOR_TYPE_ORIENTATION                "ORIENTATION"
 
 #define ELEMENT_NAME                                                                                   "NAME"
 #define ELEMENT_VENDOR                                                                                 "VENDOR"
 #define ELEMENT_ACCEL_ROTATION_DIRECTION_COMPENSATION                  "ACCEL_ROTATION_DIRECTION_COMPENSATION"
 #define ELEMENT_ACCEL_SCALE                                                                            "ACCEL_SCALE"
 #define ELEMENT_LINEAR_ACCEL_SIGN_COMPENSATION                                 "LINEAR_ACCEL_SIGN_COMPENSATION"
+#define ELEMENT_ORIENTATION_DATA_UNIT                                                  "RAW_DATA_UNIT"
+#define ELEMENT_GRAVITY_SIGN_COMPENSATION                                              "GRAVITY_SIGN_COMPENSATION"
+#define ELEMENT_PITCH_ROTATION_COMPENSATION                                            "PITCH_ROTATION_COMPENSATION"
+#define ELEMENT_ROLL_ROTATION_COMPENSATION                                             "ROLL_ROTATION_COMPENSATION"
+#define ELEMENT_AZIMUTH_ROTATION_COMPENSATION                                  "AZIMUTH_ROTATION_COMPENSATION"
 
 #define INITIAL_VALUE -1
 #define GRAVITY 9.80665
+#define DEVIATION 0.1
+
+#define PI 3.141593
+#define AZIMUTH_OFFSET_DEGREES 360
+#define AZIMUTH_OFFSET_RADIANS (2 * PI)
 
 #define MS_TO_US 1000
 #define MIN_DELIVERY_DIFF_FACTOR 0.75f
@@ -55,7 +67,9 @@
 
 linear_accel_sensor::linear_accel_sensor()
 : m_accel_sensor(NULL)
-, m_gravity_sensor(NULL)
+, m_gyro_sensor(NULL)
+, m_magnetic_sensor(NULL)
+, m_fusion_sensor(NULL)
 , m_time(0)
 {
        cvirtual_sensor_config &config = cvirtual_sensor_config::get_instance();
@@ -79,6 +93,13 @@ linear_accel_sensor::linear_accel_sensor()
 
        INFO("m_raw_data_unit = %s", m_raw_data_unit.c_str());
 
+       if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ORIENTATION_DATA_UNIT, m_orientation_data_unit)) {
+               ERR("[ORIENTATION_DATA_UNIT] is empty\n");
+               throw ENXIO;
+       }
+
+       INFO("m_orientation_data_unit = %s", m_orientation_data_unit.c_str());
+
        if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_DEFAULT_SAMPLING_TIME, &m_default_sampling_time)) {
                ERR("[DEFAULT_SAMPLING_TIME] is empty\n");
                throw ENXIO;
@@ -106,6 +127,12 @@ linear_accel_sensor::linear_accel_sensor()
 
        INFO("m_accel_scale = %f", m_accel_scale);
 
+       if (!config.get(SENSOR_TYPE_GRAVITY, ELEMENT_GRAVITY_SIGN_COMPENSATION, m_gravity_sign_compensation, 3)) {
+               ERR("[GRAVITY_SIGN_COMPENSATION] is empty\n");
+               throw ENXIO;
+       }
+
+       INFO("m_gravity_sign_compensation = (%d, %d, %d)", m_gravity_sign_compensation[0], m_gravity_sign_compensation[1], m_gravity_sign_compensation[2]);
 
        if (!config.get(SENSOR_TYPE_LINEAR_ACCEL, ELEMENT_LINEAR_ACCEL_SIGN_COMPENSATION, m_linear_accel_sign_compensation, 3)) {
                ERR("[LINEAR_ACCEL_SIGN_COMPENSATION] is empty\n");
@@ -114,6 +141,27 @@ linear_accel_sensor::linear_accel_sensor()
 
        INFO("m_linear_accel_sign_compensation = (%d, %d, %d)", m_linear_accel_sign_compensation[0], m_linear_accel_sign_compensation[1], m_linear_accel_sign_compensation[2]);
 
+       if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_AZIMUTH_ROTATION_COMPENSATION, &m_azimuth_rotation_compensation)) {
+               ERR("[AZIMUTH_ROTATION_COMPENSATION] is empty\n");
+               throw ENXIO;
+       }
+
+       INFO("m_azimuth_rotation_compensation = %d", m_azimuth_rotation_compensation);
+
+       if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_PITCH_ROTATION_COMPENSATION, &m_pitch_rotation_compensation)) {
+               ERR("[PITCH_ROTATION_COMPENSATION] is empty\n");
+               throw ENXIO;
+       }
+
+       INFO("m_pitch_rotation_compensation = %d", m_pitch_rotation_compensation);
+
+       if (!config.get(SENSOR_TYPE_ORIENTATION, ELEMENT_ROLL_ROTATION_COMPENSATION, &m_roll_rotation_compensation)) {
+               ERR("[ROLL_ROTATION_COMPENSATION] is empty\n");
+               throw ENXIO;
+       }
+
+       INFO("m_roll_rotation_compensation = %d", m_roll_rotation_compensation);
+
        m_interval = m_default_sampling_time * MS_TO_US;
 
 }
@@ -125,12 +173,15 @@ linear_accel_sensor::~linear_accel_sensor()
 
 bool linear_accel_sensor::init()
 {
-       m_gravity_sensor = sensor_plugin_loader::get_instance().get_sensor(GRAVITY_SENSOR);
        m_accel_sensor = sensor_plugin_loader::get_instance().get_sensor(ACCELEROMETER_SENSOR);
+       m_gyro_sensor = sensor_plugin_loader::get_instance().get_sensor(GYROSCOPE_SENSOR);
+       m_magnetic_sensor = sensor_plugin_loader::get_instance().get_sensor(GEOMAGNETIC_SENSOR);
+
+       m_fusion_sensor = sensor_plugin_loader::get_instance().get_sensor(FUSION_SENSOR);
 
-       if (!m_accel_sensor || !m_gravity_sensor) {
-               ERR("Failed to load sensors,  accel: 0x%x, gravity: 0x%x",
-                       m_accel_sensor, m_gravity_sensor);
+       if (!m_accel_sensor || !m_gyro_sensor || !m_magnetic_sensor || !m_fusion_sensor) {
+               ERR("Failed to load sensors,  accel: 0x%x, gyro: 0x%x, mag: 0x%x, fusion: 0x%x",
+                       m_accel_sensor, m_gyro_sensor, m_magnetic_sensor, m_fusion_sensor);
                return false;
        }
 
@@ -146,13 +197,21 @@ sensor_type_t linear_accel_sensor::get_type(void)
 bool linear_accel_sensor::on_start(void)
 {
        AUTOLOCK(m_mutex);
-       m_gravity_sensor->add_client(GRAVITY_RAW_DATA_EVENT);
-       m_gravity_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
-       m_gravity_sensor->start();
-
        m_accel_sensor->add_client(ACCELEROMETER_RAW_DATA_EVENT);
        m_accel_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
        m_accel_sensor->start();
+       m_gyro_sensor->add_client(GYROSCOPE_RAW_DATA_EVENT);
+       m_gyro_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
+       m_gyro_sensor->start();
+       m_magnetic_sensor->add_client(GEOMAGNETIC_RAW_DATA_EVENT);
+       m_magnetic_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
+       m_magnetic_sensor->start();
+
+       m_fusion_sensor->register_supported_event(FUSION_EVENT);
+       m_fusion_sensor->register_supported_event(FUSION_ORIENTATION_ENABLED);
+       m_fusion_sensor->add_client(FUSION_EVENT);
+       m_fusion_sensor->add_interval((intptr_t)this, (m_interval/MS_TO_US), false);
+       m_fusion_sensor->start();
 
        activate();
        return true;
@@ -161,13 +220,21 @@ bool linear_accel_sensor::on_start(void)
 bool linear_accel_sensor::on_stop(void)
 {
        AUTOLOCK(m_mutex);
-       m_gravity_sensor->delete_client(GRAVITY_RAW_DATA_EVENT);
-       m_gravity_sensor->delete_interval((intptr_t)this, false);
-       m_gravity_sensor->stop();
-
        m_accel_sensor->delete_client(ACCELEROMETER_RAW_DATA_EVENT);
        m_accel_sensor->delete_interval((intptr_t)this, false);
        m_accel_sensor->stop();
+       m_gyro_sensor->delete_client(GYROSCOPE_RAW_DATA_EVENT);
+       m_gyro_sensor->delete_interval((intptr_t)this, false);
+       m_gyro_sensor->stop();
+       m_magnetic_sensor->delete_client(GEOMAGNETIC_RAW_DATA_EVENT);
+       m_magnetic_sensor->delete_interval((intptr_t)this, false);
+       m_magnetic_sensor->stop();
+
+       m_fusion_sensor->delete_client(FUSION_EVENT);
+       m_fusion_sensor->delete_interval((intptr_t)this, false);
+       m_fusion_sensor->unregister_supported_event(FUSION_EVENT);
+       m_fusion_sensor->unregister_supported_event(FUSION_ORIENTATION_ENABLED);
+       m_fusion_sensor->stop();
 
        deactivate();
        return true;
@@ -176,8 +243,11 @@ bool linear_accel_sensor::on_stop(void)
 bool linear_accel_sensor::add_interval(int client_id, unsigned int interval)
 {
        AUTOLOCK(m_mutex);
-       m_gravity_sensor->add_interval(client_id, interval, false);
        m_accel_sensor->add_interval(client_id, interval, false);
+       m_gyro_sensor->add_interval(client_id, interval, false);
+       m_magnetic_sensor->add_interval(client_id, interval, false);
+
+       m_fusion_sensor->add_interval(client_id, interval, false);
 
        return sensor_base::add_interval(client_id, interval, false);
 }
@@ -185,15 +255,78 @@ bool linear_accel_sensor::add_interval(int client_id, unsigned int interval)
 bool linear_accel_sensor::delete_interval(int client_id)
 {
        AUTOLOCK(m_mutex);
-       m_gravity_sensor->delete_interval(client_id, false);
        m_accel_sensor->delete_interval(client_id, false);
+       m_gyro_sensor->delete_interval(client_id, false);
+       m_magnetic_sensor->delete_interval(client_id, false);
+
+       m_fusion_sensor->delete_interval(client_id, false);
 
        return sensor_base::delete_interval(client_id, false);
 }
 
+sensor_data_t linear_accel_sensor::calculate_gravity(sensor_data_t data)
+{
+       sensor_data_t gravity_data;
+       float pitch, roll, azimuth;
+       float azimuth_offset;
+
+       quaternion<float> quat(data.values[0], data.values[1],
+                       data.values[2], data.values[3]);
+
+       euler_angles<float> euler = quat2euler(quat);
+
+       if(m_orientation_data_unit == "DEGREES") {
+               euler = rad2deg(euler);
+               azimuth_offset = AZIMUTH_OFFSET_DEGREES;
+       }
+       else {
+               azimuth_offset = AZIMUTH_OFFSET_RADIANS;
+       }
+
+       euler.m_ang.m_vec[0] *= m_pitch_rotation_compensation;
+       euler.m_ang.m_vec[1] *= m_roll_rotation_compensation;
+       euler.m_ang.m_vec[2] *= m_azimuth_rotation_compensation;
+
+       pitch = euler.m_ang.m_vec[0];
+       roll = euler.m_ang.m_vec[1];
+       if (euler.m_ang.m_vec[2] >= 0)
+               azimuth = euler.m_ang.m_vec[2];
+       else
+               azimuth = euler.m_ang.m_vec[2] + azimuth_offset;
+
+       if(m_orientation_data_unit == "DEGREES") {
+               azimuth *= DEG2RAD;
+               pitch *= DEG2RAD;
+               roll *= DEG2RAD;
+       }
+
+
+       if ((roll >= (M_PI/2)-DEVIATION && roll <= (M_PI/2)+DEVIATION) ||
+                       (roll >= -(M_PI/2)-DEVIATION && roll <= -(M_PI/2)+DEVIATION)) {
+               gravity_data.values[0] = m_gravity_sign_compensation[0] * GRAVITY * sin(roll) * cos(azimuth);
+               gravity_data.values[1] = m_gravity_sign_compensation[1] * GRAVITY * sin(azimuth);
+               gravity_data.values[2] = m_gravity_sign_compensation[2] * GRAVITY * cos(roll);
+       } else if ((pitch >= (M_PI/2)-DEVIATION && pitch <= (M_PI/2)+DEVIATION) ||
+                       (pitch >= -(M_PI/2)-DEVIATION && pitch <= -(M_PI/2)+DEVIATION)) {
+               gravity_data.values[0] = m_gravity_sign_compensation[0] * GRAVITY * sin(azimuth);
+               gravity_data.values[1] = m_gravity_sign_compensation[1] * GRAVITY * sin(pitch) * cos(azimuth);
+               gravity_data.values[2] = m_gravity_sign_compensation[2] * GRAVITY * cos(pitch);
+       } else {
+               gravity_data.values[0] = m_gravity_sign_compensation[0] * GRAVITY * sin(roll);
+               gravity_data.values[1] = m_gravity_sign_compensation[1] * GRAVITY * sin(pitch);
+               gravity_data.values[2] = m_gravity_sign_compensation[2] * GRAVITY * cos(roll) * cos(pitch);
+       }
+       gravity_data.value_count = 3;
+       gravity_data.timestamp = m_time;
+       gravity_data.accuracy = SENSOR_ACCURACY_GOOD;
+
+       return gravity_data;
+}
+
 void linear_accel_sensor::synthesize(const sensor_event_t &event, vector<sensor_event_t> &outs)
 {
        sensor_event_t lin_accel_event;
+       sensor_data_t gravity_data;
 
        unsigned long long diff_time;
 
@@ -211,17 +344,13 @@ void linear_accel_sensor::synthesize(const sensor_event_t &event, vector<sensor_
 
                m_enable_linear_accel |= ACCELEROMETER_ENABLED;
        }
-       else if (event.event_type == GRAVITY_RAW_DATA_EVENT) {
+       else if (event.event_type == FUSION_EVENT) {
                diff_time = event.data.timestamp - m_time;
 
                if (m_time && (diff_time < m_interval * MIN_DELIVERY_DIFF_FACTOR))
                        return;
 
-               m_gravity.m_data.m_vec[0] = event.data.values[0];
-               m_gravity.m_data.m_vec[1] = event.data.values[1];
-               m_gravity.m_data.m_vec[2] = event.data.values[2];
-
-               m_gravity.m_time_stamp = event.data.timestamp;
+               gravity_data = calculate_gravity(event.data);
 
                m_enable_linear_accel |= GRAVITY_ENABLED;
        }
@@ -235,9 +364,9 @@ void linear_accel_sensor::synthesize(const sensor_event_t &event, vector<sensor_
                lin_accel_event.data.value_count = 3;
                lin_accel_event.data.timestamp = m_time;
                lin_accel_event.data.accuracy = SENSOR_ACCURACY_GOOD;
-               lin_accel_event.data.values[0] = m_linear_accel_sign_compensation[0] * (m_accel.m_data.m_vec[0] - m_gravity.m_data.m_vec[0]);
-               lin_accel_event.data.values[1] = m_linear_accel_sign_compensation[1] * (m_accel.m_data.m_vec[1] - m_gravity.m_data.m_vec[1]);
-               lin_accel_event.data.values[2] = m_linear_accel_sign_compensation[2] * (m_accel.m_data.m_vec[2] - m_gravity.m_data.m_vec[2]);
+               lin_accel_event.data.values[0] = m_linear_accel_sign_compensation[0] * (m_accel.m_data.m_vec[0] - gravity_data.values[0]);
+               lin_accel_event.data.values[1] = m_linear_accel_sign_compensation[1] * (m_accel.m_data.m_vec[1] - gravity_data.values[1]);
+               lin_accel_event.data.values[2] = m_linear_accel_sign_compensation[2] * (m_accel.m_data.m_vec[2] - gravity_data.values[2]);
                push(lin_accel_event);
        }
 
@@ -246,10 +375,12 @@ void linear_accel_sensor::synthesize(const sensor_event_t &event, vector<sensor_
 
 int linear_accel_sensor::get_sensor_data(const unsigned int event_type, sensor_data_t &data)
 {
-       sensor_data_t gravity_data, accel_data;
-       ((virtual_sensor *)m_gravity_sensor)->get_sensor_data(GRAVITY_RAW_DATA_EVENT, gravity_data);
+       sensor_data_t gravity_data, accel_data, fusion_data;
+       m_fusion_sensor->get_sensor_data(FUSION_ORIENTATION_ENABLED, fusion_data);
        m_accel_sensor->get_sensor_data(ACCELEROMETER_RAW_DATA_EVENT, accel_data);
 
+       gravity_data = calculate_gravity(fusion_data);
+
        accel_data.values[0] = m_accel_rotation_direction_compensation[0] * (accel_data.values[0] - m_accel_static_bias[0]) / m_accel_scale;
        accel_data.values[1] = m_accel_rotation_direction_compensation[1] * (accel_data.values[1] - m_accel_static_bias[1]) / m_accel_scale;
        accel_data.values[2] = m_accel_rotation_direction_compensation[2] * (accel_data.values[2] - m_accel_static_bias[2]) / m_accel_scale;
index 4ef10ab..e8f8395 100755 (executable)
@@ -41,11 +41,15 @@ public:
        bool get_properties(sensor_properties_s &properties);
 private:
        sensor_base *m_accel_sensor;
-       sensor_base *m_gravity_sensor;
-       cmutex m_value_mutex;
+       sensor_base *m_gyro_sensor;
+       sensor_base *m_magnetic_sensor;
+       sensor_base *m_fusion_sensor;
 
        sensor_data<float> m_accel;
-       sensor_data<float> m_gravity;
+       sensor_data<float> m_gyro;
+       sensor_data<float> m_magnetic;
+
+       cmutex m_value_mutex;
 
        unsigned long long m_time;
        unsigned int m_interval;
@@ -54,14 +58,20 @@ private:
 
        string m_vendor;
        string m_raw_data_unit;
+       string m_orientation_data_unit;
        int m_default_sampling_time;
        float m_accel_static_bias[3];
        int m_accel_rotation_direction_compensation[3];
        float m_accel_scale;
        int m_linear_accel_sign_compensation[3];
+       int m_gravity_sign_compensation[3];
+       int m_azimuth_rotation_compensation;
+       int m_pitch_rotation_compensation;
+       int m_roll_rotation_compensation;
 
        bool on_start(void);
        bool on_stop(void);
+       sensor_data_t calculate_gravity(sensor_data_t data);
 };
 
 #endif