Skip to content

Commit 2803e79

Browse files
author
Tobias Haeckel
committed
update
1 parent 278c68e commit 2803e79

File tree

2 files changed

+51
-39
lines changed

2 files changed

+51
-39
lines changed

lib/APPLineFollowerSensorFusion/src/App.cpp

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ void App::ssrTopicCallback(const String& payload)
373373
hostSynced ? m_timeSync.hostToEspLocalMs(hostEpochMs)
374374
: m_timeSync.localNowMs(); /* Fallback: use local time if host is not synced */
375375

376-
LOG_INFO("SSR pose: ts_host_ms=%llu (hostSync=%s)", hostEpochMs, hostSynced ? "true" : "false");
376+
LOG_DEBUG("SSR pose: ts_host_ms=%llu (hostSync=%s)", hostEpochMs, hostSynced ? "true" : "false");
377377

378378
SpaceShipRadarPose ssrPose;
379379
ssrPose.x = static_cast<float>(x_mm_i);
@@ -383,22 +383,22 @@ void App::ssrTopicCallback(const String& payload)
383383
ssrPose.v_y = Y_SIGN * static_cast<float>(vy_mms_i);
384384
ssrPose.timestamp = static_cast<uint32_t>(ssrLocalTsMs);
385385

386-
if (false == m_odoOriginInitialized)
386+
if ((false == m_odoOriginInitialized || false == m_odoZeroInitialized) && m_hasVehicleData == true)
387387
{
388388
m_odoOriginX_mm = ssrPose.x;
389389
m_odoOriginY_mm = ssrPose.y;
390390
m_odoOriginTheta_mrad = ssrPose.theta;
391391
m_odoOriginInitialized = true;
392+
m_odoZeroX_mm = static_cast<float>(m_lastVehicleData.xPos);
393+
m_odoZeroY_mm = static_cast<float>(m_lastVehicleData.yPos);
394+
m_odoZeroTheta_mrad = static_cast<float>(m_lastVehicleData.orientation);
395+
m_odoZeroInitialized = true;
392396

393-
m_odoZeroX_mm = static_cast<float>(m_lastVehicleData.xPos);
394-
m_odoZeroY_mm = static_cast<float>(m_lastVehicleData.yPos);
395-
m_odoZeroTheta_mrad = static_cast<float>(m_lastVehicleData.orientation);
396-
m_odoZeroInitialized = true;
397-
398-
LOG_INFO("Odometry origin set from SSR: x=%dmm y=%dmm", x_mm_i, y_mm_i);
397+
LOG_INFO("Odometry origin set from SSR: x=%fmm y=%fmm, theta=%f mrad", m_odoOriginX_mm, m_odoOriginY_mm,
398+
m_odoOriginTheta_mrad);
399399
}
400400

401-
if (false == m_ekfInitializedFromSSR)
401+
if (false == m_ekfInitializedFromSSR && true == m_odoOriginInitialized && true == m_odoZeroInitialized)
402402
{
403403
StateVector x0;
404404
x0.setZero();
@@ -524,7 +524,7 @@ void App::filterLocationData(const VehicleData& vehicleData, const SpaceShipRada
524524
zumoLocalMs32 = static_cast<uint32_t>(m_timeSync.mapZumoToLocalMs(zumoTs32));
525525
ssrLocalMs32 = static_cast<uint32_t>(ssrPose.timestamp);
526526

527-
LOG_INFO("Filtering location data: Zumo=%u ms, SSR=%u ms", zumoLocalMs32, ssrLocalMs32);
527+
LOG_DEBUG("Filtering location data: Zumo=%u ms, SSR=%u ms", zumoLocalMs32, ssrLocalMs32);
528528

529529
/* Initialize EKF time on first data. */
530530
hasTimestamp = initializeEkfTimestamp(zumoLocalMs32, ssrLocalMs32);
@@ -576,7 +576,6 @@ void App::filterLocationData(const VehicleData& vehicleData, const SpaceShipRada
576576
void App::transformOdometryToGlobal(const VehicleData& vehicleData, float& xGlob_mm, float& yGlob_mm,
577577
float& thetaGlob_mrad) const
578578
{
579-
/* Fallback if origin or odometry zero is not initialized yet. */
580579
if ((false == m_odoOriginInitialized) || (false == m_odoZeroInitialized))
581580
{
582581
xGlob_mm = static_cast<float>(vehicleData.xPos);
@@ -585,44 +584,32 @@ void App::transformOdometryToGlobal(const VehicleData& vehicleData, float& xGlob
585584
return;
586585
}
587586

588-
/* Odometry delta since SSR origin was captured. */
589-
const float xLocal_mm = static_cast<float>(vehicleData.xPos) - m_odoZeroX_mm;
590-
const float yLocal_mm = static_cast<float>(vehicleData.yPos) - m_odoZeroY_mm;
591-
const float thetaLocal_mrad = static_cast<float>(vehicleData.orientation) - m_odoZeroTheta_mrad;
592-
593-
/* ------------------------------------------------------------------
594-
* 1) Fixed frame rotation between odometry frame and SSR world frame.
595-
* Only a pure +/- 90 deg rotation, no mirroring.
596-
* ------------------------------------------------------------------ */
597-
constexpr float PHI_MRAD = -M_PI / 2.0F * 1000.0F; // -pi/2 * 1000 -> -90 deg
587+
const float xLocal_raw = static_cast<float>(vehicleData.xPos) - m_odoZeroX_mm;
588+
const float yLocal_raw = static_cast<float>(vehicleData.yPos) - m_odoZeroY_mm;
598589

599-
const float phi_rad = PHI_MRAD / 1000.0F;
600-
const float cP = cosf(phi_rad);
601-
const float sP = sinf(phi_rad);
590+
// Map ODO pos to ENU (East/North)
591+
const float xLocal_mm = yLocal_raw; // East
592+
const float yLocal_mm = -xLocal_raw; // North
602593

603-
const float xPhi_mm = cP * xLocal_mm - sP * yLocal_mm;
604-
const float yPhi_mm = sP * xLocal_mm + cP * yLocal_mm;
594+
// ODO delta since SSR origin was captured
595+
const float thetaLocal_mrad = static_cast<float>(vehicleData.orientation) - m_odoZeroTheta_mrad;
605596

606-
/* ------------------------------------------------------------------
607-
* 2) Rotate by SSR origin yaw (world orientation at capture time).
608-
* ------------------------------------------------------------------ */
597+
// Rotate delta into SSR world frame using SSR yaw at capture time
609598
const float originTh_rad = m_odoOriginTheta_mrad / 1000.0F;
610599
const float c0 = cosf(originTh_rad);
611600
const float s0 = sinf(originTh_rad);
612601

613-
const float dxW_mm = c0 * xPhi_mm - s0 * yPhi_mm;
614-
const float dyW_mm = s0 * xPhi_mm + c0 * yPhi_mm;
602+
const float dxW_mm = c0 * xLocal_mm - s0 * yLocal_mm;
603+
const float dyW_mm = s0 * xLocal_mm + c0 * yLocal_mm;
615604

616-
/* ------------------------------------------------------------------
617-
* 3) Translate into SSR world frame.
618-
* ------------------------------------------------------------------ */
605+
// Translate into SSR world frame
619606
xGlob_mm = m_odoOriginX_mm + dxW_mm;
620607
yGlob_mm = m_odoOriginY_mm + dyW_mm;
621608

622-
/* ------------------------------------------------------------------
623-
* 4) Heading: origin yaw + fixed frame offset + odometry delta.
624-
* ------------------------------------------------------------------ */
625-
thetaGlob_mrad = m_odoOriginTheta_mrad + PHI_MRAD + thetaLocal_mrad;
609+
// Heading
610+
thetaGlob_mrad = m_odoOriginTheta_mrad + thetaLocal_mrad;
611+
612+
thetaGlob_mrad = wrapAngleMrad(thetaGlob_mrad);
626613
}
627614

628615
void App::publishFusionPose(uint32_t tsMs)
@@ -702,6 +689,7 @@ void App::publishGps(MqttClient& mqttClient, uint32_t tsMs)
702689
}
703690

704691
bool hasOrientation = gps->getOrientation(headingMrad);
692+
headingMrad = wrapAngleMrad(headingMrad);
705693

706694
static bool havePrev = false;
707695
static int32_t prevX = 0;
@@ -752,7 +740,10 @@ void App::publishGps(MqttClient& mqttClient, uint32_t tsMs)
752740

753741
void App::onVehicleData(const VehicleData& data)
754742
{
755-
publishVehicleAndSensorSnapshot(data);
743+
if (m_odoOriginInitialized && m_odoZeroInitialized)
744+
{
745+
publishVehicleAndSensorSnapshot(data);
746+
}
756747

757748
m_lastVehicleData = data;
758749
m_hasVehicleData = true;
@@ -864,6 +855,20 @@ void App::updateFromSsr(const SpaceShipRadarPose& ssrPose)
864855
m_ekf.updateCamera(z_cam);
865856
}
866857

858+
float App::wrapAngleMrad(float angleMrad) const
859+
{
860+
constexpr float PI_MRAD = M_PI * 1000.0F;
861+
constexpr float TWO_PI_MRAD = 2.0F * PI_MRAD;
862+
/* Wrap to [-pi, pi). */
863+
float x = std::fmod(angleMrad + PI_MRAD, TWO_PI_MRAD);
864+
if (x < 0.0F)
865+
{
866+
x += TWO_PI_MRAD;
867+
}
868+
869+
return x - PI_MRAD;
870+
}
871+
867872
/******************************************************************************
868873
* External Functions
869874
*****************************************************************************/

lib/APPLineFollowerSensorFusion/src/App.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,13 @@ class App
371371
Source determineNewestSource(uint32_t zumoLocalMs32, uint32_t ssrLocalMs32, uint32_t lastEkfUpdateMs,
372372
uint32_t& newestLocalTs) const;
373373

374+
/**
375+
* @brief Wrap angle in mrad to [-pi, pi).
376+
*
377+
* @param[in] angleMrad Angle in mrad to wrap.
378+
*/
379+
float wrapAngleMrad(float angleMrad) const;
380+
374381
/**
375382
* @brief Initialize EKF timestamp on first data reception.
376383
*

0 commit comments

Comments
 (0)