Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
60 changes: 60 additions & 0 deletions orocos_kdl/src/chainjnttojacsolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,65 @@ namespace KDL
}
return (error = E_NOERROR);
}

int ChainJntToJacSolver::JntToJac(const JntArray& q_in, std::vector<Jacobian>& jac, int seg_nr)
{
if(locked_joints_.size() != chain.getNrOfJoints())
return (error = E_NOT_UP_TO_DATE);
unsigned int segmentNr;
if(seg_nr<0)
segmentNr=chain.getNrOfSegments();
else
segmentNr = seg_nr;

//Initialize Jacobian to zero since only segmentNr columns are computed
SetToZero(jac[0]);

if( q_in.rows()!=chain.getNrOfJoints() || jac[0].columns() != chain.getNrOfJoints())
return (error = E_SIZE_MISMATCH);
else if(segmentNr>chain.getNrOfSegments())
return (error = E_OUT_OF_RANGE);
else if(jac.size() < segmentNr)
return (error = E_SIZE_MISMATCH);

T_tmp = Frame::Identity();
SetToZero(t_tmp);
int j=0;
int k=0;
Frame total;

// Loop through segments
for (unsigned int i=0;i<segmentNr;i++) {
if ( i!=0 ) {
jac[i] = jac[i-1];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please explain why you take the jacobian of the previous segment

}
//Calculate new Frame_base_ee
if(chain.getSegment(i).getJoint().getType()!=Joint::Fixed) {
//pose of the new end-point expressed in the base
total = T_tmp*chain.getSegment(i).pose(q_in(j));
//changing base of new segment's twist to base frame if it is not locked
//t_tmp = T_tmp.M*chain.getSegment(i).twist(1.0);
if(!locked_joints_[j])
t_tmp = T_tmp.M*chain.getSegment(i).twist(q_in(j),1.0);
}else{
total = T_tmp*chain.getSegment(i).pose(0.0);
}
Comment on lines +128 to +142
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
for (unsigned int i=0;i<segmentNr;i++) {
if ( i!=0 ) {
jac[i] = jac[i-1];
}
//Calculate new Frame_base_ee
if(chain.getSegment(i).getJoint().getType()!=Joint::Fixed) {
//pose of the new end-point expressed in the base
total = T_tmp*chain.getSegment(i).pose(q_in(j));
//changing base of new segment's twist to base frame if it is not locked
//t_tmp = T_tmp.M*chain.getSegment(i).twist(1.0);
if(!locked_joints_[j])
t_tmp = T_tmp.M*chain.getSegment(i).twist(q_in(j),1.0);
}else{
total = T_tmp*chain.getSegment(i).pose(0.0);
}
for (unsigned int i=0;i<segmentNr;i++)
{
if (i > 0)
jac[i] = jac[i-1];
// Calculate new Frame_base_ee
if (chain.getSegment(i).getJoint().getType() != Joint::Fixed)
{
// Pose of the new end-point expressed in the base
total = T_tmp * chain.getSegment(i).pose(q_in(j));
// Changing base of new segment's twist to base frame if it is not locked
if (!locked_joints_[j])
t_tmp = T_tmp.M * chain.getSegment(i).twist(q_in(j),1.0);
}
else
{
total = T_tmp * chain.getSegment(i).pose(0.0);
}


//Changing Refpoint of all columns to new ee
changeRefPoint(jac[i],total.p-T_tmp.p,jac[i]);

//Only increase jointnr if the segment has a joint
if(chain.getSegment(i).getJoint().getType()!=Joint::Fixed) {
//Only put the twist inside if it is not locked
if(!locked_joints_[j])
jac[i].setColumn(k++,t_tmp);
j++;
}

T_tmp = total;
}
return (error = E_NOERROR);
}

Comment on lines +144 to +159
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
//Changing Refpoint of all columns to new ee
changeRefPoint(jac[i],total.p-T_tmp.p,jac[i]);
//Only increase jointnr if the segment has a joint
if(chain.getSegment(i).getJoint().getType()!=Joint::Fixed) {
//Only put the twist inside if it is not locked
if(!locked_joints_[j])
jac[i].setColumn(k++,t_tmp);
j++;
}
T_tmp = total;
}
return (error = E_NOERROR);
}
// Changing Refpoint of all columns to new ee
changeRefPoint(jac[i], total.p - T_tmp.p, jac[i]);
// Only increase jointnr if the segment has a joint
if (chain.getSegment(i).getJoint().getType() != Joint::Fixed)
{
//Only put the twist inside if it is not locked
if (!locked_joints_[j])
jac[i].setColumn(k++, t_tmp);
j++;
}
T_tmp = total;
}
return (error = E_NOERROR);
}

}

3 changes: 2 additions & 1 deletion orocos_kdl/src/chainjnttojacsolver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,12 @@ namespace KDL
* KDL::ChainFkSolverVel_recursive
*
* @param q_in input joint positions
* @param jac output jacobian
* @param jac output jacobian of last segment or array of jacobians for each segment
* @param seg_nr The final segment to compute
* @return success/error code
*/
virtual int JntToJac(const JntArray& q_in, Jacobian& jac, int seg_nr=-1);
virtual int JntToJac(const JntArray& q_in, std::vector<Jacobian>& jac, int seg_nr=-1);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add missing docstring

Copy link
Author

Choose a reason for hiding this comment

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

Added the missing comment on the Jacobian string output.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I would copy the entire docstring and make it specific for each set of arguments


/**
*
Expand Down
37 changes: 37 additions & 0 deletions orocos_kdl/tests/solvertest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,43 @@ void SolverTest::FkPosAndIkPosLocal(Chain& chain,ChainFkSolverPos& fksolverpos,
}


void SolverTest::JacAllSegments()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please also add this test in python

Copy link
Contributor

Choose a reason for hiding this comment

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

I can take a look at this

{
std::cout << "KDL Jac Solver Test for returning all segment Jacobians" << std::endl;

double eps = 1e-6;

unsigned int nj = motomansia10.getNrOfJoints();
unsigned int ns = motomansia10.getNrOfSegments();

JntArray q(nj);
Jacobian jac(nj);
std::vector<Jacobian> jac_all(ns, Jacobian(nj));

ChainJntToJacSolver jacsolver(motomansia10);

// random
q(0) = 0.2;
q(1) = 0.6;
q(2) = 1.;
q(3) = 0.5;
q(4) = -1.4;
q(5) = 0.3;
q(6) = -0.8;

CPPUNIT_ASSERT_EQUAL((int)SolverI::E_NOERROR, jacsolver.JntToJac(q, jac_all, ns));
for (unsigned int seg=0; seg<ns; seg++)
{
jacsolver.JntToJac(q, jac, seg+1);
for ( unsigned int i=0; i<jac.rows(); i++ ) {
for ( unsigned int j=0; j<nj; j++ ) {
CPPUNIT_ASSERT(Equal(jac(i,j), jac_all[seg](i,j), eps));
}
}
}
}


void SolverTest::VereshchaginTest()
{
std::cout << "KDL Vereshchagin Hybrid Dynamics Tests" <<std::endl;
Expand Down
2 changes: 2 additions & 0 deletions orocos_kdl/tests/solvertest.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class SolverTest : public CppUnit::TestFixture
CPPUNIT_TEST(FkVelAndJacTest );
CPPUNIT_TEST(FkVelAndIkVelTest );
CPPUNIT_TEST(FkPosAndIkPosTest );
CPPUNIT_TEST(JacAllSegments );
CPPUNIT_TEST(VereshchaginTest );
CPPUNIT_TEST(ExternalWrenchEstimatorTest );
CPPUNIT_TEST(IkSingularValueTest );
Expand All @@ -54,6 +55,7 @@ class SolverTest : public CppUnit::TestFixture
void FkVelAndJacTest();
void FkVelAndIkVelTest();
void FkPosAndIkPosTest();
void JacAllSegments();
void VereshchaginTest();
void ExternalWrenchEstimatorTest();
void IkSingularValueTest() ;
Expand Down
4 changes: 3 additions & 1 deletion python_orocos_kdl/PyKDL/kinfam.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,9 @@ void init_kinfam(pybind11::module &m)
// ------------------------------
py::class_<ChainJntToJacSolver, SolverI> chain_jnt_to_jac_solver(m, "ChainJntToJacSolver");
chain_jnt_to_jac_solver.def(py::init<const Chain&>(), py::arg("chain"));
chain_jnt_to_jac_solver.def("JntToJac", &ChainJntToJacSolver::JntToJac,
chain_jnt_to_jac_solver.def("JntToJac", (int (ChainJntToJacSolver::*)(const JntArray&, Jacobian&, int)) &ChainJntToJacSolver::JntToJac,
py::arg("q_in"), py::arg("jac"), py::arg("seg_nr")=-1);
chain_jnt_to_jac_solver.def("JntToJac", (int (ChainJntToJacSolver::*)(const JntArray&, std::vector<Jacobian>&, int)) &ChainJntToJacSolver::JntToJac,
Copy link
Collaborator

Choose a reason for hiding this comment

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

This doesn't work yet, see also

// Argument by reference doesn't work for container types
// chain_fk_solver_vel.def("JntToCart", (int (ChainFkSolverVel::*)(const JntArrayVel&, std::vector<FrameVel>&, int)) &ChainFkSolverVel::JntToCart,
// py::arg("q_in"), py::arg("p_out"), py::arg("segmentNr")=-1);

There are multiple ways to work around this. docs I don't like making custom vectors. I would go for converting this to a lamda function, which accepts a py::list instead of the vector. Then you need to copy from the vector to the python list.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Take a look at #497

Copy link
Contributor

Choose a reason for hiding this comment

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

I made these changes for Craig. These were just a copy/paste of existing code.
Are you saying that the existing code doesn't work and you would like that fixed? Or is there an error in the copy/paste itself?

Copy link
Collaborator

Choose a reason for hiding this comment

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

What I am saying is that pybind can't handle references of container arguments. So when a reference container argument is an output of the function, you don't get the update value of the argument. I will be same as when you called the function. So see #497 for how I fixed it for another function with a reference container argument.

py::arg("q_in"), py::arg("jac"), py::arg("seg_nr")=-1);
chain_jnt_to_jac_solver.def("setLockedJoints", &ChainJntToJacSolver::setLockedJoints, py::arg("locked_joints"));

Expand Down
Loading