Skip to content

Commit 19fe472

Browse files
committedMay 17, 2022
Try creating a loop joint
This PR supercedes #345 with a more general solution that would also help address #25 and solve a lot of issues related to casting joints. Open to feedback.. # TODO - [ ] clean up all the excess joints and links created during the process of loop joint creation. - [ ] fix SetJointTransformChild to use only the joint. Signed-off-by: Arjo Chakravarty <[email protected]>
1 parent 3325673 commit 19fe472

File tree

3 files changed

+65
-60
lines changed

3 files changed

+65
-60
lines changed
 

‎dartsim/src/Base.hh

+6-17
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ struct JointInfo
7474
{
7575
dart::dynamics::JointPtr joint;
7676
dart::dynamics::SimpleFramePtr frame;
77+
dart::dynamics::BodyNode *phantomBody{nullptr};
7778

7879
enum JointType
7980
{
@@ -364,7 +365,6 @@ class Base : public Implements3d<FeatureList<Feature>>
364365
this->joints.idToObject[id] = std::make_shared<JointInfo>();
365366
this->joints.idToObject[id]->joint = _joint;
366367
this->joints.objectToID[_joint] = id;
367-
this->joints.idToObject[id]->type = JointInfo::JointType::JOINT;
368368
dart::dynamics::SimpleFramePtr jointFrame =
369369
dart::dynamics::SimpleFrame::createShared(
370370
_joint->getChildBodyNode(), _joint->getName() + "_frame",
@@ -376,23 +376,12 @@ class Base : public Implements3d<FeatureList<Feature>>
376376
return id;
377377
}
378378

379-
public: inline std::size_t AddJointConstraint(DartWeldJointConsPtr _joint)
379+
public: inline void AddJointWeldConstraint(const std::size_t _id,
380+
DartWeldJointConsPtr _joint, dart::dynamics::BodyNode* _phantomBody)
380381
{
381-
const std::size_t id = this->GetNextEntity();
382-
this->joints.idToObject[id] = std::make_shared<JointInfo>();
383-
this->joints.idToObject[id]->constraint = _joint;
384-
this->joints.idToObject[id]->type = JointInfo::JointType::CONSTRAINT;
385-
// TODO(arjo): Refactor the joints.objectToId to support constraints.
386-
// this->joints.objectToID[_joint] = id;
387-
// dart::dynamics::SimpleFramePtr jointFrame =
388-
// dart::dynamics::SimpleFrame::createShared(
389-
// _joint->getChildBodyNode(), _joint->getName() + "_frame",
390-
// _joint->getTransformFromChildBodyNode());
391-
392-
// this->joints.idToObject[id]->frame = jointFrame;
393-
// this->frames[id] = this->joints.idToObject[id]->frame.get();
394-
395-
return id;
382+
this->joints.idToObject[_id]->constraint = _joint;
383+
this->joints.idToObject[_id]->type = JointInfo::JointType::CONSTRAINT;
384+
this->joints.idToObject[_id]->phantomBody = _phantomBody;
396385
}
397386

398387
public: inline std::size_t AddShape(

‎dartsim/src/JointFeatures.cc

+57-41
Original file line numberDiff line numberDiff line change
@@ -331,29 +331,21 @@ void JointFeatures::SetJointMaxEffort(
331331
/////////////////////////////////////////////////
332332
std::size_t JointFeatures::GetJointDegreesOfFreedom(const Identity &_id) const
333333
{
334-
auto jointInfo = this->ReferenceInterface<JointInfo>(_id);
335-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
336-
return 0;
337-
return jointInfo->joint->getNumDofs();
334+
return this->ReferenceInterface<JointInfo>(_id)->joint->getNumDofs();
338335
}
339336

340337
/////////////////////////////////////////////////
341338
Pose3d JointFeatures::GetJointTransformFromParent(const Identity &_id) const
342339
{
343-
auto jointInfo = this->ReferenceInterface<JointInfo>(_id);
344-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
345-
return jointInfo->constraint->getRelativeTransform().inverse();
346-
return jointInfo->joint->getTransformFromParentBodyNode();
340+
return this->ReferenceInterface<JointInfo>(_id)
341+
->joint->getTransformFromParentBodyNode();
347342
}
348343

349344
/////////////////////////////////////////////////
350345
Pose3d JointFeatures::GetJointTransformToChild(const Identity &_id) const
351346
{
352-
auto jointInfo = this->ReferenceInterface<JointInfo>(_id);
353-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
354-
return jointInfo->constraint->getRelativeTransform();
355347
return this->ReferenceInterface<JointInfo>(_id)
356-
->joint->getTransformFromChildBodyNode().inverse();
348+
->joint->getTransformFromChildBodyNode().inverse();
357349
}
358350

359351
/////////////////////////////////////////////////
@@ -467,11 +459,6 @@ Identity JointFeatures::CastToFixedJoint(
467459
const Identity &_jointID) const
468460
{
469461
auto jointInfo = this->ReferenceInterface<JointInfo>(_jointID);
470-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
471-
{
472-
// TODO(arjo): Handle constraint casts.
473-
return this->GenerateInvalidId();
474-
}
475462
dart::dynamics::WeldJoint *const weld =
476463
dynamic_cast<dart::dynamics::WeldJoint *>(
477464
jointInfo->joint.get());
@@ -499,15 +486,25 @@ Identity JointFeatures::AttachFixedJoint(
499486
if (bn->getParentJoint()->getType() != "FreeJoint")
500487
{
501488
// child already has a parent joint
502-
// use a WeldJointConstraint between the two bodies
489+
// Create a phantom link and a joint to attach the child to the phantom
490+
const auto &[joint, phantomBody] =
491+
bn->getSkeleton()->createJointAndBodyNodePair<
492+
dart::dynamics::WeldJoint,
493+
dart::dynamics::BodyNode>(
494+
bn, properties, dart::dynamics::BodyNode::AspectProperties());
495+
const std::size_t jointID = this->AddJoint(joint);
496+
phantomBody->setCollidable(false);
497+
498+
// use a WeldJointConstraint between the phantom joint and the link
503499
auto worldId = this->GetWorldOfModelImpl(
504500
this->models.IdentityOf(bn->getSkeleton()));
505501
auto dartWorld = this->worlds.at(worldId);
506502

507503
auto constraint =
508-
std::make_shared<dart::constraint::WeldJointConstraint>(parentBn, bn);
504+
std::make_shared<dart::constraint::WeldJointConstraint>(
505+
parentBn, phantomBody);
509506
dartWorld->getConstraintSolver()->addConstraint(constraint);
510-
auto jointID = this->AddJointConstraint(constraint);
507+
this->AddJointWeldConstraint(jointID, constraint, phantomBody);
511508
return this->GenerateIdentity(jointID, this->joints.at(jointID));
512509
}
513510
{
@@ -530,11 +527,6 @@ Identity JointFeatures::CastToFreeJoint(
530527
const Identity &_jointID) const
531528
{
532529
auto jointInfo = this->ReferenceInterface<JointInfo>(_jointID);
533-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
534-
{
535-
// TODO(arjo): Handle constraint casts.
536-
return this->GenerateInvalidId();
537-
}
538530
auto *const freeJoint =
539531
dynamic_cast<dart::dynamics::FreeJoint *>(
540532
jointInfo->joint.get());
@@ -559,11 +551,6 @@ Identity JointFeatures::CastToRevoluteJoint(
559551
const Identity &_jointID) const
560552
{
561553
auto jointInfo = this->ReferenceInterface<JointInfo>(_jointID);
562-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
563-
{
564-
// TODO(arjo): Handle constraint casts.
565-
return this->GenerateInvalidId();
566-
}
567554
dart::dynamics::RevoluteJoint *const revolute =
568555
dynamic_cast<dart::dynamics::RevoluteJoint *>(
569556
jointInfo->joint.get());
@@ -609,9 +596,26 @@ Identity JointFeatures::AttachRevoluteJoint(
609596

610597
if (bn->getParentJoint()->getType() != "FreeJoint")
611598
{
612-
// child already has a parent joint
613-
// TODO(scpeters): use a WeldJointConstraint between the two bodies
614-
return this->GenerateInvalidId();
599+
// Create a phantom link and a joint to attach the child to the phantom
600+
const auto &[joint, phantomBody] =
601+
bn->getSkeleton()->createJointAndBodyNodePair<
602+
dart::dynamics::RevoluteJoint,
603+
dart::dynamics::BodyNode>(
604+
bn, properties, dart::dynamics::BodyNode::AspectProperties());
605+
const std::size_t jointID = this->AddJoint(joint);
606+
phantomBody->setCollidable(false);
607+
608+
// use a WeldJointConstraint between the phantom joint and the link
609+
auto worldId = this->GetWorldOfModelImpl(
610+
this->models.IdentityOf(bn->getSkeleton()));
611+
auto dartWorld = this->worlds.at(worldId);
612+
613+
auto constraint =
614+
std::make_shared<dart::constraint::WeldJointConstraint>(
615+
parentBn, phantomBody);
616+
dartWorld->getConstraintSolver()->addConstraint(constraint);
617+
this->AddJointWeldConstraint(jointID, constraint, phantomBody);
618+
return this->GenerateIdentity(jointID, this->joints.at(jointID));
615619
}
616620

617621
{
@@ -634,11 +638,6 @@ Identity JointFeatures::CastToPrismaticJoint(
634638
const Identity &_jointID) const
635639
{
636640
auto jointInfo = this->ReferenceInterface<JointInfo>(_jointID);
637-
if (jointInfo->type == JointInfo::JointType::CONSTRAINT)
638-
{
639-
// TODO(arjo): Handle constraint casts.
640-
return this->GenerateInvalidId();
641-
}
642641
dart::dynamics::PrismaticJoint *prismatic =
643642
dynamic_cast<dart::dynamics::PrismaticJoint*>(jointInfo->joint.get());
644643

@@ -683,9 +682,26 @@ Identity JointFeatures::AttachPrismaticJoint(
683682

684683
if (bn->getParentJoint()->getType() != "FreeJoint")
685684
{
686-
// child already has a parent joint
687-
// TODO(scpeters): use a WeldJointConstraint between the two bodies
688-
return this->GenerateInvalidId();
685+
// Create a phantom link and a joint to attach the child to the phantom
686+
const auto &[joint, phantomBody] =
687+
bn->getSkeleton()->createJointAndBodyNodePair<
688+
dart::dynamics::PrismaticJoint,
689+
dart::dynamics::BodyNode>(
690+
bn, properties, dart::dynamics::BodyNode::AspectProperties());
691+
const std::size_t jointID = this->AddJoint(joint);
692+
phantomBody->setCollidable(false);
693+
694+
// use a WeldJointConstraint between the phantom joint and the link
695+
auto worldId = this->GetWorldOfModelImpl(
696+
this->models.IdentityOf(bn->getSkeleton()));
697+
auto dartWorld = this->worlds.at(worldId);
698+
699+
auto constraint =
700+
std::make_shared<dart::constraint::WeldJointConstraint>(
701+
parentBn, phantomBody);
702+
dartWorld->getConstraintSolver()->addConstraint(constraint);
703+
this->AddJointWeldConstraint(jointID, constraint, phantomBody);
704+
return this->GenerateIdentity(jointID, this->joints.at(jointID));
689705
}
690706

691707
{

‎dartsim/src/JointFeatures_TEST.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,7 @@ TEST_F(JointFeaturesFixture, JointAttachMultiple)
978978
EXPECT_EQ(initialModel3Pose,
979979
math::eigen3::convert(dartBody3->getWorldTransform()));
980980

981+
981982
const std::size_t numSteps = 100;
982983
for (std::size_t i = 0; i < numSteps; ++i)
983984
{
@@ -995,12 +996,11 @@ TEST_F(JointFeaturesFixture, JointAttachMultiple)
995996
EXPECT_NEAR(0.0, body2LinearVelocity.Z(), 1e-7);
996997
EXPECT_NEAR(0.0, body3LinearVelocity.Z(), 1e-7);
997998
}
998-
999999
// Detach the joints. M1 and M3 should fall as there is now nothing stopping
10001000
// them from falling.
10011001
fixedJoint1->Detach();
10021002
fixedJoint2->Detach();
1003-
1003+
10041004
for (std::size_t i = 0; i < numSteps; ++i)
10051005
{
10061006
world->Step(output, state, input);

0 commit comments

Comments
 (0)
Please sign in to comment.