Estimation of egomotion not working (feeding reasonable data via custom CAN parser)

DRIVE OS Version: DRIVE OS version: 6.0.10

Issue Description:

Goal:

  • Feeding egomotion via a custom CAN parser (Bypasse the VehicleIO API)
  • No IMU (DW_EGOMOTION_ODOMETRY)

Problem

  • Reasonable/Plausible values for front steering angle, wheel speeds and speed ESC but all estimations of egomotion stays zero and the quality for all values contains the status INVALID (with bounds [0,0]) (see logs below) even if dwEgomotion_addVehicleIOState returns DW_SUCCESS

Details

  • I logged the values via m_vioNonSafety.speedESCTimestamp etc:
    • speedESC: ~ 1.74 m/s
    • wheel speeds: all ~ 4.8 rad/s
    • front steering angle: ~ 0 rad (makes sense, driving straight ahead)
  • status of dwEgomotion_addVehicleIOState ist always DW_SUCCESS
  • valid flags of estimation always 327
  • timestamps (dwEgomotion_getEstimationTimestamp()) plausible and monotonically increasing

Code Snippet

dwVehicleIOSafetyState m_vioSafety{};
dwVehicleIONonSafetyState m_vioNonSafety{};
dwVehicleIOActuationFeedback m_vioAct{};
...
CHECK_DW_ERROR_MSG(dwCANInterpreter_buildFromDBC(&m_aCanInterpreter, m_dbcFile_acan.c_str(), m_context), 
                        "Error:Cannot create DBC-based A-CAN message interpreter");

...
CHECK_DW_ERROR_MSG(dwCANInterpreter_consume(&msg, m_aCanInterpreter), "Consume message failed");
dwStatus status_num = dwCANInterpreter_getNumberSignals(&num, m_aCanInterpreter);

for (uint32_t i = 0; i < num; ++i) // alle Signale durchgehen
            {
                dwStatus status_name = dwCANInterpreter_getSignalName(&name, i, m_aCanInterpreter);


               if (status_name== DW_SUCCESS && status_num==DW_SUCCESS && num>0)
                {
                    dwStatus status = dwCANInterpreter_getf32(&value, &timestamp, i, m_aCanInterpreter);
                    timestamp = msg.timestamp_us; 

                    if (status != DW_SUCCESS)
                    {
                        std::cout << "Get value and timestamp of signal" << i << "failed" << std::endl;
                    }

                    if (status == DW_SUCCESS && timestamp > 0) 
                    {
                        //////////////////////////////////////////////////////////////////////////////////////////////////////
                        // Read from CAN data and fill vehicle state structs
                        //////////////////////////////////////////////////////////////////////////////////////////////////////

                        if (strcmp(name,  "ESP_21.ESP_v_Signal") == 0) // "ESP_21.ESP_v_Signal"
                        {
                            m_vioNonSafety.speedESC = value * (1000.0f/3600.0f); 
                            m_vioNonSafety.speedESCTimestamp = timestamp;

                            setSignalValid(&m_vioNonSafety.validityInfo.speedESC);
                            setSignalValid(&m_vioNonSafety.validityInfo.speedESCTimestamp);

                            m_haveSpeedESC  = true;
                        }
... // (same for m_vioNonSafety.wheelSpeed [0,1,2,3], m_vioNonSafety.wheelTicksTimestam[0,1,2,3],  m_vioNonSafety.frontSteeringAngle and  m_vioNonSafety.validityInfo.frontSteeringTimestamp)                        
                    }
                }
                
            }

            if (m_haveSteering && m_haveSpeedESC && m_haveWheelSpeeds) 

            {
                if (m_lastEgoMotionAddedTime < msg.timestamp_us)
                    {
                    dwStatus status = dwEgomotion_addVehicleIOState(&m_vioSafety, &m_vioNonSafety, &m_vioAct, m_egomotion); // In case relevant new information is contained in this state then it gets consumed, otherwise state is ignored

                    m_lastEgoMotionAddedTime = sensorEvent->timestamp_us; // ggf msg.timestamp_us
                    }
             }

Detailed logs

Logs

---- Values ----
Added vehicleio state to egomotion module: steering angle (rad): -0.0104719763621688
front steering angle (rad): -0.000707565923221409
wheel speeds (rad/s): [4.93203067779541, 4.90873908996582, 4.94367647171021, 4.92620754241943]
speed ESC (m/s): 1.76111125946045

---- Timestamps ----
Added vehicleio state times to egomotion module: steering angle timestamp: 1767810981213747
wheel speed timestamps (rad/s): [1767810981216987, 1767810981216987, 1767810981216987, 1767810981216987]
speed ESC timestamp: 1767810981207722

---- Egomotion Estimation Availability ----
Egomotion estimation available: Yes

---- Motion Model Type ----
DW_EGOMOTION_ODOMETRY

---- Validities ----
Signal Validities: DW_SUCCESS
DW_SUCCESS
DW_SUCCESS, DW_SUCCESS, DW_SUCCESS, DW_SUCCESS, DW_SUCCESS

---- Latest Egomotion Estimate ----
Egomotion estimate timestamp: 1767810981213747
timestamp_us: 1767810981213747
linearVelocity (m/s): [0, 0, 0]
linearAcceleration (m/s^2): [0, 0, 0]
angularVelocity (rad/s): [0, 0, 0]
angularAcceleration (rad/s^2): [0, 0, 0]
rotation (quat w,x,y,z): [1, 0, 0, 0]
validFlags: 327

Quality: (printed in detail)
linVel.x status=INVALID bounds=[0, 0]
linVel.y status=INVALID bounds=[0, 0]
linVel.z status=INVALID bounds=[0, 0]
angVel.x status=INVALID bounds=[0, 0]
angVel.y status=INVALID bounds=[0, 0]
angVel.z status=INVALID bounds=[0, 0]
rot.roll status=INVALID bounds=[0, 0]
rot.pitch status=INVALID bounds=[0, 0]

Code for logs
std::cout << "---- Values ----" << std::endl;
std::cout << "Added vehicleio state to egomotion module: steering angle (rad): " << m_vioSafety.steeringWheelAngle << std::endl;
std::cout << "front steering angle (rad): " << m_vioNonSafety.frontSteeringAngle  << std::endl;
std::cout << "wheel speeds (rad/s): [" << m_vioNonSafety.wheelSpeed[0] << ", " << m_vioNonSafety.wheelSpeed[1] << ", "
<< m_vioNonSafety.wheelSpeed[2] << ", " << m_vioNonSafety.wheelSpeed[3] << "]"  << std::endl;
std::cout << "speed ESC (m/s): " << m_vioNonSafety.speedESC << std::endl;
std::cout << "-----------------------------------" << std::endl; 
std::cout << "---- Timestamps ----" << std::endl;
std::cout << "Added vehicleio state times to egomotion module: steering angle timestamp: " << m_vioNonSafety.frontSteeringTimestamp << std::endl;
std::cout << "wheel speed timestamps (rad/s): [" << m_vioNonSafety.wheelTicksTimestamp[0] << ", " << m_vioNonSafety.wheelTicksTimestamp[1] << ", "
<< m_vioNonSafety.wheelTicksTimestamp[2] << ", " << m_vioNonSafety.wheelTicksTimestamp[3] << "]"  << std::endl;
std::cout << "speed ESC timestamp: " << m_vioNonSafety.speedESCTimestamp  << std::endl;
std::cout << "-----------------------------------" << std::endl;
// check if egomotion estimation is available loggen
bool estimationAvailable = false;
dwStatus estimation_status = dwEgomotion_hasEstimation(&estimationAvailable, m_egomotion);

std::cout << "---- Egomotion Estimation Availability ----" << std::endl;
if (estimation_status != DW_SUCCESS)
 {
 std::cout << "Check if egomotion estimation is available failed" << std::endl;
 }
else
 {
 std::cout << "Egomotion estimation available: " << (estimationAvailable ? "Yes" : "No") << std::endl;
 }
std::cout << "-----------------------------------" << std::endl; 
}
// check which motion model type is currently used in egomotion loggen
dwMotionModel motionModelType;
dwStatus motionmodel_status = dwEgomotion_getMotionModel(&motionModelType, m_egomotion);

std::cout << "---- Motion Model Type ----" << std::endl;
if (motionmodel_status != DW_SUCCESS)
 {
 std::cout << "Check motion model type failed" << std::endl;
 }
else
 {
 switch(motionModelType)
   {
   case DW_EGOMOTION_ODOMETRY:
   std::cout << "DW_EGOMOTION_ODOMETRY" << std::endl;
   break;
   case DW_EGOMOTION_IMU_ODOMETRY :
   std::cout << "DW_EGOMOTION_IMU_ODOMETRY" << std::endl;
   break;
   case DW_EGOMOTION_VEHICLE_MOTION_OBSERVER :
   std::cout << "DW_EGOMOTION_VEHICLE_MOTION_OBSERVER" << std::endl;
   break;
   default: break;
   }
 }
 std::cout << "-----------------------------------" << std::endl; 
}
                        
                       
std::cout << "---- Validities ----" << std::endl;
std::cout << "Signal Validities: " << dwGetStatusName(dwSignal_checkSignalValidity(m_vioSafety.validityInfo.steeringWheelAngle))  << std::endl;
std::cout << dwGetStatusName(dwSignal_checkSignalValidity(m_vioNonSafety.validityInfo.frontSteeringAngle))  << std::endl;
std::cout <<dwGetStatusName(dwSignal_checkSignalValidity(m_vioNonSafety.validityInfo.wheelSpeed[0])) << ", " << dwGetStatusName(dwSignal_checkSignalValidity(m_vioNonSafety.validityInfo.wheelSpeed[1])) << ", "
<< dwGetStatusName(dwSignal_checkSignalValidity(m_vioNonSafety.validityInfo.wheelSpeed[2]))  << ", " << dwGetStatusName(dwSignal_checkSignalValidity(m_vioNonSafety.validityInfo.wheelSpeed[3])) << ", "
<< dwGetStatusName(dwSignal_checkSignalValidity(m_vioNonSafety.validityInfo.speedESC))
<< std::endl;
std::cout << "-----------------------------------" << std::endl; 
dwEgomotionResult m_latestEgoEstimate {};
dwTime_t estimate_timestamp = 0;
dwStatus status = dwEgomotion_getEstimation(&m_latestEgoEstimate, m_egomotion);
dwStatus timestamp_status = dwEgomotion_getEstimationTimestamp(&estimate_timestamp, m_egomotion);
// Print  egomotion state estimate
if (status != DW_SUCCESS && timestamp_status != DW_SUCCESS)
  {
  std::cout << "Get latest egomotion estimate failed, status: " << dwGetStatusName(status) << std::endl;
  }
else
  {
  std::cout << "---- Latest Egomotion Estimate ----" << std::endl;
  std::cout << "Egomotion estimate timestamp: " << estimate_timestamp << std::endl;
  std::cout << " timestamp_us: " << m_latestEgoEstimate.timestamp << std::endl;
  std::cout << " linearVelocity (m/s): [" << m_latestEgoEstimate.linearVelocity[0] << ", "<< m_latestEgoEstimate.linearVelocity[1] << ", " << m_latestEgoEstimate.linearVelocity[2] << "]" << std::endl;
  std::cout << " linearAcceleration (m/s^2): [" << m_latestEgoEstimate.linearAcceleration[0] << ", "<< m_latestEgoEstimate.linearAcceleration[1] << ", " << m_latestEgoEstimate.linearAcceleration[2] << "]" << std::endl;
  std::cout << " angularVelocity (rad/s): [" << m_latestEgoEstimate.angularVelocity[0] << ", "<< m_latestEgoEstimate.angularVelocity[1] << ", " << m_latestEgoEstimate.angularVelocity[2] << "]" << std::endl;
  std::cout << " angularAcceleration (rad/s^2): [" << m_latestEgoEstimate.angularAcceleration[0] << ", "<< m_latestEgoEstimate.angularAcceleration[1] << ", " << m_latestEgoEstimate.angularAcceleration[2] << "]" << std::endl;
  std::cout << " rotation (quat w,x,y,z): [" << m_latestEgoEstimate.rotation.w << ", "<< m_latestEgoEstimate.rotation.x << ", " << m_latestEgoEstimate.rotation.y << ", "<< m_latestEgoEstimate.rotation.z << "]" << std::endl;
  std::cout << " validFlags: " << m_latestEgoEstimate.validFlags << std::endl;
  std::cout << "-----------------------------------" << std::endl; 
  std::cout << " Quality: (printed in detail)" << std::endl;
  dumpEgomotionQuality(m_latestEgoEstimate);
  std::cout << "-----------------------------------" << std::endl; 
  }

Dear @Jis ,
Thank you for logs and details. Let me check and get back to you.

Dear @SivaRamaKrishnaNV,
could you please provide any update / did you check it yet?

Is it related to Lidar Calibration: Egomotion relative transform always Identity (DW_EGOMOTION_ODOMETRY), ICP works ?

I think it is, we were able to narrow the issue down to this point (to the egomotion estimation problem). So this topic problably solves the other one. Do you have any ideas?