Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/ik panda #340

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
107 changes: 102 additions & 5 deletions gtdynamics/kinematics/Kinematics.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <gtdynamics/universal_robot/Robot.h>
#include <gtdynamics/utils/Interval.h>
#include <gtdynamics/utils/PointOnLink.h>
#include <gtdynamics/utils/PoseOnLink.h>
#include <gtsam/geometry/Point3.h>
#include <gtsam/geometry/Pose3.h>
#include <gtsam/nonlinear/LevenbergMarquardtParams.h>
Expand Down Expand Up @@ -65,6 +66,56 @@ struct ContactGoal {
///< Map of link name to ContactGoal
using ContactGoals = std::vector<ContactGoal>;

/**
* Similar to the previous struct ContactGoal but with poses instead of
* points.
* Desired world pose for a end-effector pose.
*
* This simple struct stores the robot link that holds the end-effector, the
* end-effector's pose in the final link's CoM frame, and a `goal_pose` in
* world coordinate frames. The goal is satisfied iff
* `pose_on_link.predict(values, k) == goal_pose`.
*/
struct PoseGoal {
LinkSharedPtr ee_link; ///< Link that hold end-effector
gtsam::Pose3 comTee; ///< In link's CoM frame.
gtsam::Pose3 goal_pose; ///< In world frame.
Joobz marked this conversation as resolved.
Show resolved Hide resolved
Joobz marked this conversation as resolved.
Show resolved Hide resolved

/// Constructor
PoseGoal(const LinkSharedPtr& ee_link, const gtsam::Pose3& comTee,
const gtsam::Pose3& goal_pose)
: ee_link(ee_link), comTee(comTee), goal_pose(goal_pose) {}

/// Return link associated with contact pose.
const LinkSharedPtr& link() const { return ee_link; }

/// Return goal pose in ee_link COM frame.
const gtsam::Pose3& poseInCoM() const { return comTee; }

/// Return CoM pose needed to achieve goal pose.
const gtsam::Pose3 sTcom() const {
return goal_pose.compose(poseInCoM().inverse());
}

/// Print to stream.
friend std::ostream& operator<<(std::ostream& os, const PoseGoal& cg);

/// GTSAM-style print, works with wrapper.
void print(const std::string& s) const;

/**
* @fn Check that the contact goal has been achieved for given values.
* @param values a GTSAM Values instance that should contain link pose.
* @param k time step to check (default 0).
* @param tol tolerance in 3D (default 1e-9).
*/
bool satisfied(const gtsam::Values& values, size_t k = 0,
double tol = 1e-9) const;
};

///< Map of time to PoseGoal
using PoseGoals = std::map<size_t, PoseGoal>;
Comment on lines +112 to +113
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to have multiple pose goals for a single timestep? In which case maybe std::map<size_t, std::vector<PoseGoal>> would be more appropriate? Or if you don't need it I guess you can leave it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in the painting case, only one pose per timestep is necessary, I think having multiple poses per timestep on a 7-DoF doesn't make much sense as we would be over constraining the problem, right?


/// Noise models etc specific to Kinematics class
struct KinematicsParameters : public OptimizationParameters {
using Isotropic = gtsam::noiseModel::Isotropic;
Expand Down Expand Up @@ -131,29 +182,60 @@ class Kinematics : public Optimizer {
EqualityConstraints pointGoalConstraints(
const CONTEXT& context, const ContactGoals& contact_goals) const;

/**
* @fn Create a pose prior for a given link for each given pose.
* @param context Slice or Interval instance.
* @param pose_goals goals for poses
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are still not explaining what pose_goals is. size_t can be many things, what does it mean? Does it pertain to all contexts?

* @returns graph with pose goal factors.
*/
template <class CONTEXT>
gtsam::NonlinearFactorGraph poseGoalObjectives(
const CONTEXT& context, const PoseGoals& pose_goals) const;

/**
* @fn Factors that minimize joint angles.
* @param context Slice or Interval instance.
* @param robot Robot specification from URDF/SDF.
* @param joint_priors Values where the mean of the priors is specified. The
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment. You use Values. Does that mean in your case you specify different priors for every time step? Or, is it simply robot-specific in which case aa std::map with joint indices would be the right thing. I already commented on this but not getting ansers. And, answers should end up in the documentation...

* default is an empty Values, meaning that no means are specified.
Joobz marked this conversation as resolved.
Show resolved Hide resolved
* @returns graph with prior factors on joint angles.
*/
template <class CONTEXT>
gtsam::NonlinearFactorGraph jointAngleObjectives(const CONTEXT& context,
const Robot& robot) const;
gtsam::NonlinearFactorGraph jointAngleObjectives(
const CONTEXT& context, const Robot& robot,
const gtsam::Values& joint_priors = gtsam::Values()) const;
gchenfc marked this conversation as resolved.
Show resolved Hide resolved

/**
* @fn Factors that enforce joint angle limits.
* @param context Slice or Interval instance.
* @param robot Robot specification from URDF/SDF.
* @return graph with prior factors on joint angles.
*/
template <class CONTEXT>
gtsam::NonlinearFactorGraph jointAngleLimits(const CONTEXT& context,
const Robot& robot) const;

/**
* @fn Initialize kinematics.
*
* Use wTcom for poses and zero-mean noise for joint angles.
* If no values in initial_joints are given, use wTcom for poses and zero-mean
* noise for joint angles.
* If values are given, initialize joints with their given values, and
* zero-mean noise to the ones that without a given value. Poses are
* initialized with their fk values.
*
*
* @param context Slice or Interval instance.
* @param robot Robot specification from URDF/SDF.
* @param gaussian_noise time step to check (default 0.1).
* @param initial_joints initial values for joints
* @returns values with identity poses and zero joint angles.
*/
template <class CONTEXT>
gtsam::Values initialValues(const CONTEXT& context, const Robot& robot,
double gaussian_noise = 0.1) const;
gtsam::Values initialValues(
const CONTEXT& context, const Robot& robot, double gaussian_noise = 0.1,
const gtsam::Values& initial_joints = gtsam::Values(),
bool use_fk = false) const;

/**
* @fn Inverse kinematics given a set of contact goals.
Expand All @@ -169,6 +251,21 @@ class Kinematics : public Optimizer {
const ContactGoals& contact_goals,
bool contact_goals_as_constraints = true) const;

/**
* @fn Inverse kinematics given a set of desired poses
* @fn This function does inverse kinematics separately on each slice
* @param context Slice or Interval instance
* @param robot Robot specification from URDF/SDF
* @param pose_goals goals for EE poses
* @param joint_priors optional argument to put priors centered on given
* values. If empty, the priors will be centered on the origin
* @return values with poses and joint angles
*/
template <class CONTEXT>
gtsam::Values inverse(
const CONTEXT& context, const Robot& robot, const PoseGoals& pose_goals,
const gtsam::Values& joint_priors = gtsam::Values()) const;
gchenfc marked this conversation as resolved.
Show resolved Hide resolved

/**
* Interpolate using inverse kinematics: the goals are linearly interpolated.
* @param context Interval instance
Expand Down
31 changes: 26 additions & 5 deletions gtdynamics/kinematics/KinematicsInterval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ EqualityConstraints Kinematics::constraints<Interval>(
return constraints;
}

template <>
NonlinearFactorGraph Kinematics::poseGoalObjectives<Interval>(
const Interval& interval,
const PoseGoals& pose_goals) const {
NonlinearFactorGraph graph;
for (size_t k = interval.k_start; k <= interval.k_end; k++) {
graph.add(poseGoalObjectives(Slice(k), pose_goals));
}
return graph;
}

template <>
NonlinearFactorGraph Kinematics::pointGoalObjectives<Interval>(
const Interval& interval, const ContactGoals& contact_goals) const {
Expand All @@ -66,21 +77,31 @@ EqualityConstraints Kinematics::pointGoalConstraints<Interval>(

template <>
NonlinearFactorGraph Kinematics::jointAngleObjectives<Interval>(
const Interval& interval, const Robot& robot, const Values& mean) const {
NonlinearFactorGraph graph;
for (size_t k = interval.k_start; k <= interval.k_end; k++) {
graph.add(jointAngleObjectives(Slice(k), robot, mean));
}
return graph;
}

template <>
NonlinearFactorGraph Kinematics::jointAngleLimits<Interval>(
const Interval& interval, const Robot& robot) const {
NonlinearFactorGraph graph;
for (size_t k = interval.k_start; k <= interval.k_end; k++) {
graph.add(jointAngleObjectives(Slice(k), robot));
graph.add(jointAngleLimits(Slice(k), robot));
}
return graph;
}

template <>
Values Kinematics::initialValues<Interval>(const Interval& interval,
const Robot& robot,
double gaussian_noise) const {
Values Kinematics::initialValues<Interval>(
const Interval& interval, const Robot& robot, double gaussian_noise,
const gtsam::Values& joint_priors, bool use_fk) const {
Values values;
for (size_t k = interval.k_start; k <= interval.k_end; k++) {
values.insert(initialValues(Slice(k), robot, gaussian_noise));
values.insert(initialValues(Slice(k), robot, gaussian_noise, joint_priors, use_fk));
}
return values;
}
Expand Down
Loading