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

Use angle between quaternions in OrientationGoal? #31

Open
AndyZe opened this issue May 12, 2021 · 2 comments
Open

Use angle between quaternions in OrientationGoal? #31

AndyZe opened this issue May 12, 2021 · 2 comments

Comments

@AndyZe
Copy link

AndyZe commented May 12, 2021

Currently the orientation goal looks like this:

    virtual double evaluate(const GoalContext& context) const
    {
        // return getOrientation().distance2(context.getLinkFrame().getOrientation());
        // return (getOrientation() - getOrientation().nearest(context.getLinkFrame().getOrientation())).length2();
        return fmin((getOrientation() - context.getLinkFrame().getOrientation()).length2(), (getOrientation() + context.getLinkFrame().getOrientation()).length2());
        /*return
            (getOrientation() - context.getLinkFrame().getOrientation()).length2() *
            (getOrientation() + context.getLinkFrame().getOrientation()).length2() * 0.5;*/
    }

I don't know a ton about quaternions but this seems like a nonlinear function so it might behave kind of funky: (getOrientation() - context.getLinkFrame().getOrientation()).length2()

Would it be better to use the angle between the quaternions? That would increase in a nice, linear fashion from 0 to pi.

angle

https://math.stackexchange.com/a/90098/448782

@AndyZe
Copy link
Author

AndyZe commented May 12, 2021

Let me suggest an alternative. This takes a tolerance which defaults to 0.1 rad.

class OrientationWithToleranceGoal : public LinkGoalBase
{
  tf2::Quaternion orientation_;
  double radian_tolerance_;

public:
  OrientationWithToleranceGoal() : orientation_(0, 0, 0, 1), radian_tolerance_(0.1)
  {
  }
  OrientationWithToleranceGoal(const std::string& link_name, const tf2::Quaternion& orientation,
                               double radian_tolerance, double weight = 1.0)
    : LinkGoalBase(link_name, weight), orientation_(orientation.normalized()), radian_tolerance_(radian_tolerance)
  {
  }
  inline const tf2::Quaternion& getOrientation() const
  {
    return orientation_;
  }
  inline void setOrientation(const tf2::Quaternion& orientation)
  {
    orientation_ = orientation.normalized();
  }
  virtual double evaluate(const GoalContext& context) const
  {
    // Get angle between the quaternions. This is in the range [0, pi]
    // https://math.stackexchange.com/a/90098/448782
    double theta = 2 * acos(fabs(getOrientation().dot(context.getLinkFrame().getOrientation())));

    // Cost ramps up linearly for an angle between [tolerance, pi]
    // Cost is 0 between [0,tolerance)
    // Cost is undefined elsewhere (should never happen)
    if (theta >= radian_tolerance_ && theta <= M_PI)
    {
      // (cost) = (slope) * theta + intercept
      // slope = 1 / (pi - radian_tolerance_)
      // intercept = -slope * radian_tolerance_
      double slope = 1. / (M_PI - radian_tolerance_);
      return slope * theta - slope * radian_tolerance_;
    }
    else
      return 0;
  }
};

@v4hn
Copy link
Member

v4hn commented May 13, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants