This unit test serves as example how to use the SystemLinearizer (numerical differentiation) and the Autodiff-Linearizer (automatic differentiation)
#include <gtest/gtest.h>
using std::shared_ptr;
TEST(AutoDiffLinearizerTest, SystemLinearizerComparison)
{
typedef CppAD::AD<double> AD_Scalar;
typedef Eigen::Matrix<double, state_dim, state_dim> A_type;
typedef Eigen::Matrix<double, state_dim, control_dim> B_type;
AutoDiffLinearizer<state_dim, control_dim> adLinearizer(nonlinearSystemAD);
std::shared_ptr<AutoDiffLinearizer<state_dim, control_dim>> adLinearizerClone(adLinearizer.clone());
for (
size_t i = 0;
i < 1000;
i++)
{
x.setRandom();
u.setRandom();
A_type A_ad = adLinearizer.getDerivativeState(x, u, t);
B_type B_ad = adLinearizer.getDerivativeControl(x, u, t);
A_type A_adCloned = adLinearizerClone->getDerivativeState(x, u, t);
B_type B_adCloned = adLinearizerClone->getDerivativeControl(x, u, t);
ASSERT_LT((A_system - A_ad).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_ad).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((A_system - A_adCloned).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_adCloned).array().abs().maxCoeff(), 1e-5);
}
}
TEST(AutoDiffDiscreteLinearizerTest, DiscreteSystemLinearizerComparison)
{
typedef CppAD::AD<double> AD_Scalar;
const double rate = 0.1;
shared_ptr<TestDiscreteNonlinearSystemAD> nonlinearSystemAD(
DiscreteSystemLinearizerAD<state_dim, control_dim> adLinearizer(nonlinearSystemAD);
std::shared_ptr<DiscreteSystemLinearizerAD<state_dim, control_dim>> adLinearizerClone(adLinearizer.clone());
for (
size_t i = 0;
i < 1000;
i++)
{
x.setRandom();
u.setRandom();
A_type A_system2;
B_type B_system2;
systemLinearizer.
getAandB(x, u, x, n, 1, A_system2, B_system2);
ASSERT_LT((A_system - A_system2).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_system2).array().abs().maxCoeff(), 1e-5);
A_type A_system_analytic;
A_system_analytic << 1.0 + rate * u(0), 0.0, x(1) * x(1), 2.0 * x(0) * x(1);
B_type B_system_analytic;
B_system_analytic << rate * x(0), 0.0;
ASSERT_LT((A_system - A_system_analytic).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_system_analytic).array().abs().maxCoeff(), 1e-5);
A_type A_ad = adLinearizer.getDerivativeState(x, u, n);
B_type B_ad = adLinearizer.getDerivativeControl(x, u, n);
A_type A_adCloned = adLinearizerClone->getDerivativeState(x, u, n);
B_type B_adCloned = adLinearizerClone->getDerivativeControl(x, u, n);
ASSERT_LT((A_system - A_ad).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_ad).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((A_system - A_adCloned).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_adCloned).array().abs().maxCoeff(), 1e-5);
}
}
TEST(AutoDiffLinearizerTestMP, SystemLinearizerComparisonMP)
{
typedef std::shared_ptr<AutoDiffLinearizer<state_dim, control_dim>> AdLinearizerPtr;
typedef CppAD::AD<double> AD_Scalar;
typedef Eigen::Matrix<double, state_dim, state_dim> A_type;
typedef Eigen::Matrix<double, state_dim, control_dim> B_type;
AutoDiffLinearizer<state_dim, control_dim> adLinearizer(nonlinearSystemAD);
std::vector<std::shared_ptr<SystemLinearizer<state_dim, control_dim>>> systemLinearizers;
size_t runs = 1000;
size_t numThreads = 5;
for (
size_t i = 0;
i < numThreads; ++
i)
systemLinearizers.push_back(
CppadParallel::initParallel(numThreads + 1);
for (
size_t n = 0;
n < runs; ++
n)
{
std::vector<std::thread> threads;
for (
size_t i = 0;
i < numThreads; ++
i)
{
threads.push_back(std::thread([
i, state_dim, control_dim, &adLinearizer, &systemLinearizers]() {
AdLinearizerPtr adLinearizerLocal = AdLinearizerPtr(adLinearizer.clone());
x.setRandom();
u.setRandom();
A_type A_system = systemLinearizers[
i]->getDerivativeState(x, u, t);
B_type B_system = systemLinearizers[
i]->getDerivativeControl(x, u, t);
A_type A_ad = adLinearizerLocal->getDerivativeState(x, u, t);
B_type B_ad = adLinearizerLocal->getDerivativeControl(x, u, t);
ASSERT_LT((A_system - A_ad).array().abs().maxCoeff(), 1e-5);
ASSERT_LT((B_system - B_ad).array().abs().maxCoeff(), 1e-5);
}));
}
for (auto& thr : threads)
thr.join();
}
CppadParallel::resetParallel();
}
int main(
int argc,
char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}