sfwa / ukf

Unscented Kalman Filter library for state and parameter estimation
http://au.tono.my/log/20130531-kalman-filter.html
MIT License
461 stars 172 forks source link

Can't link to separate executable: Integrator can't find custom derivative functions #54

Closed nightduck closed 3 years ago

nightduck commented 3 years ago

Upon building my CMake project, I get the following (simplified) error message

.../motion_forecasting.cpp.o: In function `UKF::StateVector<custom generic types> UKF::IntegratorRK4::integrate<UKF::StateVector<same generic types>>(float, UKF::StateVector<more generic types> const&)':
/home/path/to/ukf/include/UKF/Integrator.h:35: undefined reference to `UKF::StateVector<...> UKF::StateVector<...>::derivative<>() const'
/home/path/to/ukf/include/UKF/Integrator.h:36: undefined reference to `UKF::StateVector<...> UKF::StateVector<...>::derivative<>() const'
/home/path/to/ukf/include/UKF/Integrator.h:37: undefined reference to `UKF::StateVector<...> UKF::StateVector<...>::derivative<>() const'
/home/path/to/ukf/include/UKF/Integrator.h:38: undefined reference to `UKF::StateVector<...> UKF::StateVector<...>::derivative<>() const'

So the integrator function can't see my custom definition of my state vector's derivative, defined like so, in the UKF namespace

template <> template <>
TrajectoryStateVector TrajectoryStateVector::derivative<UKF::Vector<3>>(
        const UKF::Vector<3>& droneVelocity,
        const UKF::Vector<3>& droneAngularVelocity,
        const UKF::Vector<3>& droneAcceleration,
        const UKF::Vector<3>& droneAngularAcceleration) const {
    ...
}

using MotionForecastingCore = UKF::Core<
    TrajectoryStateVector,
    MeasurementVector,
    UKF::IntegratorRK4
>;

Is this a cmake error?

nightduck commented 3 years ago

The fix is to put all this code in a separate library. It doesn't work when put directly in an executable for some reason.

nightduck commented 3 years ago

Nvm. Even in its own library, the project will never compile as long as I call the Core::step() function at some point.

Furthermore: the sfwa_ukf example only compiles when left as a useless library. When linked to an executable (example code below), it fails to build.

Modify bottom of CMakeLists.txt:

ADD_EXECUTABLE(prog main.cpp)
target_link_libraries(prog cukf)

Add new file main.cpp:

#include "cukf.h"

int main(int argc, char** argv) {
    ukf_init();
    ukf_sensor_clear();
    ukf_set_position(3,5,6);

    real_t cv[UKF_CONTROL_DIM] = {1,2,3,4};
    ukf_iterate(0, cv); 

    struct ukf_state_t state;
    ukf_get_state(&state);
}

After calling (from repo root)

mkdir build && cd build
cmake ..
cd examples/sfwa_ukf
make

You get a waterfall of errors, similar to the one described in the original issue.

nightduck commented 3 years ago

So the library thing was a false flag.

The issue was my derivative function defined one generic, but passed 4 arguments. Somewhat related, these same generic arguments and function arguments should be passed to each expected_measurement function. Like so:

template <> template <>
TrajectoryStateVector TrajectoryStateVector::derivative<UKF::Vector<3>, UKF::Vector<3>, UKF::Vector<3>, UKF::Vector<3>>(
        const UKF::Vector<3>& droneVelocity,
        const UKF::Vector<3>& droneAngularVelocity,
        const UKF::Vector<3>& droneAcceleration,
        const UKF::Vector<3>& droneAngularAcceleration) const {
    ...
}

template <> template <>
UKF::Vector<3> MeasurementVector::expected_measurement
<TrajectoryStateVector, BoundingBox, UKF::Vector<3>, UKF::Vector<3>, UKF::Vector<3>, UKF::Vector<3>>(
        const TrajectoryStateVector& state,
        const UKF::Vector<3>& droneVelocity,
        const UKF::Vector<3>& droneAngularVelocity,
        const UKF::Vector<3>& droneAcceleration,
        const UKF::Vector<3>& droneAngularAcceleration) {
    ...
}