void parse_ins_msg(void) { uint8_t offset = 0; if (xsens_id == XSENS_ReqLeverArmGpsAck_ID) { xsens_gps_arm_x = XSENS_ReqLeverArmGpsAck_x(xsens_msg_buf); xsens_gps_arm_y = XSENS_ReqLeverArmGpsAck_y(xsens_msg_buf); xsens_gps_arm_z = XSENS_ReqLeverArmGpsAck_z(xsens_msg_buf); DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x, &xsens_gps_arm_y, &xsens_gps_arm_z); } else if (xsens_id == XSENS_Error_ID) { xsens_errorcode = XSENS_Error_errorcode(xsens_msg_buf); } else if (xsens_id == XSENS_MTData2_ID) { for (offset = 0; offset < xsens_len;) { uint8_t code1 = xsens_msg_buf[offset]; uint8_t code2 = xsens_msg_buf[offset + 1]; int subpacklen = (int)xsens_msg_buf[offset + 2]; offset += 3; if (code1 == 0x10) { if (code2 == 0x10) { // UTC } else if (code2 == 0x20) { // Packet Counter } if (code2 == 0x30) { // ITOW } } else if (code1 == 0x20) { if (code2 == 0x30) { // Attitude Euler ins_phi = XSENS_DATA_Euler_roll(xsens_msg_buf, offset) * M_PI / 180; ins_theta = XSENS_DATA_Euler_pitch(xsens_msg_buf, offset) * M_PI / 180; ins_psi = XSENS_DATA_Euler_yaw(xsens_msg_buf, offset) * M_PI / 180; new_ins_attitude = 1; } } else if (code1 == 0x40) { if (code2 == 0x10) { // Delta-V ins_ax = XSENS_DATA_Acceleration_x(xsens_msg_buf, offset) * 100.0f; ins_ay = XSENS_DATA_Acceleration_y(xsens_msg_buf, offset) * 100.0f; ins_az = XSENS_DATA_Acceleration_z(xsens_msg_buf, offset) * 100.0f; } } else if (code1 == 0x80) { if (code2 == 0x20) { // Rate Of Turn ins_p = XSENS_DATA_RateOfTurn_x(xsens_msg_buf, offset) * M_PI / 180; ins_q = XSENS_DATA_RateOfTurn_y(xsens_msg_buf, offset) * M_PI / 180; ins_r = XSENS_DATA_RateOfTurn_z(xsens_msg_buf, offset) * M_PI / 180; } } else if (code1 == 0x30) { if (code2 == 0x10) { // Baro Pressure } } else if (code1 == 0xE0) { if (code2 == 0x20) { // Status Word xsens_msg_statusword = XSENS_DATA_StatusWord_status(xsens_msg_buf, offset); //gps.tow = xsens_msg_statusword; #if USE_GPS_XSENS if (bit_is_set(xsens_msg_statusword, 2) && bit_is_set(xsens_msg_statusword, 1)) { if (bit_is_set(xsens_msg_statusword, 23) && bit_is_set(xsens_msg_statusword, 24)) { gps.fix = GPS_FIX_3D; } else { gps.fix = GPS_FIX_2D; } } else { gps.fix = GPS_FIX_NONE; } #endif } } else if (code1 == 0x88) { if (code2 == 0x40) { gps.week = XSENS_DATA_GpsSol_week(xsens_msg_buf, offset); gps.num_sv = XSENS_DATA_GpsSol_numSv(xsens_msg_buf, offset); gps.pacc = XSENS_DATA_GpsSol_pAcc(xsens_msg_buf, offset); gps.sacc = XSENS_DATA_GpsSol_sAcc(xsens_msg_buf, offset); gps.pdop = XSENS_DATA_GpsSol_pDop(xsens_msg_buf, offset); } else if (code2 == 0xA0) { // SVINFO gps.tow = XSENS_XDI_GpsSvInfo_iTOW(xsens_msg_buf + offset); #if USE_GPS_XSENS gps.nb_channels = XSENS_XDI_GpsSvInfo_nch(xsens_msg_buf + offset); gps.last_3dfix_ticks = sys_time.nb_sec_rem; gps.last_3dfix_time = sys_time.nb_sec; uint8_t i; // Do not write outside buffer for (i = 0; i < Min(gps.nb_channels, GPS_NB_CHANNELS); i++) { uint8_t ch = XSENS_XDI_GpsSvInfo_chn(xsens_msg_buf + offset, i); if (ch > gps.nb_channels) { continue; } gps.svinfos[ch].svid = XSENS_XDI_GpsSvInfo_svid(xsens_msg_buf + offset, i); gps.svinfos[ch].flags = XSENS_XDI_GpsSvInfo_bitmask(xsens_msg_buf + offset, i); gps.svinfos[ch].qi = XSENS_XDI_GpsSvInfo_qi(xsens_msg_buf + offset, i); gps.svinfos[ch].cno = XSENS_XDI_GpsSvInfo_cnr(xsens_msg_buf + offset, i); } #endif } } else if (code1 == 0x50) { if (code2 == 0x10) { //gps.hmsl = XSENS_DATA_Altitude_h(xsens_msg_buf,offset)* 1000.0f; } else if (code2 == 0x20) { // Altitude Elipsoid gps.utm_pos.alt = XSENS_DATA_Altitude_h(xsens_msg_buf, offset) * 1000.0f; // Compute geoid (MSL) height float geoid_h = wgs84_ellipsoid_to_geoid(lla_f.lat, lla_f.lon); gps.hmsl = gps.utm_pos.alt - (geoid_h * 1000.0f); SetBit(gps.valid_fields, GPS_VALID_HMSL_BIT); //gps.tow = geoid_h * 1000.0f; //gps.utm_pos.alt; } else if (code2 == 0x40) { // LatLong #ifdef GPS_LED LED_TOGGLE(GPS_LED); #endif gps.last_3dfix_ticks = sys_time.nb_sec_rem; gps.last_3dfix_time = sys_time.nb_sec; gps.week = 0; // FIXME lla_f.lat = RadOfDeg(XSENS_DATA_LatLon_lat(xsens_msg_buf, offset)); lla_f.lon = RadOfDeg(XSENS_DATA_LatLon_lon(xsens_msg_buf, offset)); // Set the real UTM zone gps.utm_pos.zone = (DegOfRad(lla_f.lon) + 180) / 6 + 1; utm_f.zone = nav_utm_zone0; // convert to utm utm_of_lla_f(&utm_f, &lla_f); // copy results of utm conversion gps.utm_pos.east = utm_f.east * 100; gps.utm_pos.north = utm_f.north * 100; SetBit(gps.valid_fields, GPS_VALID_POS_UTM_BIT); gps_xsens_publish(); } } else if (code1 == 0xD0) { if (code2 == 0x10) { // Velocity ins_vx = ((INS_FORMAT)XSENS_DATA_VelocityXYZ_x(xsens_msg_buf, offset)); ins_vy = ((INS_FORMAT)XSENS_DATA_VelocityXYZ_y(xsens_msg_buf, offset)); ins_vz = ((INS_FORMAT)XSENS_DATA_VelocityXYZ_z(xsens_msg_buf, offset)); gps.ned_vel.x = ins_vx; gps.ned_vel.y = ins_vy; gps.ned_vel.z = ins_vx; SetBit(gps.valid_fields, GPS_VALID_VEL_NED_BIT); } } if (subpacklen < 0) { subpacklen = 0; } offset += subpacklen; } /* gps.pacc = XSENS_DATA_RAWGPS_hacc(xsens_msg_buf,offset) / 100; gps.sacc = XSENS_DATA_RAWGPS_sacc(xsens_msg_buf,offset) / 100; gps.pdop = 5; // FIXME Not output by XSens */ /* */ /* ins_mx = XSENS_DATA_Calibrated_magX(xsens_msg_buf,offset); ins_my = XSENS_DATA_Calibrated_magY(xsens_msg_buf,offset); ins_mz = XSENS_DATA_Calibrated_magZ(xsens_msg_buf,offset); */ /* xsens_time_stamp = XSENS_DATA_TimeStamp_ts(xsens_msg_buf,offset); #if USE_GPS_XSENS gps.tow = xsens_time_stamp; #endif */ } }
void parse_ins_msg(void) { uint8_t offset = 0; if (xsens_id == XSENS_ReqOutputModeAck_ID) { xsens_output_mode = XSENS_ReqOutputModeAck_mode(xsens_msg_buf); } else if (xsens_id == XSENS_ReqOutputSettings_ID) { xsens_output_settings = XSENS_ReqOutputSettingsAck_settings(xsens_msg_buf); } else if (xsens_id == XSENS_ReqMagneticDeclinationAck_ID) { xsens_declination = DegOfRad(XSENS_ReqMagneticDeclinationAck_declination(xsens_msg_buf)); DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x, &xsens_gps_arm_y, &xsens_gps_arm_z); } else if (xsens_id == XSENS_ReqLeverArmGpsAck_ID) { xsens_gps_arm_x = XSENS_ReqLeverArmGpsAck_x(xsens_msg_buf); xsens_gps_arm_y = XSENS_ReqLeverArmGpsAck_y(xsens_msg_buf); xsens_gps_arm_z = XSENS_ReqLeverArmGpsAck_z(xsens_msg_buf); DOWNLINK_SEND_IMU_MAG_SETTINGS(DefaultChannel, DefaultDevice, &xsens_declination, &xsens_declination, &xsens_gps_arm_x, &xsens_gps_arm_y, &xsens_gps_arm_z); } else if (xsens_id == XSENS_Error_ID) { xsens_errorcode = XSENS_Error_errorcode(xsens_msg_buf); } #if USE_GPS_XSENS else if (xsens_id == XSENS_GPSStatus_ID) { gps.nb_channels = XSENS_GPSStatus_nch(xsens_msg_buf); gps.num_sv = 0; uint8_t i; // Do not write outside buffer for (i = 0; i < Min(gps.nb_channels, GPS_NB_CHANNELS); i++) { uint8_t ch = XSENS_GPSStatus_chn(xsens_msg_buf, i); if (ch > gps.nb_channels) { continue; } gps.svinfos[ch].svid = XSENS_GPSStatus_svid(xsens_msg_buf, i); gps.svinfos[ch].flags = XSENS_GPSStatus_bitmask(xsens_msg_buf, i); gps.svinfos[ch].qi = XSENS_GPSStatus_qi(xsens_msg_buf, i); gps.svinfos[ch].cno = XSENS_GPSStatus_cnr(xsens_msg_buf, i); if (gps.svinfos[ch].flags > 0) { gps.num_sv++; } } } #endif else if (xsens_id == XSENS_MTData_ID) { /* test RAW modes else calibrated modes */ //if ((XSENS_MASK_RAWInertial(xsens_output_mode)) || (XSENS_MASK_RAWGPS(xsens_output_mode))) { if (XSENS_MASK_RAWInertial(xsens_output_mode)) { ins_p = XSENS_DATA_RAWInertial_gyrX(xsens_msg_buf, offset); ins_q = XSENS_DATA_RAWInertial_gyrY(xsens_msg_buf, offset); ins_r = XSENS_DATA_RAWInertial_gyrZ(xsens_msg_buf, offset); #if USE_IMU imu_xsens.gyro_available = TRUE; #endif offset += XSENS_DATA_RAWInertial_LENGTH; } if (XSENS_MASK_RAWGPS(xsens_output_mode)) { #if USE_GPS_XSENS_RAW_DATA && USE_GPS_XSENS gps.week = 0; // FIXME gps.tow = XSENS_DATA_RAWGPS_itow(xsens_msg_buf, offset) * 10; gps.lla_pos.lat = XSENS_DATA_RAWGPS_lat(xsens_msg_buf, offset); gps.lla_pos.lon = XSENS_DATA_RAWGPS_lon(xsens_msg_buf, offset); gps.lla_pos.alt = XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset); /* Set the real UTM zone */ gps.utm_pos.zone = (gps.lla_pos.lon / 1e7 + 180) / 6 + 1; LLA_FLOAT_OF_BFP(lla_f, gps.lla_pos); utm_f.zone = nav_utm_zone0; /* convert to utm */ utm_of_lla_f(&utm_f, &lla_f); /* copy results of utm conversion */ gps.utm_pos.east = utm_f.east * 100; gps.utm_pos.north = utm_f.north * 100; gps.utm_pos.alt = gps.lla_pos.alt; ins_x = utm_f.east; ins_y = utm_f.north; // Altitude: Xsens LLH gives ellipsoid height ins_z = -(INS_FORMAT)XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset) / 1000.; // Compute geoid (MSL) height float hmsl = wgs84_ellipsoid_to_geoid(lla_f.lat, lla_f.lon); gps.hmsl = XSENS_DATA_RAWGPS_alt(xsens_msg_buf, offset) - (hmsl * 1000.0f); ins_vx = ((INS_FORMAT)XSENS_DATA_RAWGPS_vel_n(xsens_msg_buf, offset)) / 100.; ins_vy = ((INS_FORMAT)XSENS_DATA_RAWGPS_vel_e(xsens_msg_buf, offset)) / 100.; ins_vz = ((INS_FORMAT)XSENS_DATA_RAWGPS_vel_d(xsens_msg_buf, offset)) / 100.; gps.ned_vel.x = XSENS_DATA_RAWGPS_vel_n(xsens_msg_buf, offset); gps.ned_vel.y = XSENS_DATA_RAWGPS_vel_e(xsens_msg_buf, offset); gps.ned_vel.z = XSENS_DATA_RAWGPS_vel_d(xsens_msg_buf, offset); gps.pacc = XSENS_DATA_RAWGPS_hacc(xsens_msg_buf, offset) / 100; gps.sacc = XSENS_DATA_RAWGPS_sacc(xsens_msg_buf, offset) / 100; gps.pdop = 5; // FIXME Not output by XSens gps_xsens_msg_available = TRUE; #endif offset += XSENS_DATA_RAWGPS_LENGTH; } //} else { if (XSENS_MASK_Temp(xsens_output_mode)) { offset += XSENS_DATA_Temp_LENGTH; } if (XSENS_MASK_Calibrated(xsens_output_mode)) { uint8_t l = 0; if (!XSENS_MASK_AccOut(xsens_output_settings)) { ins_ax = XSENS_DATA_Calibrated_accX(xsens_msg_buf, offset); ins_ay = XSENS_DATA_Calibrated_accY(xsens_msg_buf, offset); ins_az = XSENS_DATA_Calibrated_accZ(xsens_msg_buf, offset); #if USE_IMU imu_xsens.accel_available = TRUE; #endif l++; } if (!XSENS_MASK_GyrOut(xsens_output_settings)) { ins_p = XSENS_DATA_Calibrated_gyrX(xsens_msg_buf, offset); ins_q = XSENS_DATA_Calibrated_gyrY(xsens_msg_buf, offset); ins_r = XSENS_DATA_Calibrated_gyrZ(xsens_msg_buf, offset); #if USE_IMU imu_xsens.gyro_available = TRUE; #endif l++; } if (!XSENS_MASK_MagOut(xsens_output_settings)) { ins_mx = XSENS_DATA_Calibrated_magX(xsens_msg_buf, offset); ins_my = XSENS_DATA_Calibrated_magY(xsens_msg_buf, offset); ins_mz = XSENS_DATA_Calibrated_magZ(xsens_msg_buf, offset); #if USE_IMU imu_xsens.mag_available = TRUE; #endif l++; } offset += l * XSENS_DATA_Calibrated_LENGTH / 3; } if (XSENS_MASK_Orientation(xsens_output_mode)) { if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x00) { float q0 = XSENS_DATA_Quaternion_q0(xsens_msg_buf, offset); float q1 = XSENS_DATA_Quaternion_q1(xsens_msg_buf, offset); float q2 = XSENS_DATA_Quaternion_q2(xsens_msg_buf, offset); float q3 = XSENS_DATA_Quaternion_q3(xsens_msg_buf, offset); float dcm00 = 1.0 - 2 * (q2 * q2 + q3 * q3); float dcm01 = 2 * (q1 * q2 + q0 * q3); float dcm02 = 2 * (q1 * q3 - q0 * q2); float dcm12 = 2 * (q2 * q3 + q0 * q1); float dcm22 = 1.0 - 2 * (q1 * q1 + q2 * q2); ins_phi = atan2(dcm12, dcm22); ins_theta = -asin(dcm02); ins_psi = atan2(dcm01, dcm00); offset += XSENS_DATA_Quaternion_LENGTH; } if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x01) { ins_phi = XSENS_DATA_Euler_roll(xsens_msg_buf, offset) * M_PI / 180; ins_theta = XSENS_DATA_Euler_pitch(xsens_msg_buf, offset) * M_PI / 180; ins_psi = XSENS_DATA_Euler_yaw(xsens_msg_buf, offset) * M_PI / 180; offset += XSENS_DATA_Euler_LENGTH; } if (XSENS_MASK_OrientationMode(xsens_output_settings) == 0x10) { offset += XSENS_DATA_Matrix_LENGTH; } new_ins_attitude = 1; } if (XSENS_MASK_Auxiliary(xsens_output_mode)) { uint8_t l = 0; if (!XSENS_MASK_Aux1Out(xsens_output_settings)) { l++; } if (!XSENS_MASK_Aux2Out(xsens_output_settings)) { l++; } offset += l * XSENS_DATA_Auxiliary_LENGTH / 2; } if (XSENS_MASK_Position(xsens_output_mode)) { #if (! USE_GPS_XSENS_RAW_DATA) && USE_GPS_XSENS lla_f.lat = RadOfDeg(XSENS_DATA_Position_lat(xsens_msg_buf, offset)); lla_f.lon = RadOfDeg(XSENS_DATA_Position_lon(xsens_msg_buf, offset)); gps.lla_pos.lat = (int32_t)(DegOfRad(lla_f.lat) * 1e7); gps.lla_pos.lon = (int32_t)(DegOfRad(lla_f.lon) * 1e7); gps.utm_pos.zone = (DegOfRad(lla_f.lon) + 180) / 6 + 1; /* convert to utm */ utm_of_lla_f(&utm_f, &lla_f); /* copy results of utm conversion */ gps.utm_pos.east = utm_f.east * 100; gps.utm_pos.north = utm_f.north * 100; ins_x = utm_f.east; ins_y = utm_f.north; ins_z = XSENS_DATA_Position_alt(xsens_msg_buf, offset); //TODO is this hms or above ellipsoid? gps.hmsl = ins_z * 1000; // what about gps.lla_pos.alt and gps.utm_pos.alt ? gps_xsens_msg_available = TRUE; #endif offset += XSENS_DATA_Position_LENGTH; } if (XSENS_MASK_Velocity(xsens_output_mode)) { #if (! USE_GPS_XSENS_RAW_DATA) && USE_GPS_XSENS ins_vx = XSENS_DATA_Velocity_vx(xsens_msg_buf, offset); ins_vy = XSENS_DATA_Velocity_vy(xsens_msg_buf, offset); ins_vz = XSENS_DATA_Velocity_vz(xsens_msg_buf, offset); #endif offset += XSENS_DATA_Velocity_LENGTH; } if (XSENS_MASK_Status(xsens_output_mode)) { xsens_msg_status = XSENS_DATA_Status_status(xsens_msg_buf, offset); #if USE_GPS_XSENS if (bit_is_set(xsens_msg_status, 2)) { gps.fix = GPS_FIX_3D; } // gps fix else if (bit_is_set(xsens_msg_status, 1)) { gps.fix = 0x01; } // efk valid else { gps.fix = GPS_FIX_NONE; } #ifdef GPS_LED if (gps.fix == GPS_FIX_3D) { LED_ON(GPS_LED); } else { LED_TOGGLE(GPS_LED); } #endif // GPS_LED #endif // USE_GPS_XSENS offset += XSENS_DATA_Status_LENGTH; } if (XSENS_MASK_TimeStamp(xsens_output_settings)) { xsens_time_stamp = XSENS_DATA_TimeStamp_ts(xsens_msg_buf, offset); #if USE_GPS_XSENS gps.tow = xsens_time_stamp; #endif offset += XSENS_DATA_TimeStamp_LENGTH; } if (XSENS_MASK_UTC(xsens_output_settings)) { xsens_time.hour = XSENS_DATA_UTC_hour(xsens_msg_buf, offset); xsens_time.min = XSENS_DATA_UTC_min(xsens_msg_buf, offset); xsens_time.sec = XSENS_DATA_UTC_sec(xsens_msg_buf, offset); xsens_time.nanosec = XSENS_DATA_UTC_nanosec(xsens_msg_buf, offset); xsens_time.year = XSENS_DATA_UTC_year(xsens_msg_buf, offset); xsens_time.month = XSENS_DATA_UTC_month(xsens_msg_buf, offset); xsens_time.day = XSENS_DATA_UTC_day(xsens_msg_buf, offset); offset += XSENS_DATA_UTC_LENGTH; } //} } }