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

Add degraded status chainiksolverpos #358

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions orocos_kdl/src/chainiksolverpos_nr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ namespace KDL
chain(_chain),nj (chain.getNrOfJoints()),
iksolver(_iksolver),fksolver(_fksolver),
delta_q(_chain.getNrOfJoints()),
maxiter(_maxiter),eps(_eps)
maxiter(_maxiter),
eps(_eps),
numiter(0),
ikvelstatus(E_NOERROR)
{
}

Expand All @@ -48,23 +51,49 @@ namespace KDL
return (error = E_SIZE_MISMATCH);

q_out = q_init;
bool degraded = false;

unsigned int i;
for(i=0;i<maxiter;i++){
for(numiter=1; numiter<=maxiter; ++numiter) {
craigirobot marked this conversation as resolved.
Show resolved Hide resolved
degraded = false; // prove otherwise
if (E_NOERROR > fksolver.JntToCart(q_out,f) )
return (error = E_FKSOLVERPOS_FAILED);
delta_twist = diff(f,p_in);
const int rc = iksolver.CartToJnt(q_out,delta_twist,delta_q);
if (E_NOERROR > rc)
ikvelstatus = iksolver.CartToJnt(q_out,delta_twist,delta_q);
if (E_NOERROR > ikvelstatus)
return (error = E_IKSOLVER_FAILED);
// we chose to continue if the child solver returned a positive
// check for degraded solution (but can still continue motion)
else if (E_NOERROR < ikvelstatus)
degraded = true;
// we choose to continue if the child solver returned a positive
// "error", which may simply indicate a degraded solution
Add(q_out,delta_q,q_out);
if(Equal(delta_twist,Twist::Zero(),eps))
// converged, but possibly with a degraded solution
return (rc > E_NOERROR ? E_DEGRADED : E_NOERROR);
return (ikvelstatus > E_NOERROR ? E_DEGRADED : E_NOERROR);
}
return (error = E_MAX_ITERATIONS_EXCEEDED); // failed to converge

// update cartesian output to be in sync with final joint solution
(void)fksolver.JntToCart(q_out,f);

// not converged but singularity avoidance is active so okay
if (degraded)
return (error = E_DEGRADED);
else
return (error = E_MAX_ITERATIONS_EXCEEDED);
}

void ChainIkSolverPos_NR::setEps(const double _eps)
{
if (0 < _eps)
eps = _eps;
// else silently ignore
}

void ChainIkSolverPos_NR::setMaxIter(const unsigned int _maxiter)
{
if (1 <= _maxiter)
maxiter = _maxiter;
// else silently ignore
}

ChainIkSolverPos_NR::~ChainIkSolverPos_NR()
Expand Down
43 changes: 43 additions & 0 deletions orocos_kdl/src/chainiksolverpos_nr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,47 @@ namespace KDL {
*/
virtual int CartToJnt(const JntArray& q_init, const Frame& p_in, JntArray& q_out);

/**
* Set maximum number of iterations
*/
void setMaxIter(const unsigned int maxiter_in);

/**
* Set epsilon
* \pre 0 < eps, otherwise eps is ignored
*/
void setEps(const double eps_in);

/**
* Get maximum number of iterations
* \pre 1 <= maxiter, otherwise maxiter is ignored
*/
unsigned int getMaxIter() const { return maxiter; }

/**
* Get epsilon
*/
double getEps() const { return eps; }

/**
* Get delta twist from last call to CartToJnt()
*/
void getDeltaTwist(KDL::Twist& _delta_twist)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Reason why not to just simple return?

Copy link
Author

@craigirobot craigirobot Nov 24, 2021

Choose a reason for hiding this comment

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

Do you mean something like this?

Twist& getDeltaTwist()
{
    return delta_twist;
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, indeed. But then get a const reference.

Copy link
Author

Choose a reason for hiding this comment

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

Ah, so this?

const Twist& getDeltaTwist()const
{
return delta_twist;
}

Copy link
Author

Choose a reason for hiding this comment

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

I just added this commit.

{
_delta_twist = delta_twist;
}

/**
* Get status of ik velocity solver
*/
int getVelSolverStatus() const { return ikvelstatus; }

/**
* Get number iterations spent in last call to CartToJnt()
* Defaults to 0 at construction
*/
unsigned int getNumIters() const { return numiter; }

/// @copydoc KDL::SolverI::strError()
virtual const char* strError(const int error) const;

Expand All @@ -90,6 +131,8 @@ namespace KDL {

unsigned int maxiter;
double eps;
unsigned int numiter;
int ikvelstatus;
};

}
Expand Down
4 changes: 2 additions & 2 deletions orocos_kdl/tests/solvertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ void SolverTest::IkSingularValueTest()
CPPUNIT_ASSERT_EQUAL(0, fksolver.JntToCart(q,F));
F_des = F * dF ;

CPPUNIT_ASSERT_EQUAL((int)SolverI::E_MAX_ITERATIONS_EXCEEDED,
CPPUNIT_ASSERT_EQUAL((int)SolverI::E_DEGRADED,
iksolver1.CartToJnt(q,F_des,q_solved)); // no converge
CPPUNIT_ASSERT_EQUAL((int)ChainIkSolverVel_pinv::E_CONVERGE_PINV_SINGULAR,
ikvelsolver1.getError()); // truncated SV solution
Expand Down Expand Up @@ -627,7 +627,7 @@ void SolverTest::IkSingularValueTest()
CPPUNIT_ASSERT_EQUAL((int)SolverI::E_NOERROR, fksolver.JntToCart(q,F));
F_des = F * dF ;

CPPUNIT_ASSERT_EQUAL((int)SolverI::E_MAX_ITERATIONS_EXCEEDED,
CPPUNIT_ASSERT_EQUAL((int)SolverI::E_DEGRADED,
iksolver1.CartToJnt(q,F_des,q_solved)); // no converge
CPPUNIT_ASSERT_EQUAL((int)ChainIkSolverVel_pinv::E_CONVERGE_PINV_SINGULAR,
ikvelsolver1.getError()); // truncated SV solution
Expand Down