Program Listing for File math_user_utils.cpp

Return to documentation for file (src/tap/algorithms/math_user_utils.cpp)

/*
 * Copyright (c) 2020-2021 Advanced Robotics at the University of Washington <robomstr@uw.edu>
 *
 * This file is part of Taproot.
 *
 * Taproot is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Taproot is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Taproot.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "math_user_utils.hpp"

#include <cstdint>

float tap::algorithms::fastInvSqrt(float x)
{
    static_assert(sizeof(float) == 4, "fast inverse sqrt requires 32-bit float");
    float halfx = 0.5f * x;
    float y = x;
    int32_t i = reinterpretCopy<float, int32_t>(y);
    i = 0x5f3759df - (i >> 1);
    y = reinterpretCopy<int32_t, float>(i);
    y = y * (1.5f - (halfx * y * y));
    return y;
}

void tap::algorithms::rotateVector(float* x, float* y, float radians)
{
    float x_temp = *x;
    *x = (*x) * cosf(radians) - *y * sinf(radians);
    *y = x_temp * sinf(radians) + *y * cosf(radians);
}

tap::algorithms::CMSISMat<3, 1> tap::algorithms::cross(
    const tap::algorithms::CMSISMat<3, 1>& a,
    const tap::algorithms::CMSISMat<3, 1>& b)
{
    return tap::algorithms::CMSISMat<3, 1>(
        {a.data[1] * b.data[2] - a.data[2] * b.data[1],
         a.data[2] * b.data[0] - a.data[0] * b.data[2],
         a.data[0] * b.data[1] - a.data[1] * b.data[0]});
}

tap::algorithms::CMSISMat<3, 3> tap::algorithms::fromEulerAngles(
    const float roll,
    const float pitch,
    const float yaw)
{
    return tap::algorithms::CMSISMat<3, 3>(
        {cosf(yaw) * cosf(pitch),
         (cosf(yaw) * sinf(pitch) * sinf(roll)) - (sinf(yaw) * cosf(roll)),
         (cosf(yaw) * sinf(pitch) * cosf(roll)) + sinf(yaw) * sinf(roll),
         sinf(yaw) * cosf(pitch),
         sinf(yaw) * sinf(pitch) * sinf(roll) + cosf(yaw) * cosf(roll),
         sinf(yaw) * sinf(pitch) * cosf(roll) - cosf(yaw) * sinf(roll),
         -sinf(pitch),
         cosf(pitch) * sinf(roll),
         cosf(pitch) * cosf(roll)});
}

modm::Vector3f tap::algorithms::eulerAnglesFromQuaternion(modm::Quaternion<float>& q)
{
    modm::Vector3f eulerAngles;

    // roll (x-axis rotation)
    float sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
    float cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
    eulerAngles.x = std::atan2(sinr_cosp, cosr_cosp);

    // pitch (y-axis rotation)
    float sinp = std::sqrt(1 + 2 * (q.w * q.y - q.x * q.z));
    float cosp = std::sqrt(1 - 2 * (q.w * q.y - q.x * q.z));
    eulerAngles.y = 2 * std::atan2(sinp, cosp) - static_cast<float>(M_PI) / 2;

    // yaw (z-axis rotation)
    float siny_cosp = 2 * (q.w * q.z + q.x * q.y);
    float cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
    eulerAngles.z = std::atan2(siny_cosp, cosy_cosp);

    return eulerAngles;
}