Mujoco KDL Wrapper  0.2.2
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
ex_pos_ctrl.cpp
Go to the documentation of this file.
1/* ex_pos_ctrl.cpp (MJCF)
2 * Joint position control: drive the Kinova GEN3 from the home pose to a target
3 * pose using linearly interpolated position setpoints, then hold.
4 *
5 * The setpoint trajectory is a straight-line interpolation in joint space over
6 * kMotionDuration seconds. After the motion completes the final position is
7 * held indefinitely.
8 *
9 * Requires MuJoCo Menagerie in cache.
10 *
11 * Usage:
12 * ex_pos_ctrl [--headless]
13 *
14 * With --headless runs the full motion and prints final max joint error. */
15
17#include "example_paths.hpp"
18
19#include <algorithm>
20#include <cmath>
21#include <iomanip>
22#include <iostream>
23#include <string>
24
25static constexpr double kHomePose[7] = { 0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708 };
26static constexpr double kTargetPose[7] = { 0.3, 0.5, 2.9, -2.0, 0.3, 1.2, 1.3 };
27static constexpr double kMotionDuration = 2.0; // seconds for the interpolated move
28
29int main(int argc, char *argv[])
30{
31 bool headless = false;
32 for (int i = 1; i < argc; ++i)
33 if (std::string(argv[i]) == "--headless") headless = true;
34
35 const std::string mjcf = mj_kdl_examples::menagerie_model("kinova_gen3/gen3.xml");
36
38 sc.timestep = 0.002;
39 sc.add_floor = true;
40 sc.add_skybox = true;
42 r.path = mjcf.c_str();
43 sc.robots.push_back(r);
44
45 mjModel *model = nullptr;
46 mjData *data = nullptr;
47 if (!mj_kdl::build_scene(&model, &data, &sc)) {
48 std::cerr << "build_scene() failed\n";
49 return 1;
50 }
51
52 mj_kdl::Robot robot;
53 if (!mj_kdl::init_robot_from_mjcf(&robot, model, data, "base_link", "bracelet_link")) {
54 std::cerr << "init_robot_from_mjcf() failed\n";
55 mj_kdl::destroy_scene(model, data);
56 return 1;
57 }
58
59 unsigned n = static_cast<unsigned>(robot.n_joints);
60
61 KDL::JntArray q_home(n);
62 for (unsigned i = 0; i < n; ++i) q_home(i) = kHomePose[i];
63
65
66 mj_kdl::Env env;
67 env.spec = sc;
68 env.model = model;
69 env.data = data;
70 mj_kdl::env_add_robot(&env, &robot);
71
72 double t_start = 0.0;
73
74 env.on_reset = [&](mj_kdl::ResetContext *) {
75 mj_kdl::set_joint_pos(&robot, q_home, false);
76 t_start = data->time;
77 };
78
79 mj_kdl::reset(&env);
80
81 auto ctrl_step = [&]() {
82 mj_kdl::update(&robot);
83
84 double alpha = std::clamp((data->time - t_start) / kMotionDuration, 0.0, 1.0);
85 for (unsigned i = 0; i < n; ++i)
86 robot.jnt_pos_cmd[i] = kHomePose[i] + alpha * (kTargetPose[i] - kHomePose[i]);
87 };
88
89 if (headless) {
90 // Run until the trajectory is complete plus a short settling period.
91 const double end_time = kMotionDuration + 1.0;
92 while (data->time < end_time) {
93 ctrl_step();
94 mj_kdl::step(&robot);
95 }
96
97 double max_err = 0.0;
98 for (unsigned i = 0; i < n; ++i)
99 max_err = std::max(max_err, std::abs(kTargetPose[i] - robot.jnt_pos_msr[i]));
100 std::cout << "max joint error at end: " << std::fixed << std::setprecision(4) << max_err
101 << " rad\n";
102 } else {
103 mj_kdl::Viewer viewer;
104 if (!mj_kdl::init_window_sim(&viewer, &robot)) {
105 std::cerr << "init_window_sim() failed\n";
106 mj_kdl::cleanup(&robot);
107 mj_kdl::destroy_scene(model, data);
108 return 1;
109 }
110
111 double prev_sim_time = data->time;
112 while (true) {
113 if (data->time < prev_sim_time - 1e-6) mj_kdl::reset(&env);
114 prev_sim_time = data->time;
115 ctrl_step();
116 if (!mj_kdl::step(&robot)) break;
117 }
118
119 mj_kdl::cleanup(&viewer);
120 }
121
122 mj_kdl::cleanup(&robot);
123 mj_kdl::destroy_scene(model, data);
124 return 0;
125}
int main(int argc, char *argv[])
void env_add_robot(Env *env, Robot *robot)
ResetInfo reset(Env *env, const ResetOptions *options=nullptr)
bool step(Robot *s)
void cleanup(Robot *r)
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)
void update(Robot *r)
bool build_scene(mjModel **out_model, mjData **out_data, const SceneSpec *spec)
void destroy_scene(mjModel *model, mjData *data)
bool init_window_sim(Viewer *v, Robot *r, const char *title="MuJoCo")
std::string menagerie_model(const fs::path &relative)
ResetHook on_reset
std::vector< double > jnt_pos_msr
std::vector< double > jnt_pos_cmd
std::vector< RobotSpec > robots