Mujoco KDL Wrapper  0.5.1
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
test_mjcf_pos_ctrl.cpp
Go to the documentation of this file.
1/* test_mjcf_pos_ctrl.cpp
2 * POSITION mode on the Kinova GEN3: the MJCF's own servos (kp = 2000, kv = 100) track a linear
3 * joint trajectory, and commands are clamped to the servos' ctrlrange. */
4
6#include "common.hpp"
7#include "example_paths.hpp"
8
9#include <gtest/gtest.h>
10
11#include <algorithm>
12#include <cmath>
13#include <filesystem>
14#include <string>
15
16namespace ex = mj_kdl_examples;
17namespace fs = std::filesystem;
18
19static constexpr double kTargetPose[7] = { 0.3, 0.5, 2.9, -2.0, 0.3, 1.2, 1.3 };
20static constexpr double kMotionDuration = 1.5; // [s]
21static constexpr double kSettleTime = 0.5; // [s]
22static constexpr double kErrTol = 0.01; // [rad], measured 0.0061
23
24class MjcfPosCtrlTest : public testing::Test
25{
26 protected:
29
30 void SetUp() override
31 {
32 const std::string arm = ex::find_asset("kinova_gen3/gen3.xml");
33 if (!fs::exists(arm)) GTEST_SKIP() << arm << " not found";
34
36 rs.path = arm;
38 sc.timestep = 0.002;
39 sc.add_floor = true;
40 sc.add_skybox = false;
41 sc.robots.push_back(rs);
42 ASSERT_TRUE(mj_kdl::init_env(&env_, &sc));
43 ASSERT_TRUE(mj_kdl::init_robot_from_mjcf(&s_, &env_, "base_link", "bracelet_link"));
46 }
47
48 // The position servo driving joint i: robot 0's POSITION group is 1.
49 int servo(int i) const
50 {
51 const int jid = mj_name2id(env_.model, mjOBJ_JOINT, s_.joint_names[i].c_str());
52 for (int a = 0; a < env_.model->nu; ++a) {
53 if (env_.model->actuator_trnid[2 * a] == jid && env_.model->actuator_group[a] == 1)
54 return a;
55 }
56 return -1;
57 }
58};
59
60TEST_F(MjcfPosCtrlTest, TrajectoryTracking)
61{
62 const double t_start = env_.data->time;
63 while (env_.data->time < t_start + kMotionDuration + kSettleTime) {
64 mj_kdl::update(&env_);
65 const double alpha = ex::clamp01((env_.data->time - t_start) / kMotionDuration);
66 for (int i = 0; i < 7; ++i)
67 s_.jnt_pos_cmd[i] = ex::kHomePose[i] + alpha * (kTargetPose[i] - ex::kHomePose[i]);
68 mj_kdl::step(&env_);
69 }
70 mj_kdl::update(&env_);
71
72 double max_err = 0.0;
73 for (int i = 0; i < 7; ++i)
74 max_err = std::max(max_err, std::abs(kTargetPose[i] - s_.jnt_pos_msr[i]));
75 EXPECT_LE(max_err, kErrTol);
76}
77
78TEST_F(MjcfPosCtrlTest, ClampCtrlrange)
79{
80 for (int i = 0; i < 7; ++i) s_.jnt_pos_cmd[i] = 1e9;
81 mj_kdl::update(&env_);
82
83 int limited = 0;
84 for (int i = 0; i < 7; ++i) {
85 const int a = servo(i);
86 ASSERT_GE(a, 0) << s_.joint_names[i];
87 if (!env_.model->actuator_ctrllimited[a]) continue;
88 ++limited;
89 EXPECT_EQ(s_.jnt_saturated[i], 1) << "joint " << i;
90 EXPECT_EQ(env_.data->ctrl[a], env_.model->actuator_ctrlrange[2 * a + 1]) << "joint " << i;
91 }
92 EXPECT_EQ(limited, 3) << "Gen3 joints 2, 4 and 6 have a ctrlrange";
93}
94
95int main(int argc, char *argv[])
96{
97 testing::InitGoogleTest(&argc, argv);
98 return RUN_ALL_TESTS();
99}
void SetUp() override
int servo(int 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)
double clamp01(double v)
Definition common.hpp:64
std::string find_asset(const fs::path &relative)
constexpr double kHomePose[7]
Definition common.hpp:22
KDL::JntArray home_q(unsigned n)
Definition common.hpp:68
std::vector< RobotSpec > robots
int main(int argc, char *argv[])
TEST_F(MjcfPosCtrlTest, TrajectoryTracking)