Mujoco KDL Wrapper  0.5.1
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
test_mjcf_trq_ctrl.cpp
Go to the documentation of this file.
1/* test_mjcf_trq_ctrl.cpp
2 * TORQUE mode on the Kinova GEN3 + Robotiq 2F-85: KDL gravity with the gripper's lumped mass,
3 * impedance hold, and jnt_trq_msr as the drive torque. */
4
6#include "common.hpp"
7#include "example_paths.hpp"
8
9#include <gtest/gtest.h>
10
11#include <kdl/chaindynparam.hpp>
12#include <kdl/chainfksolverpos_recursive.hpp>
13
14#include <algorithm>
15#include <cmath>
16#include <filesystem>
17#include <string>
18
19namespace ex = mj_kdl_examples;
20namespace fs = std::filesystem;
21
22class MjcfTrqCtrlTest : public testing::Test
23{
24 protected:
28
29 void SetUp() override
30 {
31 const std::string arm_mjcf = ex::find_asset("kinova_gen3/gen3.xml");
32 const std::string grp_mjcf = ex::find_asset("robotiq_2f85/2f85.xml");
33 if (!fs::exists(arm_mjcf)) GTEST_SKIP() << arm_mjcf << " not found";
34 if (!fs::exists(grp_mjcf)) GTEST_SKIP() << grp_mjcf << " not found";
35
37 rs.path = arm_mjcf;
38 rs.attachments.push_back(ex::gripper_attachment(grp_mjcf));
40 sc.timestep = 0.002;
41 sc.add_floor = true;
42 sc.add_skybox = false;
43 sc.robots.push_back(rs);
44
45 ASSERT_TRUE(mj_kdl::init_env(&env_, &sc));
47 ASSERT_TRUE(
48 mj_kdl::init_robot_from_mjcf(&s_, &env_, "base_link", "bracelet_link", "", &tool)
49 );
51 }
52
53 int dof(const mj_kdl::Robot &r, unsigned i) const
54 {
55 const int jid = mj_name2id(env_.model, mjOBJ_JOINT, r.joint_names[i].c_str());
56 return env_.model->jnt_dofadr[jid];
57 }
58
60 {
61 KDL::ChainDynParam dyn(r.chain, KDL::Vector(0, 0, -9.81));
62 KDL::JntArray g(7);
63 EXPECT_GE(dyn.JntToGravity(q_home_, g), 0);
64 double err = 0.0;
65 for (unsigned i = 0; i < 7; ++i)
66 err = std::max(err, std::abs(g(i) - env_.data->qfrc_bias[dof(r, i)]));
67 return err;
68 }
69};
70
71TEST_F(MjcfTrqCtrlTest, GravityIncludesTheGripperMass)
72{
73 // At home the gripper hangs off the wrist axes, so its weight loads the arm joints.
74 mj_forward(env_.model, env_.data);
75 EXPECT_LE(max_gravity_error(s_), 1e-9) << "measured 2e-14 Nm";
76
77 mj_kdl::Robot bare;
78 ASSERT_TRUE(mj_kdl::init_robot_from_mjcf(&bare, &env_, "base_link", "bracelet_link"));
79 EXPECT_GT(max_gravity_error(bare), 1.0) << "without the tool the chain misses ~5 Nm";
80 mj_kdl::cleanup(&bare);
81}
82
83TEST_F(MjcfTrqCtrlTest, ImpedanceDrift)
84{
86 KDL::ChainDynParam dyn(s_.chain, KDL::Vector(0, 0, -9.81));
87 KDL::Frame ee_init;
88 fk.JntToCart(q_home_, ee_init);
89
91 ex::prime_gravity(s_, dyn, q_home_);
92 for (int i = 0; i < 500; ++i) {
93 mj_kdl::update(&env_);
94 ex::pd_gravity(s_, dyn, q_home_, ex::kKp, ex::kKd);
95 mj_kdl::step(&env_);
96 }
97 mj_kdl::update(&env_);
98 EXPECT_LE((ex::tcp_frame(fk, s_).p - ee_init.p).Norm(), 1e-5) << "measured 7e-7 m";
99}
100
101TEST_F(MjcfTrqCtrlTest, TrqMsrReadsQfrcActuator)
102{
104 for (unsigned i = 0; i < 7; ++i) s_.jnt_trq_cmd[i] = 1.0 + i;
105 mj_kdl::update(&env_);
106 mj_kdl::step(&env_);
107 mj_kdl::update(&env_);
108
109 for (unsigned i = 0; i < 7; ++i) {
110 const double actuator = env_.data->qfrc_actuator[dof(s_, i)];
111 EXPECT_DOUBLE_EQ(s_.jnt_trq_msr[i], actuator) << "joint " << i;
112 EXPECT_NEAR(actuator, 1.0 + i, 1e-9) << "the motor delivers the command";
113 EXPECT_NE(actuator, env_.data->qfrc_bias[dof(s_, i)]);
114 }
115}
116
117int main(int argc, char *argv[])
118{
119 testing::InitGoogleTest(&argc, argv);
120 return RUN_ALL_TESTS();
121}
virtual int JntToGravity(const JntArray &q, JntArray &gravity)
virtual int JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr=-1)
const KDL::JntArray q_home_
void SetUp() override
double max_gravity_error(const mj_kdl::Robot &r)
int dof(const mj_kdl::Robot &r, unsigned i) const
Status init_env(Env *env, const SceneSpec *spec)
void update(Env *env)
bool step(Env *env)
Status set_control_mode(Robot *r, CtrlMode mode)
Status init_robot_from_mjcf(Robot *r, Env *env, 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)
void cleanup(Robot *r)
constexpr double kKd[7]
Definition common.hpp:26
mj_kdl::ToolFrameSpec gripper_tool(const std::string &prefix="")
Definition common.hpp:159
constexpr double kKp[7]
Definition common.hpp:25
KDL::Frame tcp_frame(KDL::ChainFkSolverPos_recursive &fk, const mj_kdl::Robot &robot)
Definition common.hpp:102
std::string find_asset(const fs::path &relative)
mj_kdl::AttachmentSpec gripper_attachment(const std::string &path, const std::string &site="pinch_site")
Definition common.hpp:149
KDL::JntArray home_q(unsigned n)
Definition common.hpp:68
void pd_gravity(mj_kdl::Robot &robot, KDL::ChainDynParam &dyn, const KDL::JntArray &q_des, const double *kp=nullptr, const double *kd=nullptr)
Definition common.hpp:112
void prime_gravity(mj_kdl::Robot &robot, KDL::ChainDynParam &dyn, const KDL::JntArray &q)
Definition common.hpp:131
std::vector< AttachmentSpec > attachments
std::vector< std::string > joint_names
std::vector< RobotSpec > robots
int main(int argc, char *argv[])
TEST_F(MjcfTrqCtrlTest, GravityIncludesTheGripperMass)