5#include <kdl/chaindynparam.hpp>
6#include <kdl/chainfksolverpos_recursive.hpp>
7#include <kdl/chainiksolvervel_wdls.hpp>
22constexpr double kHomePose[7] = { 0.0, 0.2618, 3.1416, -2.2689, 0.0, 0.9599, 1.5708 };
25constexpr double kKp[7] = { 100, 200, 100, 200, 100, 200, 100 };
26constexpr double kKd[7] = { 10, 20, 10, 20, 10, 20, 10 };
30constexpr double kPickXY[2] = { 0.40, 0.00 };
41inline Args parse_args(
int argc,
char **argv,
const std::string &default_record_path =
"")
45 for (
int i = 1; i < argc; ++i) {
46 const std::string arg = argv[i];
47 if (arg ==
"--headless") {
49 }
else if (arg ==
"--record") {
52 if (i + 1 < argc && argv[i + 1][0] !=
'-') args.
record_path = argv[++i];
58inline int verdict(
bool ok,
const std::string &goal)
60 std::cout << (ok ?
"PASS: " :
"FAIL: ") << goal <<
"\n";
64inline double clamp01(
double v) {
return std::clamp(v, 0.0, 1.0); }
66inline double clamp_abs(
double v,
double limit) {
return std::clamp(v, -limit, limit); }
71 for (
unsigned i = 0; i < n; ++i) q(i) =
kHomePose[i];
77 for (
unsigned i = 0; i < a.
rows(); ++i) out(i) = a(i) + t * (b(i) - a(i));
87 for (
unsigned i = 0; i < q.
rows(); ++i) {
96 for (
unsigned i = 0; i < q.
rows(); ++i)
97 max_err = std::max(max_err, std::abs(q(i) - robot.
jnt_pos_msr[i]));
116 const double *kp =
nullptr,
117 const double *kd =
nullptr
124 for (
unsigned i = 0; i < n; ++i) {
162 tool.
tool_body = prefix +
"g_base_mount";
171 table.
name =
"table";
172 table.mjcf_path = path;
173 table.pos[2] = surface_z;
186 for (
int k = 0; k < 3; ++k) cube.
size[k] =
kCubeHS;
187 const float rgba[4] = { 0.1f, 0.35f, 1.0f, 1.0f };
188 std::copy(rgba, rgba + 4, cube.
rgba);
213 const auto error = [&] {
218 const auto converged = [](
const KDL::Twist &dx) {
219 return dx.vel.Norm() <= 2e-3 && dx.rot.Norm() <= 2e-2;
223 for (
int iter = 0; iter < 300; ++iter) {
225 if (converged(dx))
return true;
227 const double vel_norm = dx.
vel.
Norm();
228 if (vel_norm > 0.05) dx.
vel = dx.
vel * (0.05 / vel_norm);
229 const double rot_norm = dx.
rot.
Norm();
230 if (rot_norm > 0.20) dx.
rot = dx.
rot * (0.20 / rot_norm);
232 if (ik_vel.
CartToJnt(out, dx, dq) < 0)
return false;
233 for (
unsigned i = 0; i < out.
rows(); ++i) {
236 out(i) = std::clamp(out(i) + dq(i), lo, hi);
239 return converged(error());
257 const double z_grasp =
kCubeHS;
265 const Target targets[] = {
272 for (
const Target &t : targets) {
275 std::cerr <<
"IK failed for [" << t.xy[0] <<
", " << t.xy[1] <<
", " << t.z <<
"]\n";
296 {
"HOME", &w.
home, 1.0, 2.5, 0.08, 0.0 },
297 {
"PICK_ABOVE", &w.
pick_above, 5.0, 7.0, 0.08, 0.0 },
298 {
"PICK", &w.
pick, 5.0, 8.0, 0.03, 0.0 },
303 {
"OPEN", &w.
place, 1.0, 2.0, -1.0, 0.0 },
304 {
"RETREAT", &w.
place_above, 2.0, 4.0, 0.08, 0.0 },
321 const std::vector<PhaseArm> &arms,
322 const std::vector<Phase> &phases,
324 const std::function<
void(std::size_t,
const KDL::JntArray &)> &control,
325 const std::function<
void(
const Phase &,
double t_rel)> &after_step = {}
328 const unsigned n = arms.front().robot->chain.getNrOfJoints();
329 std::vector<KDL::JntArray> q_enter(arms.size(),
KDL::JntArray(n));
333 for (
const Phase &phase : phases) {
334 std::cout <<
"State: " << phase.name <<
"\n";
335 const double t_enter = env.
data->time;
336 for (std::size_t i = 0; i < arms.size(); ++i)
read_q(*arms[i].robot, q_enter[i]);
339 const double t_rel = env.
data->time - t_enter;
340 const double alpha = phase.duration > 0.0 ?
clamp01(t_rel / phase.duration) : 1.0;
342 for (std::size_t i = 0; i < arms.size(); ++i) {
343 lerp_q(q_enter[i], *phase.target, alpha, q_des);
345 arms[i].gripper->command = phase.gripper_cmd;
349 const bool done_pose = phase.settle_tol < 0.0 || err <= phase.settle_tol;
350 const bool done_timeout = phase.timeout > 0.0 && t_rel >= phase.timeout;
351 if ((t_rel >= phase.duration && done_pose) || done_timeout)
break;
356 if (after_step) after_step(phase, t_rel);
virtual int JntToGravity(const JntArray &q, JntArray &gravity)
virtual int JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr=-1)
void setLambda(const double lambda)
virtual int CartToJnt(const JntArray &q_in, const Twist &v_in, JntArray &qdot_out)
unsigned int getNrOfJoints() const
unsigned int rows() const
double Norm(double eps=epsilon) const
void set_body_pose(Env *env, const char *body_name, const double pos[3], const double *quat=nullptr)
void pace_realtime(Env *env)
IMETHOD Vector diff(const Vector &p_w_a, const Vector &p_w_b, double dt=1)
double clamp_abs(double v, double limit)
bool solve_pick_place(const mj_kdl::Robot &robot, PickPlaceWaypoints &w)
constexpr double kGripperClosed
int verdict(bool ok, const std::string &goal)
mj_kdl::SceneSpec scene_spec()
mj_kdl::ToolFrameSpec gripper_tool(const std::string &prefix="")
double max_abs_joint_err(const mj_kdl::Robot &robot, const KDL::JntArray &q)
std::vector< Phase > pick_place_phases(const PickPlaceWaypoints &w)
KDL::Frame tcp_frame(KDL::ChainFkSolverPos_recursive &fk, const mj_kdl::Robot &robot)
constexpr double kPickXY[2]
mj_kdl::AttachmentSpec gripper_attachment(const std::string &path, const std::string &site="pinch_site")
constexpr double kHomePose[7]
constexpr double kPlaceXY[2]
KDL::JntArray home_q(unsigned n)
void read_q(const mj_kdl::Robot &robot, KDL::JntArray &q)
void pd_gravity(mj_kdl::Robot &robot, KDL::ChainDynParam &dyn, const KDL::JntArray &q_des, const double *kp=nullptr, const double *kd=nullptr)
void place_cube(mj_kdl::Env &env)
mj_kdl::SceneObject table_object(const std::string &path, double surface_z)
bool solve_near_seed(KDL::ChainIkSolverVel_wdls &ik_vel, KDL::ChainFkSolverPos_recursive &fk, const mj_kdl::Robot &robot, const KDL::JntArray &seed, const KDL::Frame &target, KDL::JntArray &out)
void prime_gravity(mj_kdl::Robot &robot, KDL::ChainDynParam &dyn, const KDL::JntArray &q)
void lerp_q(const KDL::JntArray &a, const KDL::JntArray &b, double t, KDL::JntArray &out)
bool run_phases(mj_kdl::Env &env, const std::vector< PhaseArm > &arms, const std::vector< Phase > &phases, bool &restart, const std::function< void(std::size_t, const KDL::JntArray &)> &control, const std::function< void(const Phase &, double t_rel)> &after_step={})
Args parse_args(int argc, char **argv, const std::string &default_record_path="")
mj_kdl::SceneObject cube_object(double x, double y, double surface_z)
std::vector< double > jnt_vel_msr
std::vector< double > jnt_pos_msr
std::vector< double > jnt_trq_cmd
std::vector< std::pair< double, double > > joint_limits
mj_kdl::SceneActuatorSlot * gripper
const KDL::JntArray * target
KDL::JntArray place_above