You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

spline_function.cpp 2.1 kB

2 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #include "util/util.h"
  2. #include "geo/private/math/spline_function.h"
  3. #include "Eigen/LU"
  4. #include "Eigen/Dense"
  5. #include "unsupported/Eigen/NonLinearOptimization"
  6. namespace ns
  7. {
  8. namespace geo
  9. {
  10. SplineFunction::SplineFunction(const Eigen::VectorXd& x,
  11. const Eigen::VectorXd& y, int degree)
  12. {
  13. init(x, y, degree);
  14. }
  15. void SplineFunction::init(Eigen::VectorXd const& x, Eigen::VectorXd const& y,
  16. int degree)
  17. {
  18. x_min = x.minCoeff();
  19. auto dx = x.maxCoeff() - x_min;
  20. m_alpha = 1.0 / dx;
  21. NS_ASSERT(!std::isnan(m_alpha))
  22. << "Cannot create a spline function: range of x values is too small";
  23. m_spline = Eigen::SplineFitting<Eigen::Spline<double, 1>>::Interpolate(
  24. y.transpose(),
  25. degree, // caller guarantee smaller than 3
  26. scaled_values(x));
  27. m_der_alpha.resize(degree + 1);
  28. m_der_alpha(0) = 1.0;
  29. for (int i = 0; i < degree; ++i)
  30. {
  31. m_der_alpha(i + 1) = m_der_alpha(i) * m_alpha;
  32. }
  33. }
  34. double SplineFunction::operator()(double x) const
  35. {
  36. // x values need to be scaled down in extraction as well.
  37. return m_spline(scaled_value(x))(0);
  38. }
  39. Eigen::VectorXd SplineFunction::operator()(const Eigen::VectorXd& x) const
  40. {
  41. return x.unaryExpr([&](double t) { return m_spline(scaled_value(t))(0); });
  42. }
  43. Eigen::VectorXd SplineFunction::der(double x, int degree) const
  44. {
  45. return m_spline.derivatives(scaled_value(x), degree).transpose() *
  46. m_der_alpha.head(degree + 1);
  47. }
  48. Eigen::MatrixXd SplineFunction::der(const Eigen::VectorXd& x, int degree) const
  49. {
  50. auto n = x.size();
  51. Eigen::MatrixXd ret(degree + 1, n);
  52. for (int i = 0; i < n; ++i)
  53. {
  54. ret.col(i) = der(x(i), degree);
  55. }
  56. return ret;
  57. }
  58. double SplineFunction::scaled_value(double x) const
  59. {
  60. return m_alpha * (x - x_min);
  61. }
  62. Eigen::RowVectorXd SplineFunction::scaled_values(Eigen::VectorXd const& x) const
  63. {
  64. return x.unaryExpr([this](double lx) { return scaled_value(lx); })
  65. .transpose();
  66. }
  67. } // namespace geo
  68. } // namespace ns