// Copyright 2019-2021 The MathWorks, Inc. /** * @file * @brief Distance metric between two states */ #ifndef PLANNINGCODEGEN_DISTANCEMETRIC_HPP #define PLANNINGCODEGEN_DISTANCEMETRIC_HPP #include #include #include namespace nav { template class DistanceMetric { public: DistanceMetric() {} virtual ~DistanceMetric() {} virtual std::vector distance(const std::vector& treeStates, const std::vector& queryState) = 0; protected: /// convert row major matrix to column major matrix static std::vector rowMajorToColumnMajor(const std::vector& states, std::size_t dim) { std::size_t numStates = states.size() / dim; std::vector statesReordered(states.size(), 0.0); for (std::size_t i = 0; i < dim; i++) { for (std::size_t j = 0; j < numStates; j++) { statesReordered[j + i * numStates] = states[i + j * dim]; } } return statesReordered; } protected: /// dimension of the state std::size_t m_dim; /// direction for computing distance /** * from treeStates to queryState [false, outward] or the other way around [true, inward] */ boolean_T m_reverseDirection; }; template class EuclideanMetric : public DistanceMetric { public: EuclideanMetric(std::size_t dim) { this->m_dim = dim; } std::vector distance(const std::vector& states, const std::vector& queryState) { std::vector dists; std::size_t numStates = states.size() / this->m_dim; typename std::vector::const_iterator queryIt = queryState.begin(); typename std::vector::const_iterator statesIt = states.begin(); for (std::size_t i = 0; i < numStates; i++) { dists.push_back(distanceInternal(statesIt, queryIt)); statesIt += this->m_dim; } return dists; } protected: T distanceInternal(const typename std::vector::const_iterator& state1It, const typename std::vector::const_iterator& state2It) { T sum = static_cast(0.0); for (size_t i = 0; i < this->m_dim; i++) { sum += ( *(state2It + i) - *(state1It + i)) * ( *(state2It + i) - *(state1It + i)); } return std::sqrt(sum); } }; } #endif