Mujoco KDL Wrapper  0.5.1
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
ex_joint_ctrl.cpp
Go to the documentation of this file.
1/* ex_joint_ctrl.cpp
2 * Joint control on the Kinova GEN3 in two motions: POSITION mode drives the arm from home to a
3 * target with setpoints interpolated linearly over kMotionDuration and holds it for kHoldTime;
4 * then VELOCITY mode (the <joint>_velocity actuators added through RobotSpec::modes) brings it
5 * back home with a clamped proportional velocity command:
6 *
7 * jnt_vel_cmd[i] = clamp(Kv * (home[i] - q[i]), -maxVel, maxVel)
8 *
9 * Usage:
10 * ex_joint_ctrl [--headless]
11 *
12 * Prints each motion's final max joint error; --headless skips the viewer and exits 1 if the
13 * POSITION motion ends further than kMaxErr from the target or the VELOCITY motion does not
14 * converge within kTol before kTimeout. */
15
16#include "common.hpp"
17#include "example_paths.hpp"
18
19#include <algorithm>
20#include <cmath>
21#include <iomanip>
22#include <iostream>
23#include <limits>
24#include <string>
25
26namespace ex = mj_kdl_examples;
27
28static constexpr double kTargetPose[7] = { 0.3, 0.5, 2.9, -2.0, 0.3, 1.2, 1.3 };
29static constexpr double kMotionDuration = 2.0; // [s]
30static constexpr double kHoldTime = 1.0; // [s]
31static constexpr double kMaxErr = 0.01; // [rad]
32static constexpr double kVelGain = 500.0; // velocity actuator kv [Nm s/rad]
33static constexpr double kKv = 2.0; // [rad/s per rad]
34static constexpr double kMaxVel = 0.6; // [rad/s]
35static constexpr double kTol = 0.01; // [rad]
36static constexpr double kTimeout = 5.0; // [s]
37
38enum class Motion { Position, Velocity };
39
40int main(int argc, char *argv[])
41{
42 const bool headless = ex::parse_args(argc, argv).headless;
43
46 r.path = ex::asset("kinova_gen3/gen3.xml");
47 r.modes = { { .mode = mj_kdl::CtrlMode::VELOCITY, .joints = {}, .kv = kVelGain } };
48 sc.robots.push_back(r);
49
50 mj_kdl::Env env;
51 mj_kdl::Robot robot;
52 if (!mj_kdl::init_env(&env, &sc)) return 1;
53 if (!mj_kdl::init_robot_from_mjcf(&robot, &env, "base_link", "bracelet_link")) return 1;
54
55 const unsigned n = robot.chain.getNrOfJoints();
56 const KDL::JntArray q_home = ex::home_q(n);
57 bool restart = false;
58
59 env.on_reset = [&](mj_kdl::ResetContext *) {
60 mj_kdl::set_joint_pos(&robot, q_home);
61 for (unsigned i = 0; i < n; ++i) robot.jnt_pos_cmd[i] = q_home(i);
62 restart = true;
63 };
64 mj_kdl::reset(&env);
65 if (!headless && !mj_kdl::open_viewer(&env)) return 1;
66
67 constexpr double kNotReached = std::numeric_limits<double>::infinity();
68 Motion motion = Motion::Position;
69 double t_start = 0.0;
70 double pos_err = kNotReached;
71 double vel_err = kNotReached;
72 double vel_time = 0.0;
73 while (true) {
74 if (restart) {
75 restart = false;
77 motion = Motion::Position;
78 t_start = env.data->time;
79 pos_err = vel_err = kNotReached;
80 }
81 mj_kdl::update(&env);
82 const double t = env.data->time - t_start;
83 double max_err = 0.0;
84 if (motion == Motion::Position) {
85 const double alpha = ex::clamp01(t / kMotionDuration);
86 for (unsigned i = 0; i < n; ++i) {
87 robot.jnt_pos_cmd[i] = q_home(i) + alpha * (kTargetPose[i] - q_home(i));
88 max_err = std::max(max_err, std::abs(kTargetPose[i] - robot.jnt_pos_msr[i]));
89 }
90 if (t >= kMotionDuration + kHoldTime) {
91 pos_err = max_err;
93 motion = Motion::Velocity;
94 t_start = env.data->time;
95 continue;
96 }
97 } else {
98 for (unsigned i = 0; i < n; ++i) {
99 const double err = q_home(i) - robot.jnt_pos_msr[i];
100 max_err = std::max(max_err, std::abs(err));
101 robot.jnt_vel_cmd[i] = ex::clamp_abs(kKv * err, kMaxVel);
102 }
103 if (max_err < kTol || t >= kTimeout) {
104 vel_err = max_err;
105 vel_time = t;
106 break;
107 }
108 }
109 if (!mj_kdl::step(&env)) break;
111 }
112
113 const bool pos_ok = pos_err <= kMaxErr;
114 const bool vel_ok = vel_err < kTol;
115 std::cout << std::fixed << std::setprecision(4) << "POSITION: max joint error at the target "
116 << pos_err << " rad (limit " << kMaxErr << " rad)\nVELOCITY: max joint error at home "
117 << vel_err << " rad (" << (vel_ok ? "converged" : "not converged")
118 << " at t = " << std::setprecision(2) << vel_time << " s, timeout " << kTimeout
119 << " s)\n";
120 mj_kdl::cleanup(&env);
121 return headless ? ex::verdict(pos_ok && vel_ok, "both motions reached their goal") : 0;
122}
unsigned int getNrOfJoints() const
int main(int argc, char *argv[])
ResetInfo reset(Env *env, const ResetOptions *options=nullptr)
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)
Status open_viewer(Env *env, const char *title="MuJoCo")
void pace_realtime(Env *env)
std::string asset(const fs::path &relative)
double clamp_abs(double v, double limit)
Definition common.hpp:66
double clamp01(double v)
Definition common.hpp:64
int verdict(bool ok, const std::string &goal)
Definition common.hpp:58
mj_kdl::SceneSpec scene_spec()
Definition common.hpp:138
KDL::JntArray home_q(unsigned n)
Definition common.hpp:68
Args parse_args(int argc, char **argv, const std::string &default_record_path="")
Definition common.hpp:41
ResetHook on_reset
std::vector< double > jnt_vel_cmd
std::vector< double > jnt_pos_cmd
std::vector< double > jnt_pos_msr
std::vector< CtrlModeSpec > modes
std::vector< RobotSpec > robots