142 bool headless =
false;
143 for (
int i = 1; i < argc; ++i)
144 if (std::string(argv[i]) ==
"--headless") headless =
true;
146 const fs::path root = repo_root();
147 const std::string arm_mjcf = (root /
"third_party/menagerie/kinova_gen3/gen3.xml").
string();
148 const std::string grp_mjcf = (root /
"third_party/menagerie/robotiq_2f85/2f85.xml").
string();
149 const std::string table_mjcf = (root /
"src/examples/assets/table.xml").
string();
155 gripper.
pos[2] = -0.061525;
156 gripper.
euler[0] = 180.0;
159 robot_spec.
path = arm_mjcf.c_str();
160 robot_spec.
pos[2] = kTableZ;
164 scene.
robots.push_back(robot_spec);
167 .mjcf_path = table_mjcf,
168 .pos = { 0.0, 0.0, kTableZ },
172 mjModel *model =
nullptr;
173 mjData *data =
nullptr;
183 const unsigned n = robot.
chain.getNrOfJoints();
184 const unsigned ns = robot.
chain.getNrOfSegments();
185 KDL::JntArray q_start(n);
186 for (
unsigned i = 0; i < n; ++i) q_start(i) = kTablePose[i];
200 print_contact_heights(model, data);
202 KDL::ChainFkSolverPos_recursive fk_pos(robot.
chain);
205 KDL::JntArray q(n), qd(n);
206 fill_q_state(robot, q, qd);
207 fk_pos.JntToCart(q, target);
208 KDL::Frame tracked = target;
209 target.p += KDL::Vector(kMoveX, 0.0, 0.0);
211 KDL::Twist root_acc(KDL::Vector(0.0, 0.0, -scene.
gravity_z), KDL::Vector::Zero());
212 KDL::ChainHdSolver_Vereshchagin_Fixed_Joint achd(robot.
chain, root_acc, 5);
213 KDL::ChainIdSolver_RNE rnea(robot.
chain, KDL::Vector(0.0, 0.0, scene.
gravity_z));
215 KDL::JntArray qdd(n), beta(5), ff_tau(n), constraint_tau(n), tau_cmd(n);
216 KDL::Wrenches f_ext_achd(ns, KDL::Wrench::Zero());
217 KDL::Wrenches f_ext_rnea_zero(ns, KDL::Wrench::Zero());
218 KDL::Jacobian alpha(5);
219 set_alpha_no_linear_z(alpha);
224 fill_q_state(robot, q, qd);
225 KDL::Frame cmp_current;
226 fk_pos.JntToCart(q, cmp_current);
227 const KDL::Twist cmp_err = KDL::diff(cmp_current, target);
229 KDL::ChainHdSolver_Vereshchagin_Fixed_Joint achd6(robot.
chain, root_acc, 6);
230 KDL::JntArray qdd6(n), beta6(6), ff6(n), ctau6(n), tau6(n);
231 KDL::Jacobian alpha6(6);
232 alpha6.setColumn(0, KDL::Twist(KDL::Vector(1, 0, 0), KDL::Vector(0, 0, 0)));
233 alpha6.setColumn(1, KDL::Twist(KDL::Vector(0, 1, 0), KDL::Vector(0, 0, 0)));
234 alpha6.setColumn(2, KDL::Twist(KDL::Vector(0, 0, 1), KDL::Vector(0, 0, 0)));
235 alpha6.setColumn(3, KDL::Twist(KDL::Vector(0, 0, 0), KDL::Vector(1, 0, 0)));
236 alpha6.setColumn(4, KDL::Twist(KDL::Vector(0, 0, 0), KDL::Vector(0, 1, 0)));
237 alpha6.setColumn(5, KDL::Twist(KDL::Vector(0, 0, 0), KDL::Vector(0, 0, 1)));
238 beta6(0) = clamp_abs(kKpLin * cmp_err.vel.x(), kBetaMax);
239 beta6(1) = clamp_abs(kKpLin * cmp_err.vel.y(), kBetaMax);
240 beta6(2) = clamp_abs(kKpLin * cmp_err.vel.z(), kBetaMax);
241 beta6(3) = clamp_abs(kKpRot * cmp_err.rot.x(), kBetaMax);
242 beta6(4) = clamp_abs(kKpRot * cmp_err.rot.y(), kBetaMax);
243 beta6(5) = clamp_abs(kKpRot * cmp_err.rot.z(), kBetaMax);
245 achd6.CartToJnt(q, qd, qdd6, alpha6, beta6, f_ext_achd, ff6, ctau6);
246 rnea.CartToJnt(q, qd, qdd6, f_ext_rnea_zero, tau6);
247 std::cout <<
"\n--- nc=6 (lin Z constrained) ---\n";
248 print_array(
"beta6", beta6);
249 print_array(
"qdd6", qdd6);
250 print_array(
"constraint_tau6", ctau6);
251 print_array(
"tau_cmd6", tau6);
253 KDL::ChainHdSolver_Vereshchagin_Fixed_Joint achd5(robot.
chain, root_acc, 5);
254 KDL::JntArray qdd5(n), beta5(5), ff5(n), ctau5(n), tau5(n);
255 KDL::Jacobian alpha5(5);
256 set_alpha_no_linear_z(alpha5);
257 beta5(0) = clamp_abs(kKpLin * cmp_err.vel.x(), kBetaMax);
258 beta5(1) = clamp_abs(kKpLin * cmp_err.vel.y(), kBetaMax);
259 beta5(2) = clamp_abs(kKpRot * cmp_err.rot.x(), kBetaMax);
260 beta5(3) = clamp_abs(kKpRot * cmp_err.rot.y(), kBetaMax);
261 beta5(4) = clamp_abs(kKpRot * cmp_err.rot.z(), kBetaMax);
263 achd5.CartToJnt(q, qd, qdd5, alpha5, beta5, f_ext_achd, ff5, ctau5);
264 rnea.CartToJnt(q, qd, qdd5, f_ext_rnea_zero, tau5);
265 std::cout <<
"\n--- nc=5 (lin Z free) ---\n";
266 print_array(
"beta5", beta5);
267 print_array(
"qdd5", qdd5);
268 print_array(
"constraint_tau5", ctau5);
269 print_array(
"tau_cmd5", tau5);
273 std::array<double, 5> err_prev{};
274 bool first_pid =
true;
276 double prev_sim_time = data->time;
278 auto reset_scene = [&]() {
281 fill_q_state(robot, q, qd);
282 fk_pos.JntToCart(q, tracked);
286 prev_sim_time = data->time;
289 auto step_control = [&]() {
290 const double dt = robot.
model->opt.timestep;
291 const KDL::Vector to_goal = target.p - tracked.p;
292 const double dist = to_goal.Norm();
294 tracked.p += (to_goal / dist) * std::min(dist, kVMaxLin * dt);
295 const bool print_debug = headless && step_count == 0;
296 bool ok = control_step(
297 robot, fk_pos, achd, rnea, tracked, q, qd, qdd, alpha, beta, f_ext_achd,
298 f_ext_rnea_zero, ff_tau, constraint_tau, tau_cmd, err_prev, first_pid,
306 for (
int i = 0; i < 2000; ++i) {
310 fill_q_state(robot, q, qd);
312 fk_pos.JntToCart(q, current);
313 KDL::Twist err = KDL::diff(current, target);
314 print_contact_heights(model, data);
315 print_array(
"final_achd_constraint_tau", constraint_tau);
316 print_array(
"final_rnea_full_tau_cmd", tau_cmd);
317 std::cout <<
"tcp_xy_err_mm=" << std::fixed << std::setprecision(3)
318 << std::sqrt(err.vel.x() * err.vel.x() + err.vel.y() * err.vel.y()) * 1000.0
319 <<
" tcp_z_error_unconstrained_mm=" << err.vel.z() * 1000.0
320 <<
" tcp_rot_err_rad=" << err.rot.Norm() <<
"\n";
325 if (data->time < prev_sim_time - 1e-6)
327 prev_sim_time = data->time;