36 #ifndef DOXYGEN_SHOULD_SKIP_THIS
38 #ifndef COSTFUNCTIONAUTODIFFDERIVATIVEBASE_HPP_
39 #define COSTFUNCTIONAUTODIFFDERIVATIVEBASE_HPP_
41 #include <Eigen/Dense>
42 #include <unsupported/Eigen/NonLinearOptimization>
43 #include <unsupported/Eigen/AutoDiff>
46 template <
class DIMENSIONS>
47 class CostFunctionAutoDiffDerivativeBase
51 EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
53 typedef typename DIMENSIONS::state_vector_t state_vector_t;
54 typedef typename DIMENSIONS::state_vector_array_t state_vector_array_t;
55 typedef typename DIMENSIONS::state_matrix_t state_matrix_t;
56 typedef typename DIMENSIONS::control_vector_t control_vector_t;
57 typedef typename DIMENSIONS::control_vector_array_t control_vector_array_t;
58 typedef typename DIMENSIONS::control_matrix_t control_matrix_t;
59 typedef typename DIMENSIONS::control_feedback_t control_feedback_t;
60 typedef typename DIMENSIONS::scalar_t scalar_t;
63 template<
typename _Scalar>
66 typedef _Scalar Scalar;
68 InputsAtCompileTime = Eigen::Dynamic,
69 ValuesAtCompileTime = Eigen::Dynamic
71 typedef Eigen::Matrix<Scalar,InputsAtCompileTime,1> InputType;
72 typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,1> ValueType;
73 typedef Eigen::Matrix<Scalar,ValuesAtCompileTime,InputsAtCompileTime> JacobianType;
75 const int m_inputs, m_values;
77 Functor() : m_inputs(InputsAtCompileTime), m_values(ValuesAtCompileTime) {}
78 Functor(
int inputs,
int values) : m_inputs(inputs), m_values(values) {}
80 int inputs()
const {
return m_inputs; }
81 int values()
const {
return m_values; }
88 struct iklike_functor : Functor<double>
90 typedef Eigen::AutoDiffScalar<Eigen::Matrix<double,Eigen::Dynamic,1> > ADS;
91 typedef Eigen::Matrix<ADS, Eigen::Dynamic, 1> VectorXad;
94 iklike_functor(
const int inputs_size,
const int values_size)
95 : Functor<double>(inputs_size,values_size),
96 m_targetAngles(targetAngles), m_targetLengths(targetLengths), m_beta(beta),
97 m_pfirst(pfirst), m_plast(plast)
102 int operator()(
const Eigen::VectorXd &inputs, Eigen::VectorXd &val_of_function)
105 Eigen::VectorXd curves(this->inputs()+8);
107 curves.segment(4,this->inputs()) = inputs;
111 curves.segment<2>(0) = m_pfirst - d;
112 curves.segment<2>(2) = m_pfirst;
113 curves.segment<2>(this->inputs()+4) = m_plast;
114 curves.segment<2>(this->inputs()+6) = m_plast + d;
116 ikLikeCosts(curves, m_targetAngles, m_targetLengths, m_beta, fvec);
121 int df(
const Eigen::VectorXd &x, Eigen::MatrixXd &fjac)
123 using namespace Eigen;
124 VectorXad curves(this->inputs()+8);
128 for(
int i=0; i<this->inputs();++i)
129 curves(4+i) = ADS(x(i), this->inputs(), i);
132 curves.segment<2>(0) = (m_pfirst - d).cast<ADS>();
133 curves.segment<2>(2) = (m_pfirst).cast<ADS>();
134 curves.segment<2>(this->inputs()+4) = (m_plast).cast<ADS>();
135 curves.segment<2>(this->inputs()+6) = (m_plast + d).cast<ADS>();
137 VectorXad v(this->values());
139 ikLikeCosts(curves, m_targetAngles, m_targetLengths, m_beta, v);
142 for(
int i=0; i<this->values();++i)
143 fjac.row(i) = v(i).derivatives();
148 const Eigen::VectorXd& m_targetAngles;
149 const Eigen::VectorXd& m_targetLengths;
151 Eigen::Vector2d m_pfirst, m_plast;
190 struct iklike_functor : Functor<double>
192 typedef Eigen::AutoDiffScalar<Eigen::Matrix<Scalar,Eigen::Dynamic,1> > ADS;
193 typedef Eigen::Matrix<ADS, Eigen::Dynamic, 1> VectorXad;
196 iklike_functor(
const Eigen::VectorXd& targetAngles,
const Eigen::VectorXd& targetLengths,
double beta,
const Eigen::Vector2d pfirst,
const Eigen::Vector2d plast)
197 : Functor<double>(targetAngles.size()*2-4,targetAngles.size()*2-1),
198 m_targetAngles(targetAngles), m_targetLengths(targetLengths), m_beta(beta),
199 m_pfirst(pfirst), m_plast(plast)
204 int operator()(
const Eigen::VectorXd &x, Eigen::VectorXd &fvec)
206 using namespace Eigen;
207 VectorXd curves(this->inputs()+8);
209 curves.segment(4,this->inputs()) = x;
212 curves.segment<2>(0) = m_pfirst - d;
213 curves.segment<2>(2) = m_pfirst;
214 curves.segment<2>(this->inputs()+4) = m_plast;
215 curves.segment<2>(this->inputs()+6) = m_plast + d;
217 ikLikeCosts(curves, m_targetAngles, m_targetLengths, m_beta, fvec);
222 int df(
const Eigen::VectorXd &x, Eigen::MatrixXd &fjac)
224 using namespace Eigen;
225 VectorXad curves(this->inputs()+8);
229 for(
int i=0; i<this->inputs();++i)
230 curves(4+i) = ADS(x(i), this->inputs(), i);
233 curves.segment<2>(0) = (m_pfirst - d).cast<ADS>();
234 curves.segment<2>(2) = (m_pfirst).cast<ADS>();
235 curves.segment<2>(this->inputs()+4) = (m_plast).cast<ADS>();
236 curves.segment<2>(this->inputs()+6) = (m_plast + d).cast<ADS>();
238 VectorXad v(this->values());
240 ikLikeCosts(curves, m_targetAngles, m_targetLengths, m_beta, v);
243 for(
int i=0; i<this->values();++i)
244 fjac.row(i) = v(i).derivatives();
249 const Eigen::VectorXd& m_targetAngles;
250 const Eigen::VectorXd& m_targetLengths;
252 Eigen::Vector2d m_pfirst, m_plast;
256 CostFunctionAutoDiffDerivativeBase() {};
257 virtual ~CostFunctionAutoDiffDerivativeBase() {};
259 virtual void setCurrentStateAndControl(
const state_vector_t& x,
const control_vector_t& u) {
264 virtual void setCurrentTrajectory(
const state_vector_array_t & x_traj,
const control_vector_array_t & u_traj,
const Eigen::VectorXd & h_traj)
267 virtual double evaluate() = 0;
269 virtual int getNumberOfDependentVariables() = 0 ;
277 virtual void gradient_xuh(Eigen::VectorXd & f0_gradient) = 0;
287 template<
typename Scalar>
288 void ikLikeCosts(
const Eigen::Matrix<Scalar,Eigen::Dynamic,1>& curve,
const Eigen::VectorXd& targetAngles,
const Eigen::VectorXd& targetLengths,
double beta,
289 Eigen::Matrix<Scalar,Eigen::Dynamic,1>& costs)
291 using namespace Eigen;
294 typedef Matrix<Scalar,2,1> Vec2;
295 int nb = curve.size()/2;
298 for(
int k=1;k<nb-1;++k)
300 Vec2 pk0 = curve.template segment<2>(2*(k-1));
301 Vec2 pk = curve.template segment<2>(2*k);
302 Vec2 pk1 = curve.template segment<2>(2*(k+1));
305 costs((nb-2)+(k-1)) = (pk1-pk).norm() - targetLengths(k-1);
309 Vec2 v0 = (pk-pk0).normalized();
310 Vec2 v1 = (pk1-pk).normalized();
312 costs(k-1) = beta * (atan2(-v0.y() * v1.x() + v0.x() * v1.y(), v0.x() * v1.x() + v0.y() * v1.y()) - targetAngles(k-1));
316 void draw_vecX(
const Eigen::VectorXd& res)
318 for(
int i = 0; i < (res.size()/2) ; i++ )
320 std::cout << res.segment<2>(2*i).transpose() <<
"\n";
328 Eigen::Vector2d pfirst(-5., 0.);
329 Eigen::Vector2d plast ( 5., 0.);
332 const int nb_points = 30;
333 Eigen::VectorXd targetAngles (nb_points);
334 targetAngles.fill(0);
336 Eigen::VectorXd targetLengths(nb_points-1);
337 double val = (pfirst-plast).norm() / (double)(nb_points-1);
338 targetLengths.fill(val);
342 Eigen::VectorXd x((nb_points-2)*2);
343 for(
int i = 1; i < (nb_points - 1); i++)
345 double s = (double)i / (
double)(nb_points-1);
346 x.segment<2>((i-1)*2) = plast * s + pfirst * (1. - s);
350 plast = Eigen::Vector2d(4., 1.);
353 iklike_functor func(targetAngles, targetLengths, 0.1, pfirst, plast);
356 Eigen::LevenbergMarquardt<iklike_functor> lm(func);
359 lm.parameters.ftol *= 1e-2;
360 lm.parameters.xtol *= 1e-2;
361 lm.parameters.maxfev = 2000;
364 int a = lm.minimize(x);
365 std::cerr <<
"info = " << a <<
" " << lm.nfev <<
" " << lm.njev <<
" " <<
"\n";
367 std::cout << pfirst.transpose() <<
"\n";
369 std::cout << plast.transpose() <<
"\n";