This file implements constraint unit tests. For more intuitive examples, visit the tutorial.
#pragma once
namespace optcon {
namespace example {
template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR = double>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
typedef Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>
VectorXs;
typedef Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
MatrixXs;
{
}
{
}
virtual VectorXs
evaluate(
const state_vector_t&
x,
const control_vector_t&
u,
const SCALAR t)
override {
Eigen::Matrix<SCALAR, term_dim, 1> constr_violation;
constr_violation.template segment<1>(0) << (
u(1) * Trait::cos(
x(2)) -
u(0) * Trait::sin(
x(2)) -
u(2));
return constr_violation;
}
virtual Eigen::Matrix<ct::core::ADCGScalar, Eigen::Dynamic, 1>
evaluateCppadCg(
const core::StateVector<STATE_DIM, ct::core::ADCGScalar>& x,
const core::ControlVector<CONTROL_DIM, ct::core::ADCGScalar>& u,
ct::core::ADCGScalar t) override
{
Eigen::Matrix<ct::core::ADCGScalar, term_dim, 1> constr_violation;
constr_violation.template segment<1>(0) << (
u(1) * TraitCG::cos(
x(2)) -
u(0) * TraitCG::sin(
x(2)) -
u(2));
return constr_violation;
}
virtual MatrixXs
jacobianState(
const state_vector_t& x,
const control_vector_t& u,
const SCALAR t)
override {
Eigen::Matrix<SCALAR, term_dim, STATE_DIM> jac;
jac.setZero();
return jac;
}
virtual MatrixXs
jacobianInput(
const state_vector_t& x,
const control_vector_t& u,
const SCALAR t)
override {
Eigen::Matrix<SCALAR, term_dim, CONTROL_DIM> jac;
jac.setZero();
jac << -sin(
x(2)), cos(
x(2)),
SCALAR(-1.0);
return jac;
}
};
template <size_t STATE_DIM, size_t CONTROL_DIM, typename SCALAR = double>
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
typedef Eigen::Matrix<SCALAR, Eigen::Dynamic, 1>
VectorXs;
typedef Eigen::Matrix<SCALAR, Eigen::Dynamic, Eigen::Dynamic>
MatrixXs;
ConstraintTerm2D()
{
}
virtual ~ConstraintTerm2D() {}
ConstraintTerm2D<STATE_DIM, CONTROL_DIM, SCALAR>*
clone()
const override {
return new ConstraintTerm2D<STATE_DIM, CONTROL_DIM, SCALAR>();
}
virtual VectorXs
evaluate(
const state_vector_t&
x,
const control_vector_t&
u,
const SCALAR t)
override {
Eigen::Matrix<SCALAR, term_dim, 1> constr_violation;
constr_violation(0) = (
u(1) * Trait::cos(
x(2)) -
u(0) * Trait::sin(
x(2)) -
u(2));
constr_violation(1) = (
u(2) * Trait::cos(
x(1)) -
u(2) * Trait::sin(
x(1)) -
u(1));
return constr_violation;
}
virtual Eigen::Matrix<ct::core::ADCGScalar, Eigen::Dynamic, 1>
evaluateCppadCg(
const core::StateVector<STATE_DIM, ct::core::ADCGScalar>& x,
const core::ControlVector<CONTROL_DIM, ct::core::ADCGScalar>& u,
ct::core::ADCGScalar t) override
{
Eigen::Matrix<ct::core::ADCGScalar, term_dim, 1> constr_violation;
constr_violation(0) = (
u(1) * TraitCG::cos(
x(2)) -
u(0) * TraitCG::sin(
x(2)) -
u(2));
constr_violation(1) = (
u(2) * TraitCG::cos(
x(1)) -
u(2) * TraitCG::sin(
x(1)) -
u(1));
return constr_violation;
}
virtual MatrixXs
jacobianState(
const state_vector_t& x,
const control_vector_t& u,
const SCALAR t)
override {
Eigen::Matrix<SCALAR, term_dim, STATE_DIM> jac;
jac.setZero();
jac.row(0) << 0.0, 0.0, -
u(1) * sin(
x(2)) -
u(0) * cos(
x(2));
jac.row(1) << 0.0, -(
u(2)) * sin(
x(1)) -
u(2) * cos(
x(1)), 0.0;
return jac;
}
virtual MatrixXs
jacobianInput(
const state_vector_t& x,
const control_vector_t& u,
const SCALAR t)
override {
Eigen::Matrix<SCALAR, term_dim, CONTROL_DIM> jac;
jac.setZero();
jac.row(0) << -sin(
x(2)), cos(
x(2)), -1.0;
jac.row(1) << 0.0, -1.0, cos(
x(1)) - sin(
x(1));
return jac;
}
};
TEST(ConstraintComparison, comparisonAnalyticAD)
{
std::shared_ptr<ct::optcon::ConstraintContainerAD<state_dim, control_dim>> constraintAD(
new ct::optcon::ConstraintContainerAD<state_dim, control_dim>());
std::shared_ptr<ct::optcon::ConstraintContainerAnalytical<state_dim, control_dim>> constraintAN(
term1_ad->setName("term1_ad");
std::shared_ptr<ConstraintTerm2D<state_dim, control_dim>> term2_ad(new ConstraintTerm2D<state_dim, control_dim>());
term2_ad->setName("term2_ad");
std::shared_ptr<ConstraintTerm1D<state_dim, control_dim, double>> term1_an(
term1_an->setName("term1_an");
std::shared_ptr<ConstraintTerm2D<state_dim, control_dim, double>> term2_an(
new ConstraintTerm2D<state_dim, control_dim, double>());
term2_an->setName("term2_an");
std::cout << "Adding terms to constraint_analytic" << std::endl;
constraintAD->addIntermediateConstraint(term1_ad, verbose);
constraintAD->addIntermediateConstraint(term2_ad, verbose);
constraintAN->addIntermediateConstraint(term1_an, verbose);
constraintAN->addIntermediateConstraint(term2_an, verbose);
constraintAD->initialize();
constraintAN->initialize();
Eigen::VectorXd g1_ad, g1_an;
Eigen::Matrix<double, state_dim, 1> state = Eigen::Matrix<double, state_dim, 1>::Random();
Eigen::Matrix<double, control_dim, 1> control = Eigen::Matrix<double, control_dim, 1>::Random();
double time = 0.5;
constraintAN->setCurrentStateAndControl(state, control, time);
constraintAD->setCurrentStateAndControl(state, control, time);
g1_an = constraintAN->evaluateIntermediate();
g1_ad = constraintAD->evaluateIntermediate();
std::cout << "g1_an: " << g1_an.transpose() << std::endl;
std::cout << "g1_ad: " << g1_ad.transpose() << std::endl;
ASSERT_TRUE(g1_an.isApprox(g1_ad));
Eigen::MatrixXd C_an, C_ad, D_an, D_ad;
C_an = constraintAN->jacobianStateIntermediate();
D_an = constraintAN->jacobianInputIntermediate();
C_ad = constraintAD->jacobianStateIntermediate();
D_ad = constraintAD->jacobianInputIntermediate();
ASSERT_TRUE(C_an.isApprox(C_ad));
ASSERT_TRUE(D_an.isApprox(D_ad));
ASSERT_TRUE(1.0);
}
}
}
}