18#include <kdl/chainjnttojacsolver.hpp>
28static constexpr double kMaxPlaceErr = 0.005;
30static constexpr const char *kPushBody =
"bracelet_link";
31static constexpr const char *kPushPhase =
"PLACE_ABOVE";
32static constexpr double kPushForce = 20.0;
33static constexpr double kPushOn = 0.8;
34static constexpr double kPushOff = 2.0;
35static constexpr double kPushRamp = 0.2;
36static constexpr double kSettle = 0.5;
38static constexpr double kMinDeflection = 0.010;
39static constexpr double kDeflectionRatio[] = { 0.85, 1.15 };
40static constexpr double kMaxResidual = 0.004;
41static constexpr double kMaxCubeSlip = 0.010;
42static constexpr double kMinElbowHeight = 0.45;
54static double push_scale(
double t_rel)
61int main(
int argc,
char *argv[])
71 scene.
robots.push_back(robot_spec);
86 if (!fingers || !cube || !push)
return 1;
100 bool restart =
false;
104 ctx->data->ctrl[fingers->
ctrl_id] = 0.0;
112 const auto control = [&](std::size_t,
const KDL::JntArray &q_des) {
117 const auto after_step = [&](
const ex::Phase &phase,
double t_rel) {
121 const bool pushing = std::string(phase.
name) == kPushPhase;
122 const KDL::Vector force = push_dir * (pushing ? kPushForce * push_scale(t_rel) : 0.0);
124 if (!pushing)
return;
132 if (t_rel < kPushOn) m.
lag0 = lag;
133 const double deflection =
KDL::dot(lag - m.
lag0, push_dir);
134 if (t_rel >= kPushOff + kSettle && m.
residual < 0.0) m.
residual = std::abs(deflection);
136 const bool full = t_rel >= kPushOn + kPushRamp && t_rel <= kPushOff - kPushRamp;
137 if (!full || deflection <= m.
peak)
return;
141 const double *com = env.
data->xipos + 3 * push->
body_id;
145 for (
unsigned i = 0; i < n; ++i)
160 std::cout << std::fixed << std::setprecision(4) <<
"cube final position: [" << c.
x() <<
", "
161 << c.
y() <<
", " << c.
z() <<
"] place error " << place_xy * 1000.0 <<
" mm (limit "
162 << kMaxPlaceErr * 1000.0 <<
" mm)" << (on_table ?
"" :
", not on the table") <<
"\n"
163 <<
"push deflection: " << m.
peak * 1000.0 <<
" mm (at least "
164 << kMinDeflection * 1000.0 <<
" mm), stiffness predicts " << m.
predicted * 1000.0
165 <<
" mm, ratio " << ratio <<
" (limits " << kDeflectionRatio[0] <<
".."
166 << kDeflectionRatio[1] <<
")\n"
167 <<
"deflection " << kSettle <<
" s after the push: " << m.
residual * 1000.0
168 <<
" mm (limit " << kMaxResidual * 1000.0 <<
" mm)\n"
169 <<
"cube from the TCP while pushed: " << m.
cube_slip * 1000.0 <<
" mm (limit "
170 << kMaxCubeSlip * 1000.0 <<
" mm)\n"
171 <<
"lowest elbow above the table: " << elbow_h * 1000.0 <<
" mm (limit "
172 << kMinElbowHeight * 1000.0 <<
" mm)\n";
174 const bool ok = completed && on_table && place_xy <= kMaxPlaceErr && m.
peak >= kMinDeflection
175 && ratio >= kDeflectionRatio[0] && ratio <= kDeflectionRatio[1]
177 && m.
cube_slip <= kMaxCubeSlip && elbow_h >= kMinElbowHeight;
178 return headless ?
ex::verdict(ok,
"the cube was placed through the push") : 0;
virtual int JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr=-1)
virtual int JntToJac(const JntArray &q_in, Jacobian &jac, int seg_nr=-1)
unsigned int getNrOfJoints() const
void changeRefPoint(const Vector &base_AB)
Twist getColumn(unsigned int i) const
int main(int argc, char *argv[])
ResetInfo reset(Env *env, const ResetOptions *options=nullptr)
Status init_env(Env *env, const SceneSpec *spec)
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)
bool get_body_frame(Env *env, const char *body_name, KDL::Frame *out)
SceneWrenchSlot * bind_scene_wrench(SceneState *s, const char *body_name)
SceneActuatorSlot * bind_scene_actuator(SceneState *s, const char *name)
SceneFreeBodySlot * bind_scene_free_body(SceneState *s, const char *body_name)
Status open_viewer(Env *env, const char *title="MuJoCo")
doubleAcc dot(const VectorAcc &lhs, const VectorAcc &rhs)
std::string asset(const fs::path &relative)
bool solve_pick_place(const mj_kdl::Robot &robot, PickPlaceWaypoints &w)
int verdict(bool ok, const std::string &goal)
mj_kdl::SceneSpec scene_spec()
mj_kdl::ToolFrameSpec gripper_tool(const std::string &prefix="")
std::vector< Phase > pick_place_phases(const PickPlaceWaypoints &w)
constexpr double kPickXY[2]
mj_kdl::AttachmentSpec gripper_attachment(const std::string &path, const std::string &site="pinch_site")
constexpr double kPlaceXY[2]
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)
void prime_gravity(mj_kdl::Robot &robot, KDL::ChainDynParam &dyn, const KDL::JntArray &q)
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< AttachmentSpec > attachments
std::vector< RobotSpec > robots
std::vector< SceneObject > objects