Mujoco KDL Wrapper  0.3.18
MuJoCo + KDL bridge for robot kinematics and dynamics
Loading...
Searching...
No Matches
ex_pick.cpp
Go to the documentation of this file.
1/* ex_pick.cpp
2 * Scripted pick-and-place: Kinova GEN3 + Robotiq 2F-85 picks an orange cube
3 * from the floor and lifts it.
4 *
5 * Joint impedance control law applied every step:
6 * tau_i = g_kdl_i + Kp*(q_des_i - q_i) - Kd*dq_i
7 * where g_kdl is computed via KDL::ChainDynParam::JntToGravity (includes gripper inertia).
8 *
9 * A state machine drives the arm through six states, each with its own
10 * while control loop:
11 * HOME -> PREGRASP -> GRASP -> CLOSE -> LIFT -> HOLD
12 *
13 * Requires MuJoCo Menagerie in cache.
14 *
15 * Usage:
16 * ex_pick [--headless]
17 *
18 * With --headless runs the full pick sequence and prints final cube height. */
19
21#include "example_paths.hpp"
22
23#include <kdl/chaindynparam.hpp>
24#include <kdl/chainfksolverpos_recursive.hpp>
25#include <kdl/chainiksolvervel_wdls.hpp>
26
27#include <algorithm>
28#include <cmath>
29#include <iomanip>
30#include <iostream>
31#include <string>
32#include <vector>
33
34// scene constants
35static constexpr double kHomePose[7] = { 0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708 };
36static constexpr double kCubeX = 0.4;
37static constexpr double kCubeY = 0.0;
38static constexpr double kCubeHS = 0.02; // half-size of 4 cm cube
39static constexpr double kCubeZ = kCubeHS;
40static constexpr double kIkTol = 2e-3;
41
42// impedance gains (per joint, matching ex_impedance tuning)
43static constexpr double kKp[7] = { 100, 200, 100, 200, 100, 200, 100 }; // Nm/rad
44static constexpr double kKd[7] = { 10, 20, 10, 20, 10, 20, 10 }; // Nm*s/rad
45
46// helpers
47static double clamp01(double v) { return std::max(0.0, std::min(1.0, v)); }
48
49static void lerp_q(const KDL::JntArray &a, const KDL::JntArray &b, double t, KDL::JntArray &out)
50{
51 for (unsigned i = 0; i < a.rows(); ++i) out(i) = a(i) + t * (b(i) - a(i));
52}
53
54static bool solve_near_seed(
55 KDL::ChainIkSolverVel_wdls &ik_vel,
56 KDL::ChainFkSolverPos_recursive &fk,
57 const KDL::JntArray &seed,
58 const KDL::Frame &target,
59 const std::vector<bool> &joint_limited,
60 const KDL::JntArray &q_min,
61 const KDL::JntArray &q_max,
62 KDL::JntArray &out
63)
64{
65 out = seed;
66 KDL::JntArray dq(out.rows());
67 for (int iter = 0; iter < 300; ++iter) {
68 KDL::Frame fk_out;
69 fk.JntToCart(out, fk_out);
70 KDL::Twist dx = KDL::diff(fk_out, target);
71 if (dx.vel.Norm() <= kIkTol && dx.rot.Norm() <= 2e-2) return true;
72
73 double vel_norm = dx.vel.Norm();
74 if (vel_norm > 0.05) dx.vel = dx.vel * (0.05 / vel_norm);
75 double rot_norm = dx.rot.Norm();
76 if (rot_norm > 0.20) dx.rot = dx.rot * (0.20 / rot_norm);
77
78 if (ik_vel.CartToJnt(out, dx, dq) < 0) return false;
79 for (unsigned i = 0; i < out.rows(); ++i) {
80 out(i) += dq(i);
81 if (joint_limited[i]) out(i) = std::max(q_min(i), std::min(q_max(i), out(i)));
82 }
83 }
84
85 KDL::Frame fk_out;
86 fk.JntToCart(out, fk_out);
87 KDL::Twist dx = KDL::diff(fk_out, target);
88 return dx.vel.Norm() <= kIkTol && dx.rot.Norm() <= 2e-2;
89}
90
91/*
92 * Compute joint impedance torques into robot.jnt_trq_cmd:
93 * tau_i = g_kdl[i] + Kp[i]*(q_des_i - q_msr_i) - Kd[i]*dq_msr_i
94 * dyn must have been built from the chain returned by init_robot_from_mjcf with tool_body set.
95 */
96static void impedance_ctrl(
97 mj_kdl::Robot &robot,
98 const KDL::JntArray &q_des,
99 unsigned n,
100 KDL::ChainDynParam &dyn
101)
102{
103 KDL::JntArray q(n), g(n);
104 for (unsigned i = 0; i < n; ++i) q(i) = robot.jnt_pos_msr[i];
105 dyn.JntToGravity(q, g);
106 for (unsigned i = 0; i < n; ++i) {
107 robot.jnt_trq_cmd[i] =
108 g(i) + kKp[i] * (q_des(i) - robot.jnt_pos_msr[i]) - kKd[i] * robot.jnt_vel_msr[i];
109 }
110}
111
112// Copy the current measured joint positions into q.
113static void snapshot_q(const mj_kdl::Robot &robot, unsigned n, KDL::JntArray &q)
114{
115 for (unsigned i = 0; i < n; ++i) q(i) = robot.jnt_pos_msr[i];
116}
117
118static double max_abs_joint_err(const mj_kdl::Robot &robot, const KDL::JntArray &q_des, unsigned n)
119{
120 double max_err = 0.0;
121 for (unsigned i = 0; i < n; ++i)
122 max_err = std::max(max_err, std::abs(q_des(i) - robot.jnt_pos_msr[i]));
123 return max_err;
124}
125
126// state machine
128
129/*
130 * Static description of one state: how long to stay, which joint target to
131 * track (pointer into the IK-solved arrays), gripper command, and successor.
132 */
134{
135 double duration; // nominal interpolation time
136 double timeout; // force transition if settling runs long
137 double settle_tol; // rad, < 0 disables pose check
138 const KDL::JntArray *q_target; // interpolation goal (set after IK)
139 double gripper_cmd; // 0=open, 0.8=fully closed
141};
142
143/*
144 * Mutable context updated on every state transition.
145 * q_enter is the measured joint position when the state was entered;
146 * the setpoint is linearly interpolated from q_enter to q_target over duration.
147 */
149{
151 double t_enter = 0.0;
152 KDL::JntArray q_enter;
153};
154
155int main(int argc, char *argv[])
156{
157 bool headless = false;
158 for (int i = 1; i < argc; ++i)
159 if (std::string(argv[i]) == "--headless") headless = true;
160
161 // scene setup
162 const std::string arm_mjcf = mj_kdl_examples::menagerie_model("kinova_gen3/gen3.xml");
163 const std::string grp_mjcf = mj_kdl_examples::asset("robotiq_2f85/2f85.xml");
164
166 gs.mjcf_path = grp_mjcf.c_str();
167 gs.attach_to = { mj_kdl::AttachKind::Site, "pinch_site" };
168 gs.prefix = "g_";
169
171 rs.path = arm_mjcf.c_str();
172 rs.attachments.push_back(gs);
173
175 .name = "cube",
176 .mjcf_path = "",
177 .shape = mj_kdl::Shape::BOX,
178 .size = { kCubeHS, kCubeHS, kCubeHS },
179 .pos = { kCubeX, kCubeY, kCubeZ },
180 .rgba = { 1.0f, 0.5f, 0.0f, 1.0f },
181 .mass = 0.1,
183 .friction = { 0.8, 0.02, 0.001 },
184 };
185
187 sc.timestep = 0.002;
188 sc.add_floor = true;
189 sc.add_skybox = true;
190 sc.robots.push_back(rs);
191 sc.objects.push_back(cube);
192
193 mjModel *model = nullptr;
194 mjData *data = nullptr;
195 if (!mj_kdl::build_scene(&model, &data, &sc)) {
196 std::cerr << "build_scene() failed\n";
197 return 1;
198 }
199
201 tool.tool_body = "g_base";
202 tool.tcp_site = "g_pinch";
203
204 mj_kdl::Robot robot;
206 &robot, model, data, "base_link", "bracelet_link", "", &tool
207 )) {
208 std::cerr << "init_robot_from_mjcf() failed\n";
209 mj_kdl::destroy_scene(model, data);
210 return 1;
211 }
212
213 unsigned n = robot.chain.getNrOfJoints();
214 int fingers_act = mj_name2id(model, mjOBJ_ACTUATOR, "g_fingers_actuator");
215 int cube_jnt = mj_name2id(model, mjOBJ_JOINT, "cube_joint");
216 int key_id = mj_name2id(model, mjOBJ_KEY, "home");
217
218 KDL::ChainDynParam dyn(robot.chain, KDL::Vector(0.0, 0.0, -9.81));
219
220 // IK setup
221 KDL::ChainFkSolverPos_recursive fk(robot.chain);
222 KDL::JntArray q_min(n), q_max(n);
223 std::vector<bool> joint_limited(n, false);
224 for (unsigned i = 0; i < n; ++i) {
225 int jid = model->dof_jntid[robot.kdl_to_mj_dof[i]];
226 if (model->jnt_limited[jid]) {
227 joint_limited[i] = true;
228 q_min(i) = model->jnt_range[2 * jid];
229 q_max(i) = model->jnt_range[2 * jid + 1];
230 } else {
231 q_min(i) = -2 * M_PI;
232 q_max(i) = 2 * M_PI;
233 }
234 }
235 KDL::ChainIkSolverVel_wdls ik_vel(robot.chain, 1e-5, 150);
236 ik_vel.setLambda(0.05);
237
238 KDL::JntArray q_home(n), q_pregrasp(n), q_grasp(n), q_lift(n);
239 for (unsigned i = 0; i < n; ++i) q_home(i) = kHomePose[i];
240 const double kGraspZ = kCubeZ;
241 const double kPreGraspZ = kGraspZ + 0.20;
242 const double kLiftZ = kGraspZ + 0.30;
243 const KDL::Rotation kGraspRot = robot.tip_T_tcp.M;
244
245 struct WP
246 {
247 double z;
248 KDL::JntArray *out;
249 const KDL::JntArray *seed;
250 };
251 WP wps[] = {
252 { kPreGraspZ, &q_pregrasp, &q_home },
253 { kGraspZ, &q_grasp, &q_pregrasp },
254 { kLiftZ, &q_lift, &q_grasp },
255 };
256 for (auto &wp : wps) {
257 KDL::Frame target(kGraspRot, KDL::Vector(kCubeX, kCubeY, wp.z));
258 if (!solve_near_seed(ik_vel, fk, *wp.seed, target, joint_limited, q_min, q_max, *wp.out)) {
259 std::cerr << "IK failed for z=" << wp.z << "\n";
260 mj_kdl::cleanup(&robot);
261 mj_kdl::destroy_scene(model, data);
262 return 1;
263 }
264 KDL::Frame fk_out;
265 fk.JntToCart(*wp.out, fk_out);
266 double pos_err = (target.p - fk_out.p).Norm();
267 if (pos_err > kIkTol) {
268 std::cerr << "IK pose error " << pos_err << " exceeds tolerance for z=" << wp.z << "\n";
269 mj_kdl::cleanup(&robot);
270 mj_kdl::destroy_scene(model, data);
271 return 1;
272 }
273 }
274 // state configuration table
275 /*
276 * HOLD duration is 1 s in headless mode (enough to verify the lift),
277 * and 10 s in GUI mode so the user has time to inspect the scene before
278 * the window auto-closes.
279 */
280 const double kHoldDuration = headless ? 1.0 : 10.0;
281
282 // clang-format off
283 const StateConfig state_cfg[] = {
284 { .duration = 1.0, .timeout = 2.5, .settle_tol = 0.08, .q_target = &q_home, .gripper_cmd = 0.0, .next = PickState::PREGRASP },
285 { .duration = 5.0, .timeout = 7.0, .settle_tol = 0.08, .q_target = &q_pregrasp, .gripper_cmd = 0.0, .next = PickState::GRASP },
286 { .duration = 5.0, .timeout = 8.0, .settle_tol = 0.03, .q_target = &q_grasp, .gripper_cmd = 0.0, .next = PickState::CLOSE },
287 { .duration = 1.5, .timeout = 2.5, .settle_tol = -1.0, .q_target = &q_grasp, .gripper_cmd = 0.8, .next = PickState::LIFT },
288 { .duration = 3.0, .timeout = 5.0, .settle_tol = 0.08, .q_target = &q_lift, .gripper_cmd = 0.8, .next = PickState::HOLD },
289 { .duration = kHoldDuration, .timeout = kHoldDuration, .settle_tol = -1.0, .q_target = &q_lift, .gripper_cmd = 0.8, .next = PickState::DONE },
290 { .duration = 0.0, .timeout = 0.0, .settle_tol = -1.0, .q_target = &q_lift, .gripper_cmd = 0.8, .next = PickState::DONE },
291 };
292 // clang-format on
293
294 auto cfg = [&](PickState s) -> const StateConfig & { return state_cfg[static_cast<int>(s)]; };
295
296 // initial conditions
297 auto reset_cube = [&](mjData *d) {
298 int qadr = model->jnt_qposadr[cube_jnt];
299 d->qpos[qadr + 0] = kCubeX;
300 d->qpos[qadr + 1] = kCubeY;
301 d->qpos[qadr + 2] = kCubeZ;
302 d->qpos[qadr + 3] = 1.0;
303 d->qpos[qadr + 4] = d->qpos[qadr + 5] = d->qpos[qadr + 6] = 0.0;
304 };
305
307
308 mj_kdl::Env env;
309 env.spec = sc;
310 env.model = model;
311 env.data = data;
312 mj_kdl::env_add_robot(&env, &robot);
313
314 mj_kdl::ResetOptions reset_opts;
315 reset_opts.use_keyframe = key_id >= 0;
316 reset_opts.keyframe = key_id >= 0 ? key_id : 0;
317
318 env.on_reset = [&](mj_kdl::ResetContext *ctx) {
319 if (key_id < 0) mj_kdl::set_joint_pos(&robot, q_home, false);
320 reset_cube(ctx->data);
321 if (fingers_act >= 0) ctx->data->ctrl[fingers_act] = 0.0;
322 };
323
324 mj_kdl::reset(&env, &reset_opts);
325
326 // GUI init (non-headless only)
327 mj_kdl::Viewer viewer;
328 if (!headless) {
329 if (!mj_kdl::init_window_sim(&viewer, &robot)) {
330 std::cerr << "init_window_sim() failed\n";
331 mj_kdl::cleanup(&robot);
332 mj_kdl::destroy_scene(model, data);
333 return 1;
334 }
335 }
336
337 StateMachine sm;
338 sm.q_enter = KDL::JntArray(n);
339
340 KDL::JntArray q_des(n);
341
342 auto begin_state = [&](PickState next) {
343 sm.state = next;
344 sm.t_enter = data->time;
345 snapshot_q(robot, n, sm.q_enter);
346 };
347
348 begin_state(PickState::HOME);
349
350 double prev_sim_time = data->time;
351
352 while (sm.state != PickState::DONE) {
353 switch (sm.state) {
354 case PickState::HOME:
355 std::cout << "State: HOME\n";
356 while (sm.state == PickState::HOME) {
357 if (data->time < prev_sim_time - 1e-6) {
358 mj_kdl::reset(&env, &reset_opts);
359 begin_state(PickState::HOME);
360 prev_sim_time = data->time;
361 continue;
362 }
363 prev_sim_time = data->time;
364
365 const StateConfig &state = cfg(sm.state);
366 double alpha = (state.duration > 0.0)
367 ? clamp01((data->time - sm.t_enter) / state.duration)
368 : 1.0;
369 lerp_q(sm.q_enter, *state.q_target, alpha, q_des);
370
371 // HOME uses the default joint-impedance controller.
372 impedance_ctrl(robot, q_des, n, dyn);
373 mj_kdl::update(&robot);
374 if (fingers_act >= 0) data->ctrl[fingers_act] = state.gripper_cmd;
375
376 double t_rel = data->time - sm.t_enter;
377 double pose_err = max_abs_joint_err(robot, *state.q_target, n);
378 bool done_time = t_rel >= state.duration;
379 bool done_pose = (state.settle_tol < 0.0) || (pose_err <= state.settle_tol);
380 bool done_timeout = (state.timeout > 0.0) && (t_rel >= state.timeout);
381 if ((done_time && done_pose) || done_timeout) {
382 begin_state(state.next);
383 break;
384 }
385
386 if (!mj_kdl::step(&robot)) {
387
388 mj_kdl::pace_realtime(&robot);
390 break;
391 }
392 }
393 break;
394
396 std::cout << "State: PREGRASP\n";
397 while (sm.state == PickState::PREGRASP) {
398 if (data->time < prev_sim_time - 1e-6) {
399 mj_kdl::reset(&env, &reset_opts);
400 begin_state(PickState::HOME);
401 prev_sim_time = data->time;
402 break;
403 }
404 prev_sim_time = data->time;
405
406 const StateConfig &state = cfg(sm.state);
407 double alpha = (state.duration > 0.0)
408 ? clamp01((data->time - sm.t_enter) / state.duration)
409 : 1.0;
410 lerp_q(sm.q_enter, *state.q_target, alpha, q_des);
411
412 // PREGRASP could swap in a different approach controller later.
413 impedance_ctrl(robot, q_des, n, dyn);
414 mj_kdl::update(&robot);
415 if (fingers_act >= 0) data->ctrl[fingers_act] = state.gripper_cmd;
416
417 double t_rel = data->time - sm.t_enter;
418 double pose_err = max_abs_joint_err(robot, *state.q_target, n);
419 bool done_time = t_rel >= state.duration;
420 bool done_pose = (state.settle_tol < 0.0) || (pose_err <= state.settle_tol);
421 bool done_timeout = (state.timeout > 0.0) && (t_rel >= state.timeout);
422 if ((done_time && done_pose) || done_timeout) {
423 begin_state(state.next);
424 break;
425 }
426
427 if (!mj_kdl::step(&robot)) {
428
429 mj_kdl::pace_realtime(&robot);
431 break;
432 }
433 }
434 break;
435
436 case PickState::GRASP:
437 std::cout << "State: GRASP\n";
438 while (sm.state == PickState::GRASP) {
439 if (data->time < prev_sim_time - 1e-6) {
440 mj_kdl::reset(&env, &reset_opts);
441 begin_state(PickState::HOME);
442 prev_sim_time = data->time;
443 break;
444 }
445 prev_sim_time = data->time;
446
447 const StateConfig &state = cfg(sm.state);
448 double alpha = (state.duration > 0.0)
449 ? clamp01((data->time - sm.t_enter) / state.duration)
450 : 1.0;
451 lerp_q(sm.q_enter, *state.q_target, alpha, q_des);
452
453 // GRASP keeps the same structure but can use contact-aware logic later.
454 impedance_ctrl(robot, q_des, n, dyn);
455 mj_kdl::update(&robot);
456 if (fingers_act >= 0) data->ctrl[fingers_act] = state.gripper_cmd;
457
458 double t_rel = data->time - sm.t_enter;
459 double pose_err = max_abs_joint_err(robot, *state.q_target, n);
460 bool done_time = t_rel >= state.duration;
461 bool done_pose = (state.settle_tol < 0.0) || (pose_err <= state.settle_tol);
462 bool done_timeout = (state.timeout > 0.0) && (t_rel >= state.timeout);
463 if ((done_time && done_pose) || done_timeout) {
464 begin_state(state.next);
465 break;
466 }
467
468 if (!mj_kdl::step(&robot)) {
469
470 mj_kdl::pace_realtime(&robot);
472 break;
473 }
474 }
475 break;
476
477 case PickState::CLOSE:
478 std::cout << "State: CLOSE\n";
479 while (sm.state == PickState::CLOSE) {
480 if (data->time < prev_sim_time - 1e-6) {
481 mj_kdl::reset(&env, &reset_opts);
482 begin_state(PickState::HOME);
483 prev_sim_time = data->time;
484 break;
485 }
486 prev_sim_time = data->time;
487
488 const StateConfig &state = cfg(sm.state);
489 double alpha = (state.duration > 0.0)
490 ? clamp01((data->time - sm.t_enter) / state.duration)
491 : 1.0;
492 lerp_q(sm.q_enter, *state.q_target, alpha, q_des);
493
494 // CLOSE could switch to a grasp-force controller instead of pure impedance.
495 impedance_ctrl(robot, q_des, n, dyn);
496 mj_kdl::update(&robot);
497 if (fingers_act >= 0) data->ctrl[fingers_act] = state.gripper_cmd;
498
499 double t_rel = data->time - sm.t_enter;
500 double pose_err = max_abs_joint_err(robot, *state.q_target, n);
501 bool done_time = t_rel >= state.duration;
502 bool done_pose = (state.settle_tol < 0.0) || (pose_err <= state.settle_tol);
503 bool done_timeout = (state.timeout > 0.0) && (t_rel >= state.timeout);
504 if ((done_time && done_pose) || done_timeout) {
505 begin_state(state.next);
506 break;
507 }
508
509 if (!mj_kdl::step(&robot)) {
510
511 mj_kdl::pace_realtime(&robot);
513 break;
514 }
515 }
516 break;
517
518 case PickState::LIFT:
519 std::cout << "State: LIFT\n";
520 while (sm.state == PickState::LIFT) {
521 if (data->time < prev_sim_time - 1e-6) {
522 mj_kdl::reset(&env, &reset_opts);
523 begin_state(PickState::HOME);
524 prev_sim_time = data->time;
525 break;
526 }
527 prev_sim_time = data->time;
528
529 const StateConfig &state = cfg(sm.state);
530 double alpha = (state.duration > 0.0)
531 ? clamp01((data->time - sm.t_enter) / state.duration)
532 : 1.0;
533 lerp_q(sm.q_enter, *state.q_target, alpha, q_des);
534
535 // LIFT could use a stiffer transport controller if needed.
536 impedance_ctrl(robot, q_des, n, dyn);
537 mj_kdl::update(&robot);
538 if (fingers_act >= 0) data->ctrl[fingers_act] = state.gripper_cmd;
539
540 double t_rel = data->time - sm.t_enter;
541 double pose_err = max_abs_joint_err(robot, *state.q_target, n);
542 bool done_time = t_rel >= state.duration;
543 bool done_pose = (state.settle_tol < 0.0) || (pose_err <= state.settle_tol);
544 bool done_timeout = (state.timeout > 0.0) && (t_rel >= state.timeout);
545 if ((done_time && done_pose) || done_timeout) {
546 begin_state(state.next);
547 break;
548 }
549
550 if (!mj_kdl::step(&robot)) {
551
552 mj_kdl::pace_realtime(&robot);
554 break;
555 }
556 }
557 break;
558
559 case PickState::HOLD:
560 std::cout << "State: HOLD\n";
561 while (sm.state == PickState::HOLD) {
562 if (data->time < prev_sim_time - 1e-6) {
563 mj_kdl::reset(&env, &reset_opts);
564 begin_state(PickState::HOME);
565 prev_sim_time = data->time;
566 break;
567 }
568 prev_sim_time = data->time;
569
570 const StateConfig &state = cfg(sm.state);
571 double alpha = (state.duration > 0.0)
572 ? clamp01((data->time - sm.t_enter) / state.duration)
573 : 1.0;
574 lerp_q(sm.q_enter, *state.q_target, alpha, q_des);
575
576 // HOLD can later become a dedicated grasp-maintenance controller.
577 impedance_ctrl(robot, q_des, n, dyn);
578 mj_kdl::update(&robot);
579 if (fingers_act >= 0) data->ctrl[fingers_act] = state.gripper_cmd;
580
581 double t_rel = data->time - sm.t_enter;
582 double pose_err = max_abs_joint_err(robot, *state.q_target, n);
583 bool done_time = t_rel >= state.duration;
584 bool done_pose = (state.settle_tol < 0.0) || (pose_err <= state.settle_tol);
585 bool done_timeout = (state.timeout > 0.0) && (t_rel >= state.timeout);
586 if ((done_time && done_pose) || done_timeout) {
587 begin_state(state.next);
588 break;
589 }
590
591 if (!mj_kdl::step(&robot)) {
592
593 mj_kdl::pace_realtime(&robot);
595 break;
596 }
597 }
598 break;
599
600 case PickState::DONE:
601 break;
602 }
603 }
604
605 if (headless) {
606 int qadr = model->jnt_qposadr[cube_jnt];
607 double cube_z = data->qpos[qadr + 2];
608 std::cout << "cube Z after pick: " << std::fixed << std::setprecision(3) << cube_z
609 << " m\n";
610 } else {
611 mj_kdl::cleanup(&viewer);
612 }
613
614 mj_kdl::cleanup(&robot);
615 mj_kdl::destroy_scene(model, data);
616 return 0;
617}
int main(int argc, char *argv[])
Definition ex_pick.cpp:155
PickState
Definition ex_pick.cpp:127
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")
void pace_realtime(Viewer *v, const mjModel *m)
std::string asset(const fs::path &relative)
std::string menagerie_model(const fs::path &relative)
double timeout
Definition ex_pick.cpp:136
const KDL::JntArray * q_target
Definition ex_pick.cpp:138
double settle_tol
Definition ex_pick.cpp:137
PickState next
Definition ex_pick.cpp:140
double gripper_cmd
Definition ex_pick.cpp:139
double duration
Definition ex_pick.cpp:135
double t_enter
Definition ex_pick.cpp:151
KDL::JntArray q_enter
Definition ex_pick.cpp:152
PickState state
Definition ex_pick.cpp:150
ResetHook on_reset
std::vector< AttachmentSpec > attachments
std::vector< int > kdl_to_mj_dof
std::vector< double > jnt_pos_msr
std::vector< double > jnt_vel_msr
std::vector< double > jnt_trq_cmd
KDL::Frame tip_T_tcp
std::vector< RobotSpec > robots
std::vector< SceneObject > objects