7#include <gtest/gtest.h>
9#include <kdl/chaindynparam.hpp>
10#include <kdl/chainfksolverpos_recursive.hpp>
18namespace fs = std::filesystem;
20static constexpr double kHomePose[7] = { 0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708 };
21static constexpr double kKp[7] = { 100, 200, 100, 200, 100, 200, 100 };
22static constexpr double kKd[7] = { 10, 20, 10, 20, 10, 20, 10 };
33 std::unique_ptr<KDL::ChainFkSolverPos_recursive>
fk_;
34 std::unique_ptr<KDL::ChainDynParam>
dyn_;
39 const std::string arm_mjcf =
41 const std::string grp_mjcf =
43 if (!fs::exists(arm_mjcf)) {
44 GTEST_SKIP() << arm_mjcf <<
" not found";
47 if (!fs::exists(grp_mjcf)) {
48 GTEST_SKIP() << grp_mjcf <<
" not found";
53 .mjcf_path = grp_mjcf.c_str(),
56 .contact_exclusions = {},
59 rs.
path = arm_mjcf.c_str();
76 n_ =
s_.chain.getNrOfJoints();
77 fk_ = std::make_unique<KDL::ChainFkSolverPos_recursive>(
s_.chain);
78 dyn_ = std::make_unique<KDL::ChainDynParam>(
s_.chain, KDL::Vector(0, 0, -9.81));
81 for (
unsigned i = 0; i <
n_; ++i)
q_home_(i) = kHomePose[i];
98 KDL::JntArray q_zero(n_);
100 mj_forward(model_, data_);
103 ASSERT_GE(dyn_->JntToGravity(q_zero, g), 0);
105 double max_err = 0.0;
106 for (
unsigned i = 0; i < n_; ++i)
107 max_err = std::max(max_err, std::abs(g(i) - data_->qfrc_bias[s_.kdl_to_mj_dof[i]]));
108 EXPECT_LE(max_err, 5e-2);
114 fk_->JntToCart(q_home_, ee_init);
118 KDL::JntArray q(n_), g(n_);
119 for (
int i = 0; i < 500; ++i) {
121 for (
unsigned j = 0; j < n_; ++j) q(j) = s_.jnt_pos_msr[j];
122 dyn_->JntToGravity(q, g);
123 for (
unsigned j = 0; j < n_; ++j) {
125 kKp[j] * (kHomePose[j] - s_.jnt_pos_msr[j]) - kKd[j] * s_.jnt_vel_msr[j] + g(j);
130 KDL::JntArray q_end(n_);
131 for (
unsigned j = 0; j < n_; ++j) q_end(j) = s_.jnt_pos_msr[j];
133 fk_->JntToCart(q_end, ee_end);
134 double drift = (ee_init.p - ee_end.p).Norm();
135 EXPECT_LE(drift, 0.005);
145 for (
unsigned i = 0; i < n_; ++i) s_.jnt_trq_cmd[i] = 0.0;
150 for (
unsigned i = 0; i < static_cast<unsigned>(s_.n_joints); ++i) {
151 double expected = s_.data->qfrc_actuator[s_.kdl_to_mj_dof[i]];
152 EXPECT_DOUBLE_EQ(s_.jnt_trq_msr[i], expected)
153 <<
"jnt_trq_msr[" << i <<
"] does not match qfrc_actuator";
157int main(
int argc,
char *argv[])
159 testing::InitGoogleTest(&argc, argv);
160 return RUN_ALL_TESTS();
std::unique_ptr< KDL::ChainDynParam > dyn_
std::unique_ptr< KDL::ChainFkSolverPos_recursive > fk_
bool init_robot_from_mjcf(Robot *r, mjModel *model, mjData *data, const char *base_body, const char *tip_body, const char *prefix="", const ToolFrameSpec *tool=nullptr)
void set_joint_pos(Robot *r, const KDL::JntArray &q, bool call_forward=true)
bool build_scene(mjModel **out_model, mjData **out_data, const SceneSpec *spec)
void destroy_scene(mjModel *model, mjData *data)
std::string find_asset(const fs::path &relative)
std::string find_menagerie_model(const fs::path &relative)
std::vector< AttachmentSpec > attachments
std::vector< RobotSpec > robots
int main(int argc, char *argv[])
TEST_F(MjcfTrqCtrlTest, GravityAccuracy)