c++ 使用矩阵的Eigen::Ref初始化const ref成员变量

92dk7w1h  于 2023-03-14  发布在  其他
关注(0)|答案(1)|浏览(333)

考虑下面的类,我想从两个传递给构造函数的Eigen::Ref初始化两个成员变量(普通的const ref)。
在构造函数内部,打印

std::cout << "Matrix Param: " << current_predicted_sigma_points << std::endl;
std::cout << "Matrix Member: " << current_predicted_sigma_points_ << std::endl;

按预期工作,它们打印相同的矩阵,这意味着current_predicted_sigma_points_已正确初始化。
然而,当我调用Update函数时,变量current_predicted_sigma_points_包含垃圾,但weights_仍然正确。

template <typename ProcessModel, typename MeasurementModel>
class UnscentedUpdateStrategy
{
  public:
    UnscentedUpdateStrategy(
        const Eigen::Ref<const ukf_utils::PredictedSigmaMatrix<ProcessModel, ProcessModel::n_sigma_points>>
            current_predicted_sigma_points,
        const Eigen::Ref<const Eigen::Vector<double, ProcessModel::n_sigma_points>> weights)
        : current_predicted_sigma_points_{current_predicted_sigma_points}, weights_{weights}
    {
        std::cout << "Matrix Param: " << current_predicted_sigma_points << std::endl;
        std::cout << "Matrix Member: " << current_predicted_sigma_points_ << std::endl;
    }

    void Update(const Eigen::Ref<const typename MeasurementModel::PredictedVector>& measure,
                const simpleukf::ukf_utils::MeanAndCovariance<ProcessModel>& current_hypotesis,
                simpleukf::ukf_utils::MeanAndCovariance<ProcessModel>& mean_and_cov_out) const
    {
        simpleukf::ukf_utils::PredictedSigmaMatrix<MeasurementModel, ProcessModel::n_sigma_points>
            measurement_predicted_sigma_matrix_out;

        std::cout << "Matrix Member Update: " << current_predicted_sigma_points_ << std::endl;
        std::cout << "Weights Update: " << weights_ << std::endl;

        auto measurement_prediction = ukf_utils::PredictMeanAndCovarianceFromSigmaPoints<MeasurementModel>(
            measurement_predicted_sigma_matrix_out, current_predicted_sigma_points_, weights_);
        // std::forward<const MeasurementPredictionArgs>(args)...);

        // add measurement noise covariance matrix
        measurement_prediction.covariance += MeasurementModel::noise_matrix_squared;
        
        // create matrix for cross correlation: predicted measurement `measurement_prediction.mean` and pred covariance
        // `measurement_prediction.covariance`
        const auto cross_correlation_matrix =
            ukf_utils::ComputeCrossCorrelation<ProcessModel, MeasurementModel, ProcessModel::n_sigma_points>(
                current_predicted_sigma_points_,
                current_hypotesis.mean,
                measurement_predicted_sigma_matrix_out,
                measurement_prediction.mean,
                weights_);

        // Kalman gain K;
        Eigen::Matrix<double, ProcessModel::n, MeasurementModel::n> K =
            cross_correlation_matrix * measurement_prediction.covariance.inverse();

        // residual
        typename MeasurementModel::PredictedVector measure_diff = measure - measurement_prediction.mean;

        // angle normalization
        models_utils::AdjustIfNeeded<MeasurementModel>(measure_diff);

        // update state mean and covariance matrix
        mean_and_cov_out.mean = current_hypotesis.mean + K * measure_diff;
        mean_and_cov_out.covariance =
            current_hypotesis.covariance - K * measurement_prediction.covariance * K.transpose();
    }

  private:
    // TODO: should we keep a copy or not?
    const ukf_utils::PredictedSigmaMatrix<ProcessModel, ProcessModel::n_sigma_points>& current_predicted_sigma_points_;
    const Eigen::Vector<double, ProcessModel::n_sigma_points>& weights_;
};

当将成员切换到Eigen::Ref类型时,问题消失了,但我想了解在原始情况下发生了什么,因为我可能在嵌套函数接受普通引用时遇到同样的问题。

fxnxkyjh

fxnxkyjh1#

您的参数传递存在多个问题:
1.您试图从const Eigen::Ref<const Eigen::Vector<...>>类型的对象初始化const Eigen::Vector<...>&类型的成员。它们显然不是同一类型。其他参数也是如此
1.您传递了一个Eigen::Ref,但希望将其保留在函数(本例中为构造函数)的作用域之外,这是不安全的,原因有二。
Ref通常只Map您传递的向量或矩阵,但在某些情况下,Ref将获取临时副本(特别是如果内部跨距大于1,例如,当将矩阵中的一行作为向量传递时;或者当你传递一个需要求值的表达式时)。当ref超出作用域时,通常是当函数返回时,这个副本将被销毁。
此外,当传递其他参数作为函数参数时,通常只通过转换操作符构造Ref。由于当函数(这里是构造函数)返回时,Ref被销毁,因此保留对该对象的引用或指针会创建一个悬空指针。
第二个问题可以通过复制一个引用对象来解决。第一个问题不能这样解决。所以永远不要这样做。
1.一个小问题是你传递引用的方式。规范的方式是const Eigen::Ref<const ...>&作为输入参数,Eigen::Ref<...>作为输入-输出参数。注意你错过了&作为常量引用。
如何解决这一切?两个选项:
1.通过复制Refs将属性类型更改为普通Vector<double, ...>PredictedSigmaMatrix,construct
1.将构造函数的参数改为普通的对象引用、指针、shared_ptr或其他类型,并保留这些指针/引用。不要使用Eigen::Ref。这只适用于临时引用

相关问题