From 5f92d1fe4e0eca373a5f561f0e10e79d8d05d6dd Mon Sep 17 00:00:00 2001 From: vahrenkamp <vahrenkamp@042f3d55-54a8-47e9-b7fb-15903f145c44> Date: Sun, 25 Nov 2012 19:12:07 +0000 Subject: [PATCH] Improved dynamics robot creation: Mapping from VirtualRobot Kinematic structure to bullet model. Added ignoreCollision tag to physics section of robot's xml description: Allows to specify disabled collision pairs for physics engines. Adjusted ARMAR-III model to work with bullet-SimDynamics. git-svn-id: http://svn.code.sf.net/p/simox/code/trunk@340 042f3d55-54a8-47e9-b7fb-15903f145c44 --- .../BulletEngine/BulletEngine.cpp | 4 +- .../BulletEngine/BulletRobot.cpp | 644 ++++++++++++++++-- .../DynamicsEngine/BulletEngine/BulletRobot.h | 21 +- .../BulletEngine/SimoxMotionState.cpp | 4 +- .../BulletDebugViewerGlut.cpp | 8 +- .../SimDynamicsViewer/SimDynamicsViewer.cpp | 5 +- .../SimDynamicsViewer/simDynamicsWindow.cpp | 43 +- VirtualRobot/Nodes/RobotNode.cpp | 40 +- VirtualRobot/Nodes/RobotNode.h | 63 +- VirtualRobot/Nodes/RobotNodeFactory.h | 7 +- VirtualRobot/Nodes/RobotNodeFixed.cpp | 21 +- VirtualRobot/Nodes/RobotNodeFixed.h | 10 +- VirtualRobot/Nodes/RobotNodeFixedFactory.cpp | 8 +- VirtualRobot/Nodes/RobotNodeFixedFactory.h | 4 +- VirtualRobot/Nodes/RobotNodePrismatic.cpp | 30 +- VirtualRobot/Nodes/RobotNodePrismatic.h | 11 +- .../Nodes/RobotNodePrismaticFactory.cpp | 8 +- .../Nodes/RobotNodePrismaticFactory.h | 4 +- VirtualRobot/Nodes/RobotNodeRevolute.cpp | 25 +- VirtualRobot/Nodes/RobotNodeRevolute.h | 10 +- .../Nodes/RobotNodeRevoluteFactory.cpp | 8 +- VirtualRobot/Nodes/RobotNodeRevoluteFactory.h | 4 +- VirtualRobot/SceneObject.cpp | 6 + VirtualRobot/SceneObject.h | 21 +- VirtualRobot/Transformation/DHParameter.h | 12 + VirtualRobot/XML/BaseIO.cpp | 69 +- VirtualRobot/XML/BaseIO.h | 3 +- VirtualRobot/XML/RobotIO.cpp | 64 +- VirtualRobot/XML/RobotIO.h | 9 +- .../data/robots/ArmarIII/ArmarIII-Head.xml | 5 + .../data/robots/ArmarIII/ArmarIII-LeftArm.xml | 2 + .../robots/ArmarIII/ArmarIII-RightArm.xml | 2 + .../data/robots/ArmarIII/ArmarIII.xml | 11 +- .../examples/RobotViewer/showRobotWindow.cpp | 37 + 34 files changed, 1009 insertions(+), 214 deletions(-) diff --git a/SimDynamics/DynamicsEngine/BulletEngine/BulletEngine.cpp b/SimDynamics/DynamicsEngine/BulletEngine/BulletEngine.cpp index 0e5fbfedf..f8bff2148 100644 --- a/SimDynamics/DynamicsEngine/BulletEngine/BulletEngine.cpp +++ b/SimDynamics/DynamicsEngine/BulletEngine/BulletEngine.cpp @@ -366,7 +366,9 @@ void BulletEngine::print() std::vector<BulletRobot::LinkInfo> links = br->getLinks(); for (size_t j=0;j<links.size();j++) { - cout << "++++ Link " << j << ":" << links[j].node2->getName(); + cout << "++++ Link " << j << ":" << links[j].nodeJoint->getName(); + cout << "++++ - ColModelA " << j << ":" << links[j].nodeA->getName(); + cout << "++++ - ColModelB " << j << ":" << links[j].nodeB->getName(); cout << " enabled:" << links[j].joint->isEnabled() << endl; boost::shared_ptr<btHingeConstraint> hinge = boost::dynamic_pointer_cast<btHingeConstraint>(links[j].joint); diff --git a/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.cpp b/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.cpp index 5290b12c6..b7609d234 100644 --- a/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.cpp +++ b/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.cpp @@ -19,6 +19,7 @@ //#define DEBUG_FIXED_OBJECTS //#define DEBUG_SHOW_LINKS using namespace VirtualRobot; +using namespace std; namespace SimDynamics { @@ -55,38 +56,474 @@ void BulletRobot::buildBulletModels(bool enableJointMotors) return; robotNodes = robot->getRobotNodes(); + for (size_t i=0;i<robotNodes.size();i++) + { + + RobotNodePtr rn = robotNodes[i]; + CollisionModelPtr colModel = rn->getCollisionModel(); + if (colModel) + { + addIgnoredCollisionModels(rn); + // search joint and connected model + RobotNodePtr bodyA; + RobotNodePtr bodyB = rn; + RobotNodePtr joint; + RobotNodePtr joint2; + + if (rn->isTranslationalJoint() || rn->isRotationalJoint()) + joint = rn; + RobotNodePtr parent = boost::dynamic_pointer_cast<RobotNode>(rn->getParent()); + while (parent && !bodyA) + { + if (!parent->getCollisionModel() && (parent->isTranslationalJoint() || parent->isRotationalJoint())) + { + if (!joint) + { + joint = parent; + } else + { + // check for hinge2 joint + THROW_VR_EXCEPTION_IF(joint2,"three joints in a row not supported:" << joint->getName() << ", " << joint2->getName() << "," << parent->getName()); + joint2 = parent; + Eigen::Matrix4f p1 = joint->getGlobalPoseJoint(); + Eigen::Matrix4f p2 = joint2->getGlobalPoseJoint(); + + float d = (p1.block(0,3,3,1) - p2.block(0,3,3,1)).norm(); + THROW_VR_EXCEPTION_IF( (d>1e-6), "Could not create hinge2 joint: Joint coord systems must be located at the same position:" << joint->getName() << ", " << joint2->getName()); + RobotNodeRevolutePtr rev1 = boost::dynamic_pointer_cast<RobotNodeRevolute>(joint); + RobotNodeRevolutePtr rev2 = boost::dynamic_pointer_cast<RobotNodeRevolute>(joint2); + THROW_VR_EXCEPTION_IF( !rev1 || !rev2 , "Could not create hinge2 joint: Joints must be revolute nodes:" << joint->getName() << ", " << joint2->getName()); + Eigen::Vector3f ax1 = rev1->getJointRotationAxis(); + Eigen::Vector3f ax2 = rev2->getJointRotationAxis(); + float ang = MathTools::getAngle(ax1,ax2); + THROW_VR_EXCEPTION_IF( fabs(fabs(ang)-M_PI_2) > 1e-6, "Could not create hinge2 joint: Joint axes must be orthogonal to each other:" << joint->getName() << ", " << joint2->getName()); + } + } + if (parent->getCollisionModel()) + { + //if (!joint) + // THROW_VR_EXCEPTION("Could not build dynamic model: Robotnode " << parent->getName() << " and " << bodyB->getName() << " got a collision model but they are not linked by a joint."); + bodyA = parent; + break; + } + + parent = boost::dynamic_pointer_cast<RobotNode>(parent->getParent()); + } + if (!bodyA) + { + // root node + /*if (joint) + { + THROW_VR_EXCEPTION ("Not able to build valid dynamic model: First node of robot with collision model (" << rn->getName() << ") is connected with a joint (" << joint->getName() <<") but no parent collision model found."); + }*/ + bodyA = robot->getRootNode(); + } + //} else + { + /* Eigen::Matrix4f trafoA2J = Eigen::Matrix4f::Identity(); // bodyA->joint + Eigen::Matrix4f trafoJ2B = Eigen::Matrix4f::Identity(); // joint->bodyB + if (joint) + { + // now we have bodyA->joint->bodyB + // compute trafoA2J + std::vector<Eigen::Matrix4f> trafosA; + // visualization is affected by preJointTransformation + trafosA.push_back(joint->getPreJointTransformation()); + + // go parents up until bodyA is reached + parent = boost::dynamic_pointer_cast<RobotNode>(joint->getParent()); + while (parent && parent!=bodyA) + { + trafosA.push_back(parent->getPostJointTransformation()); + trafosA.push_back(parent->getPreJointTransformation()); + parent = boost::dynamic_pointer_cast<RobotNode>(parent->getParent()); + } + THROW_VR_EXCEPTION_IF(!parent,"internal error, no parent 2"); + trafosA.push_back(bodyA->getPostJointTransformation()); + std::vector<Eigen::Matrix4f>::reverse_iterator rit; + // accumulate transformations from bodyA_post to joint_pre + for (rit=trafosA.rbegin(); rit != trafosA.rend(); rit++) + { + trafoA2J *= *rit; + } + + // compute trafoJ2B + std::vector<Eigen::Matrix4f> trafosB; + + // visualization is affected by preJointTransformation + trafosB.push_back(bodyB->getPreJointTransformation()); + if (joint!=bodyB) + { + // go parents up until joint is reached + parent = boost::dynamic_pointer_cast<RobotNode>(bodyB->getParent()); + while (parent && parent!=joint) + { + trafosB.push_back(parent->getPostJointTransformation()); + trafosB.push_back(parent->getPreJointTransformation()); + parent = boost::dynamic_pointer_cast<RobotNode>(parent->getParent()); + } + THROW_VR_EXCEPTION_IF(!parent,"internal error, no parent"); + trafosB.push_back(joint->getPostJointTransformation()); + } + // accumulate transformations from joint_post to bodyB_pre + for (rit=trafosB.rbegin(); rit != trafosB.rend(); rit++) + { + trafoJ2B *= *rit; + } + } else + { + // fixed joint: bodyA -> bodyB + joint = bodyB; + + // compute trafoA2J (which is trafo from A to B) + std::vector<Eigen::Matrix4f> trafosA; + // visualization is affected by preJointTransformation + trafosA.push_back(bodyB->getPreJointTransformation()); + + // go parents up until bodyA is reached + parent = boost::dynamic_pointer_cast<RobotNode>(bodyB->getParent()); + while (parent && parent!=bodyA) + { + trafosA.push_back(parent->getPostJointTransformation()); + trafosA.push_back(parent->getPreJointTransformation()); + parent = boost::dynamic_pointer_cast<RobotNode>(parent->getParent()); + } + THROW_VR_EXCEPTION_IF(!parent,"internal error, no parent 3"); + trafosA.push_back(bodyA->getPostJointTransformation()); + std::vector<Eigen::Matrix4f>::reverse_iterator rit; + // accumulate transformations from bodyA_post to joint_pre + for (rit=trafosA.rbegin(); rit != trafosA.rend(); rit++) + { + trafoA2J *= *rit; + } + + }*/ + + // check for fixed joint + if (!joint) + joint = bodyB; + + createLink(bodyA,joint,joint2,bodyB);//,trafoA2J,trafoJ2B); + } + + } + + /* + RobotNodePtr bodyA; + RobotNodePtr bodyB; + RobotNodePtr joint; + Eigen::Matrix4f trafoA = Eigen::Matrix4f; + Eigen::Matrix4f trafoB = Eigen::Matrix4f; for (size_t i=0;i<robotNodes.size();i++) { + RobotNodePtr rn = robotNodes[i]; + + switch(rn->getType()) + { + case RobotNode::Generic: + THROW_VR_EXCEPTION ("Could not build dynamic model. Only <JointNode> <TransformationNode> and <BodyNode> tags allowed!"); + break; + case RobotNode::Body: + break; + default: + continue; + } + // a body + bodyB = rn; + bodyA.reset(); + joint.reset(); + trafoA = Eigen::Matrix4f; + trafoB = Eigen::Matrix4f; + + // search parent body + RobotNodePtr parent = rn->getParent(); + bool built = false; + while (parent && !built) + { + switch (parent->getType()) + { + case RobotNode::Joint: + if (joint) + { + THROW_VR_EXCEPTION("Need bodies between joints. Two succeeding joints found in kinematic structure"); + } + joint = parent; + break; + case RobotNode::Body: + if (!joint) + { + THROW_VR_EXCEPTION("Need joint between body. Two succeeding bodies found in kinematic structure"); + } + createLink(bodyA,joint,bodyB,trafoA,trafoB); + built = true; + break; + case RobotNode::Transform: + if (!joint) + trafoA *= parent->getPostJointTransformation + built = true; + break; + } + } + + */ + + /* std::vector<SceneObjectPtr> children = rn->getChildren(); for (size_t c=0;c<children.size();c++) { - // check what to do - /* - bool fixed = !(children[c]->isRotationalJoint() || children[c]->isTranslationalJoint()); - if (fixed && !(children[c]->getCollisionModel())) - continue; // a fixed transformation without model, skip it - */ RobotNodePtr rn2 = boost::dynamic_pointer_cast<RobotNode>(children[c]); if (rn2) createLink(rn,rn2,enableJointMotors); - } + }*/ } } -void BulletRobot::createLink( VirtualRobot::RobotNodePtr node1,VirtualRobot::RobotNodePtr node2, bool enableJointMotors ) +void BulletRobot::addIgnoredCollisionModels(RobotNodePtr rn) { - THROW_VR_EXCEPTION_IF (!(node1->hasChild(node2)),"node1 must be parent of node2"); + VR_ASSERT (rn); + if (!rn->getCollisionModel()) + return; // nothing to do: no col model -> no bullet model -> no collisions + createDynamicsNode(rn); + std::vector<std::string> ic = rn->getIgnoredCollisionModels(); + RobotPtr robot = rn->getRobot(); + BulletObjectPtr drn1 = boost::dynamic_pointer_cast<BulletObject>(dynamicRobotNodes[rn]); + VR_ASSERT(drn1); + + for (size_t i=0;i<ic.size();i++) + { + RobotNodePtr rn2 = robot->getRobotNode(ic[i]); + if (!rn2) + { + VR_ERROR << "Error while processing robot node <" << rn->getName() << ">: Ignored collision model <" << ic[i] << "> is not part of robot..." << endl; + } else + { + createDynamicsNode(rn2); + BulletObjectPtr drn2 = boost::dynamic_pointer_cast<BulletObject>(dynamicRobotNodes[rn2]); + VR_ASSERT(drn2); + DynamicsWorld::GetWorld()->getEngine()->disableCollision(drn1.get(),drn2.get()); + } + } +} - if (dynamicRobotNodes.find(node1) == dynamicRobotNodes.end()) - { - createDynamicsNode(node1); - } - if (dynamicRobotNodes.find(node2) == dynamicRobotNodes.end()) +void BulletRobot::createLink( VirtualRobot::RobotNodePtr bodyA, VirtualRobot::RobotNodePtr joint, VirtualRobot::RobotNodePtr joint2, VirtualRobot::RobotNodePtr bodyB, bool enableJointMotors ) +{ + // ensure dynamics nodes are created + createDynamicsNode(bodyA); + createDynamicsNode(bodyB); + + if (hasLink(bodyA,bodyB)) + { + THROW_VR_EXCEPTION("Joints are already connected:" << bodyA->getName() << "," << bodyB->getName()); + } + BulletObjectPtr drn1 = boost::dynamic_pointer_cast<BulletObject>(dynamicRobotNodes[bodyA]); + BulletObjectPtr drn2 = boost::dynamic_pointer_cast<BulletObject>(dynamicRobotNodes[bodyB]); + VR_ASSERT(drn1); + VR_ASSERT(drn2); + boost::shared_ptr<btRigidBody> btBody1 = drn1->getRigidBody(); + boost::shared_ptr<btRigidBody> btBody2 = drn2->getRigidBody(); + VR_ASSERT(btBody1); + VR_ASSERT(btBody2); + + + Eigen::Matrix4f coordSystemNode1 = bodyA->getGlobalPoseJoint(); // todo: what if joint is not at 0 ?! + Eigen::Matrix4f coordSystemNode2 = bodyB->getGlobalPoseJoint(); + Eigen::Matrix4f coordSystemJoint = joint->getGlobalPoseJoint(); + + Eigen::Matrix4f anchorPointGlobal = joint->getGlobalPoseJoint();//node1->getGlobalPose() * node2->getPreJointTransformation(); // + + Eigen::Matrix4f anchor_inNode1 = coordSystemNode1.inverse() * anchorPointGlobal; + Eigen::Matrix4f anchor_inNode2 = coordSystemNode2.inverse() * anchorPointGlobal; + + + // The bullet model was adjusted, so that origin is at local com + // since we computed the anchor in from simox models, we must re-adjust the anchor, in order to consider the com displacement + Eigen::Matrix4f com1; + com1.setIdentity(); + com1.block(0,3,3,1) = -drn1->getCom(); + anchor_inNode1 = com1 * anchor_inNode1; + + Eigen::Matrix4f com2; + com2.setIdentity(); + com2.block(0,3,3,1) = -drn2->getCom(); + anchor_inNode2 = com2 * anchor_inNode2; + + boost::shared_ptr<btTypedConstraint> jointbt; + + float vr2bulletOffset = 0.0f; + + THROW_VR_EXCEPTION_IF (joint->isTranslationalJoint(), "Translational joints nyi..."); + if (joint->isRotationalJoint()) + { + // create joint + boost::shared_ptr<RobotNodeRevolute> rnRevJoint = boost::dynamic_pointer_cast<RobotNodeRevolute>(joint); + + // transform axis direction (not position!) + Eigen::Vector4f axisLocalJoint = Eigen::Vector4f::Zero(); + axisLocalJoint.block(0,0,3,1) = rnRevJoint->getJointRotationAxisInJointCoordSystem(); + Eigen::Matrix4f tmpGpJoint = coordSystemJoint; + tmpGpJoint.block(0,3,3,1).setZero(); // coordSystemJoint + Eigen::Vector4f axisGlobal = tmpGpJoint * axisLocalJoint; + + float limMin,limMax; + limMin = joint->getJointLimitLo(); + limMax = joint->getJointLimitHi(); + + if (joint2) + { + + VR_WARNING << "HINGE2 Joints are experimental (1:" << joint->getName() << ", 2:" << joint2->getName() << "): Assuming hing2/universal joint is defined as needed by bullet (see universal constraint header documentation)" << endl; + // UNIVERSAL/HINGE2 joint + boost::shared_ptr<RobotNodeRevolute> rnRevJoint2 = boost::dynamic_pointer_cast<RobotNodeRevolute>(joint2); + THROW_VR_EXCEPTION_IF (!rnRevJoint2, "Second joint must be a revolute joint..."); + Eigen::Matrix4f coordSystemJoint2 = joint2->getGlobalPoseJoint(); + + Eigen::Vector4f axisLocalJoint2= Eigen::Vector4f::Zero(); + axisLocalJoint2.block(0,0,3,1) = rnRevJoint2->getJointRotationAxisInJointCoordSystem(); + Eigen::Matrix4f tmpGpJoint2 = coordSystemJoint2; + tmpGpJoint2.block(0,3,3,1).setZero(); + + Eigen::Vector4f axisGlobal2 = tmpGpJoint2 * axisLocalJoint2; + + + btVector3 axis1 = BulletEngine::getVecBullet(axisGlobal.head(3),false); + btVector3 axis2 = BulletEngine::getVecBullet(axisGlobal2.head(3),false); + btVector3 pivot = BulletEngine::getVecBullet(anchorPointGlobal.block(0,3,3,1)); + boost::shared_ptr<btUniversalConstraint> hinge2(new btUniversalConstraint(*btBody1, *btBody2, pivot, axis1, axis2)); + float limMin2,limMax2; + limMin2 = joint2->getJointLimitLo(); + limMax2 = joint2->getJointLimitHi(); + hinge2->setLowerLimit(btScalar(limMin),btScalar(limMin2)); + hinge2->setUpperLimit(btScalar(limMax),btScalar(limMax2)); + jointbt = hinge2; + } else + { + // HINGE joint + Eigen::Matrix4f tmpGp1 = coordSystemNode1; + tmpGp1.block(0,3,3,1).setZero(); + Eigen::Matrix4f tmpGp2 = coordSystemNode2; + tmpGp2.block(0,3,3,1).setZero(); + Eigen::Vector3f axis_inLocal1 = (tmpGp1.inverse() * axisGlobal).block(0,0,3,1); + Eigen::Vector3f axis_inLocal2 = (tmpGp2.inverse() * axisGlobal).block(0,0,3,1); + //Eigen::Vector3f axis_inLocal2 = rnRev2->getJointRotationAxisInJointCoordSystem(); + + btVector3 pivot1 = BulletEngine::getVecBullet(anchor_inNode1.block(0,3,3,1)); + btVector3 pivot2 = BulletEngine::getVecBullet(anchor_inNode2.block(0,3,3,1)); + + + + #ifdef USE_BULLET_GENERIC_6DOF_CONSTRAINT + THROW_VR_EXCEPTION ("USE_BULLET_GENERIC_6DOF_CONSTRAINT nyi in this method..."); + #endif + //btVector3 axis1 = BulletEngine::getVecBullet(axis_inLocal1,false); + //btVector3 axis2 = BulletEngine::getVecBullet(axis_inLocal2,false); + //boost::shared_ptr<btHingeConstraint> hinge(new btHingeConstraint(*btBody1, *btBody2, pivot1, pivot2, axis1, axis2,false)); + + // we need to align coord system joint, so that z-axis is rotation axis + Eigen::Vector3f axisGlobal = rnRevJoint->getJointRotationAxis(); + Eigen::Vector3f axisLocal = rnRevJoint->getJointRotationAxisInJointCoordSystem(); + MathTools::Quaternion q1 = MathTools::getRotation(Eigen::Vector3f::UnitZ(),axisLocal); + Eigen::Matrix4f rotationzAlignment = MathTools::quat2eigen4f(q1); + Eigen::Matrix4f coordSystemJoint_zAligned = coordSystemJoint * rotationzAlignment ; + + // get transformation coord1 -> joint coord + Eigen::Matrix4f trafoNode1 = coordSystemNode1.inverse() * coordSystemJoint_zAligned; + // get transformation coord2 -> joint coord + Eigen::Matrix4f trafoNode2 = coordSystemNode2.inverse() * coordSystemJoint_zAligned; + + // now we need to pivot points in local coord systems + btTransform tr1 = BulletEngine::getPoseBullet(trafoNode1); + btTransform tr2 = BulletEngine::getPoseBullet(trafoNode2); + tr1.getOrigin() = pivot1; + tr2.getOrigin() = pivot2; + + boost::shared_ptr<btHingeConstraint> hinge(new btHingeConstraint(*btBody1, *btBody2, tr1, tr2, true)); + + // todo: check effects of parameters... + //hinge->setParam(BT_CONSTRAINT_STOP_ERP,0.9f); + /* + hinge->setParam(BT_CONSTRAINT_CFM,0.9f); + hinge->setParam(BT_CONSTRAINT_STOP_CFM,0.01f);*/ + //hinge->setLimit(limMin,limMax);//,btScalar(1.0f)); + //hinge->setParam(BT_CONSTRAINT_CFM,1.0f); + + btScalar startAngle = joint->getJointValue(); + btScalar startAngleBT = hinge->getHingeAngle(); + btScalar limMinBT, limMaxBT; + btScalar diff = joint->getJointValueOffset();//startAngleBT + startAngle); + limMinBT = limMin + diff;//diff - limMax;// + limMaxBT = limMax + diff;//diff - limMin;// + if (fabs(startAngleBT - startAngle)>1e-6) + { + cout << "joint " << joint->getName() << ": jv diff:" << diff << endl; + cout << "Simox limits: " << limMin << "/" << limMax << ", bullet limits:" << limMinBT << "/" << limMaxBT << endl; + } + hinge->setLimit(btScalar(limMinBT),btScalar(limMaxBT)); + vr2bulletOffset = diff; + //hinge->setLimit(btScalar(limMin),btScalar(limMax)); + //hinge->setAngularOnly(true); + jointbt = hinge; + } + } else + { + // create fixed joint + btTransform localA,localB; + localA = BulletEngine::getPoseBullet(anchor_inNode1); + localB = BulletEngine::getPoseBullet(anchor_inNode2); + boost::shared_ptr<btGeneric6DofConstraint> generic6Dof(new btGeneric6DofConstraint(*btBody1, *btBody2, localA, localB, true)); + generic6Dof->setOverrideNumSolverIterations(100); + + for (int i=0;i<6;i++) + generic6Dof->setLimit(i,0,0); + + /*generic6Dof->setParam(BT_CONSTRAINT_STOP_CFM,0.01f,0); + generic6Dof->setParam(BT_CONSTRAINT_STOP_CFM,0.01f,1); + generic6Dof->setParam(BT_CONSTRAINT_STOP_CFM,0.01f,2); + generic6Dof->setParam(BT_CONSTRAINT_STOP_CFM,0.01f,3); + generic6Dof->setParam(BT_CONSTRAINT_STOP_CFM,0.01f,4); + generic6Dof->setParam(BT_CONSTRAINT_STOP_CFM,0.01f,5);*/ + /*generic6Dof->setParam(BT_CONSTRAINT_STOP_ERP,0.9f,0); + generic6Dof->setParam(BT_CONSTRAINT_STOP_ERP,0.9f,1); + generic6Dof->setParam(BT_CONSTRAINT_STOP_ERP,0.9f,2); + generic6Dof->setParam(BT_CONSTRAINT_STOP_ERP,0.9f,3); + generic6Dof->setParam(BT_CONSTRAINT_STOP_ERP,0.9f,4); + generic6Dof->setParam(BT_CONSTRAINT_STOP_ERP,0.9f,5);*/ + jointbt = generic6Dof; + } + LinkInfo i; + i.nodeA = bodyA; + i.nodeB = bodyB; + i.dynNode1 = drn1; + i.dynNode2 = drn2; + i.nodeJoint = joint; + i.nodeJoint2 = joint2; + i.joint = jointbt; + i.jointValueOffset = vr2bulletOffset; + + // disable col model + i.disabledCollisionPairs.push_back( + std::pair<DynamicsObjectPtr,DynamicsObjectPtr>( + boost::dynamic_pointer_cast<DynamicsObject>(drn1), + boost::dynamic_pointer_cast<DynamicsObject>(drn2))); + + links.push_back(i); +#ifndef DEBUG_FIXED_OBJECTS + if (enableJointMotors && joint->isRotationalJoint()) { - createDynamicsNode(node2); + // start standard actuator + actuateNode(joint,joint->getJointValue()); } +#endif +} + +void BulletRobot::createLink( VirtualRobot::RobotNodePtr node1,VirtualRobot::RobotNodePtr node2, bool enableJointMotors ) +{ + THROW_VR_EXCEPTION_IF (!(node1->hasChild(node2)),"node1 must be parent of node2"); + + // ensure dynamics nodes are created + createDynamicsNode(node1); + createDynamicsNode(node2); if (hasLink(node1,node2)) { @@ -102,8 +539,6 @@ void BulletRobot::createLink( VirtualRobot::RobotNodePtr node1,VirtualRobot::Rob VR_ASSERT(btBody1); VR_ASSERT(btBody2); - - Eigen::Matrix4f coordSystemNode1 = node1->getGlobalPoseJoint(); // todo: what if joint is not at 0 ?! Eigen::Matrix4f coordSystemNode2 = node2->getGlobalPoseJoint(); @@ -385,8 +820,9 @@ void BulletRobot::createLink( VirtualRobot::RobotNodePtr node1,VirtualRobot::Rob #endif } LinkInfo i; - i.node1 = node1; - i.node2 = node2; + i.nodeA = node1; + i.nodeB = node2; + i.nodeJoint = node2; i.dynNode1 = drn1; i.dynNode2 = drn2; i.joint = joint; @@ -433,7 +869,7 @@ bool BulletRobot::hasLink( VirtualRobot::RobotNodePtr node1, VirtualRobot::Robot { for (size_t i=0; i<links.size();i++) { - if (links[i].node1 == node1 && links[i].node2 == node2) + if (links[i].nodeA == node1 && links[i].nodeB == node2) return true; } return false; @@ -490,29 +926,57 @@ void BulletRobot::actuateJoints(float dt) m->m_enableMotor = false; #else boost::shared_ptr<btHingeConstraint> hinge = boost::dynamic_pointer_cast<btHingeConstraint>(link.joint); - VR_ASSERT(hinge); - if (it->second.enabled) - { - btScalar targ = btScalar(it->second.jointValueTarget+link.jointValueOffset); - //btScalar act = btScalar(it->first->getJointValue()); - btScalar act = btScalar(getJointAngle(it->first)); - hinge->enableAngularMotor(true,(targ-act),10.0f); - //hinge->enableMotor(true); - //hinge->setMotorTarget(it->second.jointValueTarget+link.jointValueOffset,dt); - } else - hinge->enableMotor(false); + if (!hinge) + { + // hinge2 / universal joint + boost::shared_ptr<btUniversalConstraint> hinge2 = boost::dynamic_pointer_cast<btUniversalConstraint>(link.joint); + VR_ASSERT(hinge2); + btRotationalLimitMotor *m; + if (it->second.node==link.nodeJoint) + { + m = hinge2->getRotationalLimitMotor(1); // second motor + } else + { + VR_ASSERT(it->second.node==link.nodeJoint2); + m = hinge2->getRotationalLimitMotor(2); // third motor + } + VR_ASSERT(m); + if (it->second.enabled) + { + btScalar targ = btScalar(it->second.jointValueTarget+link.jointValueOffset); + //btScalar act = btScalar(it->first->getJointValue()); + btScalar act = btScalar(getJointAngle(it->first)); + m->m_enableMotor = true; + m->m_targetVelocity = (targ-act); // inverted joint dir?! + } else + m->m_enableMotor = false; + } else + { + if (it->second.enabled) + { + btScalar targ = btScalar(it->second.jointValueTarget+link.jointValueOffset); + //btScalar act = btScalar(it->first->getJointValue()); + btScalar act = btScalar(getJointAngle(it->first)); + hinge->enableAngularMotor(true,(targ-act),10.0f); + //hinge->enableMotor(true); + //hinge->setMotorTarget(it->second.jointValueTarget+link.jointValueOffset,dt); + } else + hinge->enableMotor(false); + } #endif } it++; } + + setPoseNonActuatedRobotNodes(); } BulletRobot::LinkInfo BulletRobot::getLink( VirtualRobot::RobotNodePtr node ) { for (size_t i=0;i<links.size();i++) { - if (links[i].node2 == node) + if (links[i].nodeJoint == node || links[i].nodeJoint2 == node) return links[i]; } THROW_VR_EXCEPTION("No link with node " << node->getName()); @@ -523,7 +987,7 @@ bool BulletRobot::hasLink( VirtualRobot::RobotNodePtr node ) { for (size_t i=0;i<links.size();i++) { - if (links[i].node2 == node) + if (links[i].nodeJoint == node || links[i].nodeJoint2 == node) return true; } return false; @@ -532,8 +996,14 @@ bool BulletRobot::hasLink( VirtualRobot::RobotNodePtr node ) void BulletRobot::actuateNode( VirtualRobot::RobotNodePtr node, float jointValue ) { VR_ASSERT(node); + if (node->isRotationalJoint()) { + if (!hasLink(node)) + { + VR_ERROR << "No link for node " << node->getName() << endl; + return; + } LinkInfo link = getLink(node); #ifdef USE_BULLET_GENERIC_6DOF_CONSTRAINT boost::shared_ptr<btGeneric6DofConstraint> dof = boost::dynamic_pointer_cast<btGeneric6DofConstraint>(link.joint); @@ -546,8 +1016,28 @@ void BulletRobot::actuateNode( VirtualRobot::RobotNodePtr node, float jointValue DynamicsRobot::actuateNode(node,jointValue); #else boost::shared_ptr<btHingeConstraint> hinge = boost::dynamic_pointer_cast<btHingeConstraint>(link.joint); - VR_ASSERT(hinge); - hinge->enableAngularMotor(true,0.0f,bulletMaxMotorImulse);// is max impulse ok?! (10 seems to be ok, 1 oscillates) + if (!hinge) + { + // hinge2 / universal joint + boost::shared_ptr<btUniversalConstraint> hinge2 = boost::dynamic_pointer_cast<btUniversalConstraint>(link.joint); + VR_ASSERT(hinge2); + btRotationalLimitMotor *m; + if (node==link.nodeJoint) + { + m = hinge2->getRotationalLimitMotor(1); // second motor + } else + { + VR_ASSERT(node==link.nodeJoint2); + m = hinge2->getRotationalLimitMotor(2); // third motor + } + VR_ASSERT(m); + m->m_enableMotor = true; + m->m_maxMotorForce = 5;//bulletMaxMotorImulse; //?! + m->m_maxLimitForce = 300; + } else + { + hinge->enableAngularMotor(true,0.0f,bulletMaxMotorImulse);// is max impulse ok?! (10 seems to be ok, 1 oscillates) + } DynamicsRobot::actuateNode(node,jointValue); // inverted joint direction in bullet #endif } else @@ -582,8 +1072,23 @@ float BulletRobot::getJointAngle( VirtualRobot::RobotNodePtr rn ) boost::shared_ptr<btHingeConstraint> hinge = boost::dynamic_pointer_cast<btHingeConstraint>(link.joint); if (!hinge) { - //VR_WARNING << "RobotNode " << rn->getName() << " is not associated with a hinge joint?!" << endl; - return 0.0f; + // hinge2 / universal joint + boost::shared_ptr<btUniversalConstraint> hinge2 = boost::dynamic_pointer_cast<btUniversalConstraint>(link.joint); + if (!hinge2) + return 0.0f; + btRotationalLimitMotor *m; + if (rn==link.nodeJoint) + { + m = hinge2->getRotationalLimitMotor(1); // second motor + } else if (rn==link.nodeJoint2) + { + m = hinge2->getRotationalLimitMotor(2); // third motor + } else + return 0.0f; + VR_ASSERT(m); + hinge2->calculateTransforms(); + float a2 = m->m_currentPosition; + return (a2-link.jointValueOffset);// inverted joint direction in bullet } return (hinge->getHingeAngle()-link.jointValueOffset);// inverted joint direction in bullet #endif @@ -607,9 +1112,22 @@ float BulletRobot::getJointSpeed( VirtualRobot::RobotNodePtr rn ) #else boost::shared_ptr<btHingeConstraint> hinge = boost::dynamic_pointer_cast<btHingeConstraint>(link.joint); if (!hinge) - { - VR_WARNING << "RobotNode " << rn->getName() << " is not associated with a hinge joint?!" << endl; - return 0.0f; + { + // hinge2 / universal joint + boost::shared_ptr<btUniversalConstraint> hinge2 = boost::dynamic_pointer_cast<btUniversalConstraint>(link.joint); + if (!hinge2) + return 0.0f; + btRotationalLimitMotor *m; + if (rn==link.nodeJoint) + { + m = hinge2->getRotationalLimitMotor(1); // second motor + } else if (rn==link.nodeJoint2) + { + m = hinge2->getRotationalLimitMotor(2); // third motor + } else + return 0.0f; + VR_ASSERT(m); + return m->m_targetVelocity; } return hinge->getMotorTargetVelosity(); #endif @@ -636,4 +1154,50 @@ Eigen::Matrix4f BulletRobot::getComGlobal( VirtualRobot::RobotNodePtr rn ) return bo->getComGlobal(); } +void BulletRobot::setPoseNonActuatedRobotNodes() +{ + VR_ASSERT(robot); + std::vector<RobotNodePtr> rns = robot->getRobotNodes(); + std::vector<RobotNodePtr> actuatedNodes; + std::vector<RobotNodePtr> notActuatedNodes; + size_t i; + // only objects with collisionmodel are processed by bullet + for (i=0;i<rns.size();i++) + { + if (rns[i]->getCollisionModel()) + actuatedNodes.push_back(rns[i]); + else + notActuatedNodes.push_back(rns[i]); + } + size_t lastSize = notActuatedNodes.size(); + while (notActuatedNodes.size()>0) + { + vector<RobotNodePtr>::iterator it = notActuatedNodes.begin(); + while (it!=notActuatedNodes.end()) + { + SceneObjectPtr parent = (*it)->getParent(); + if (!parent || find(actuatedNodes.begin(), actuatedNodes.end(), parent)!=actuatedNodes.end()) + { + // parent is at correct pose, we can update *it + if (parent) + (*it)->updatePose(false); + + // if root, we also have to delete node from list + actuatedNodes.push_back(*it); + it = notActuatedNodes.erase(it); + } else + it++; + } + + + // just a sanity check + if (lastSize == notActuatedNodes.size()) + { + VR_ERROR << "Internal error?!" << endl; + return; + } else + lastSize = notActuatedNodes.size(); + } +} + } // namespace VirtualRobot diff --git a/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.h b/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.h index 5f68a801e..430eff56b 100644 --- a/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.h +++ b/SimDynamics/DynamicsEngine/BulletEngine/BulletRobot.h @@ -47,8 +47,10 @@ public: struct LinkInfo { - VirtualRobot::RobotNodePtr node1; // parent - VirtualRobot::RobotNodePtr node2; // child + VirtualRobot::RobotNodePtr nodeA; // parent + VirtualRobot::RobotNodePtr nodeB; // child + VirtualRobot::RobotNodePtr nodeJoint; // joint + VirtualRobot::RobotNodePtr nodeJoint2; // joint2 (only used for hinge2/universal joints) BulletObjectPtr dynNode1; // parent BulletObjectPtr dynNode2; // child std::vector< std::pair<DynamicsObjectPtr,DynamicsObjectPtr> > disabledCollisionPairs; @@ -100,9 +102,22 @@ protected: void buildBulletModels(bool enableJointMotors); + //void createLink( VirtualRobot::RobotNodePtr bodyA, VirtualRobot::RobotNodePtr joint, VirtualRobot::RobotNodePtr bodyB, Eigen::Matrix4f &trafoA2J, Eigen::Matrix4f &trafoJ2B, bool enableJointMotors = true ); + // Possible joint types: + // fixed (joint=fixed !joint2) + // hinge (joint=revolute !joint2) + // universal (hinge2) (joint=revolute joint2=revolute) // experimental + void createLink( VirtualRobot::RobotNodePtr bodyA, VirtualRobot::RobotNodePtr joint, VirtualRobot::RobotNodePtr joint2, VirtualRobot::RobotNodePtr bodyB, bool enableJointMotors = true ); + void createLink(VirtualRobot::RobotNodePtr node1,VirtualRobot::RobotNodePtr node2, bool enableJointMotors); - std::vector<LinkInfo> links; + // ensure that all robot nodes, which are not actuated directly, are at the correct pose + void setPoseNonActuatedRobotNodes(); + + // process all ignoreCollision tags of physics section of RobotNode. Adds according collision disabled information to physics engine. + void addIgnoredCollisionModels(VirtualRobot::RobotNodePtr rn); + + std::vector<LinkInfo> links; btScalar bulletMaxMotorImulse; diff --git a/SimDynamics/DynamicsEngine/BulletEngine/SimoxMotionState.cpp b/SimDynamics/DynamicsEngine/BulletEngine/SimoxMotionState.cpp index cb3b52731..8659a06c6 100644 --- a/SimDynamics/DynamicsEngine/BulletEngine/SimoxMotionState.cpp +++ b/SimDynamics/DynamicsEngine/BulletEngine/SimoxMotionState.cpp @@ -121,10 +121,10 @@ void SimoxMotionState::setGlobalPoseSimox( const Eigen::Matrix4f& worldPose ) // we assume that all models are handled by Bullet, so we do not need to update children robotNodeActuator->updateVisualizationPose(resPose, ja, false); - } else + } /*else { VR_WARNING << "Could not determine dynamic robot?!" << endl; - } + }*/ } else { sceneObject->setGlobalPose(resPose); diff --git a/SimDynamics/examples/BulletDebugViewerGlut/BulletDebugViewerGlut.cpp b/SimDynamics/examples/BulletDebugViewerGlut/BulletDebugViewerGlut.cpp index d9c5e4f82..ddc11dbc7 100644 --- a/SimDynamics/examples/BulletDebugViewerGlut/BulletDebugViewerGlut.cpp +++ b/SimDynamics/examples/BulletDebugViewerGlut/BulletDebugViewerGlut.cpp @@ -26,14 +26,14 @@ int main(int argc,char* argv[]) world->addObject(dynObj); - //std::string robFile("robots/examples/SimpleRobot/Joint6.xml"); - std::string robFile("robots/iCub/iCub.xml"); + //std::string robFile("robots/examples/SimpleRobot/Joint5.xml"); + //std::string robFile("robots/iCub/iCub.xml"); //std::string robFile("robots/iCub/iCub_LeftLegTest.xml"); - //std::string robFile("robots/ArmarIII/ArmarIII-RightArm.xml"); + //std::string robFile("robots/ArmarIII/ArmarIII-RightArmTest5.xml"); //std::string robFile("robots/ArmarIII/ArmarIII-RightHandTest.xml"); //std::string robFile("robots/ArmarIII/ArmarIII-HeadTest.xml"); //std::string robFile("robots/ArmarIII/ArmarIII-RightArmTest2.xml"); - //std::string robFile("robots/ArmarIII/ArmarIII.xml"); + std::string robFile("robots/ArmarIII/ArmarIII.xml"); //std::string robFile("robots/iCub/iCub_RightHand.xml"); //std::string robFile("robots/iCub/iCub_testFinger.xml"); VirtualRobot::RuntimeEnvironment::getDataFileAbsolute(robFile); diff --git a/SimDynamics/examples/SimDynamicsViewer/SimDynamicsViewer.cpp b/SimDynamics/examples/SimDynamicsViewer/SimDynamicsViewer.cpp index 98bb05558..e24b2f3f0 100644 --- a/SimDynamics/examples/SimDynamicsViewer/SimDynamicsViewer.cpp +++ b/SimDynamics/examples/SimDynamicsViewer/SimDynamicsViewer.cpp @@ -37,8 +37,9 @@ int main(int argc, char *argv[]) cout << " --- START --- " << endl; // --robot "robots/iCub/iCub.xml" //std::string filename("robots/iCub/iCub.xml"); - //std::string filename("robots/ArmarIII/ArmarIII.xml"); - std::string filename("robots/examples/SimpleRobot/Joint6.xml"); + std::string filename("robots/ArmarIII/ArmarIII.xml"); + //std::string filename("robots/examples/SimpleRobot/Joint6.xml"); + //std::string filename("robots/ArmarIII/ArmarIII-RightArmTest6.xml"); if (VirtualRobot::RuntimeEnvironment::hasValue("robot")) { diff --git a/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp b/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp index 831c4c2ec..d7cfafb0c 100644 --- a/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp +++ b/SimDynamics/examples/SimDynamicsViewer/simDynamicsWindow.cpp @@ -276,13 +276,20 @@ bool SimDynamicsWindow::loadRobot(std::string robotFilename) cout << " ERROR while creating robot" << endl; return false; } - //robot->print(); - Eigen::Matrix4f gp = Eigen::Matrix4f::Identity(); - gp(2,3) = 200.0f; - robot->setGlobalPose(gp); - dynamicsRobot = dynamicsWorld->CreateDynamicsRobot(robot); - dynamicsWorld->addRobot(dynamicsRobot); - + try + { + //robot->print(); + Eigen::Matrix4f gp = Eigen::Matrix4f::Identity(); + gp(2,3) = 200.0f; + robot->setGlobalPose(gp); + dynamicsRobot = dynamicsWorld->CreateDynamicsRobot(robot); + dynamicsWorld->addRobot(dynamicsRobot); + }catch (VirtualRobotException &e) + { + cout << " ERROR while building dynamic robot" << endl; + cout << e.what(); + return false; + } updateJoints(); return true; } @@ -344,17 +351,26 @@ void SimDynamicsWindow::updateJointInfo() info << "jv rn:" << tmp.toStdString(); qJV += QString(" / "); - tmp = QString::number(dynamicsRobot->getJointAngle(rn),'f',3); + if (dynamicsRobot->isNodeActuated(rn)) + tmp = QString::number(dynamicsRobot->getJointAngle(rn),'f',3); + else + tmp = QString("-"); qJV += tmp; info << ",\tjv bul:" << tmp.toStdString(); qTarget = QString("Joint target: "); - tmp = QString::number(dynamicsRobot->getNodeTarget(rn),'f',3); + if (dynamicsRobot->isNodeActuated(rn)) + tmp = QString::number(dynamicsRobot->getNodeTarget(rn),'f',3); + else + tmp = QString("-"); qTarget +=tmp; info << ",targ:" << tmp.toStdString(); qVel = QString("Joint velocity: "); - tmp = QString::number(dynamicsRobot->getJointSpeed(rn),'f',3); + if (dynamicsRobot->isNodeActuated(rn)) + tmp = QString::number(dynamicsRobot->getJointSpeed(rn),'f',3); + else + tmp = QString("-"); qVel +=tmp; info << ",vel:" << tmp.toStdString(); Eigen::Matrix4f gp = rn->getGlobalPose(); @@ -381,8 +397,10 @@ void SimDynamicsWindow::updateJointInfo() qVisu += QString::number(gp(1,3),'f',2); qVisu += QString("/"); qVisu += QString::number(gp(2,3),'f',2); - - gp = dynamicsRobot->getComGlobal(rn); + if (dynamicsRobot->hasDynamicsRobotNode(rn)) + gp = dynamicsRobot->getComGlobal(rn); + else + gp = Eigen::Matrix4f::Identity(); qCom = QString("COM (bullet):"); qCom += QString::number(gp(0,3),'f',2); qCom += QString("/"); @@ -447,6 +465,7 @@ void SimDynamicsWindow::updateContactVisu() std::vector<SimDynamics::DynamicsEngine::DynamicsContactInfo> c = dynamicsWorld->getEngine()->getContacts(); for (size_t i=0;i<c.size();i++) { + cout << "Contact: " << c[i].objectA->getName() << " + " << c[i].objectB->getName() << endl; SoSeparator *normal = new SoSeparator; SoMatrixTransform *m = new SoMatrixTransform; SbMatrix ma; diff --git a/VirtualRobot/Nodes/RobotNode.cpp b/VirtualRobot/Nodes/RobotNode.cpp index 73e58960e..b97cf6391 100644 --- a/VirtualRobot/Nodes/RobotNode.cpp +++ b/VirtualRobot/Nodes/RobotNode.cpp @@ -30,11 +30,13 @@ RobotNode::RobotNode( RobotWeakPtr rob, CollisionModelPtr collisionModel, float jointValueOffset, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker) + CollisionCheckerPtr colChecker, + RobotNodeType type) : SceneObject(name,visualization,collisionModel,p,colChecker) { + nodeType = type; maxVelocity = 0.0f; maxAcceleration = 0.0f; maxTorque = 0.0f; @@ -82,9 +84,40 @@ bool RobotNode::initialize(SceneObjectPtr parent, const std::vector<SceneObjectP v->setGlobalPose(postJointTransformation); } + checkValidRobotNodeType(); + return SceneObject::initialize(parent,children); } +void RobotNode::checkValidRobotNodeType() +{ + switch (nodeType) + { + case Generic: + return; + break; + + case Joint: + THROW_VR_EXCEPTION_IF(visualizationModel, "No visualization models allowed in JointNodes"); + THROW_VR_EXCEPTION_IF(collisionModel, "No collision models allowed in JointNodes"); + THROW_VR_EXCEPTION_IF(postJointTransformation != Eigen::Matrix4f::Identity() , "No postJoint transformations allowed in JointNodes"); + break; + + case Body: + THROW_VR_EXCEPTION_IF(postJointTransformation != Eigen::Matrix4f::Identity() , "No transformations allowed in BodyNodes"); + THROW_VR_EXCEPTION_IF(preJointTransformation != Eigen::Matrix4f::Identity() , "No transformations allowed in BodyNodes"); + + break; + case Transform: + THROW_VR_EXCEPTION_IF(visualizationModel, "No visualization models allowed in TransformationNodes"); + THROW_VR_EXCEPTION_IF(collisionModel, "No collision models allowed in TransformationNodes"); + break; + default: + VR_ERROR << "RobotNodeType nyi..." << endl; + + } + +} RobotPtr RobotNode::getRobot() const { @@ -585,5 +618,10 @@ Eigen::Matrix4f RobotNode::getGlobalPose() const return globalPosePostJoint; } +RobotNode::RobotNodeType RobotNode::getType() +{ + return nodeType; +} + } // namespace VirtualRobot diff --git a/VirtualRobot/Nodes/RobotNode.h b/VirtualRobot/Nodes/RobotNode.h index ef0001bf1..b00281850 100644 --- a/VirtualRobot/Nodes/RobotNode.h +++ b/VirtualRobot/Nodes/RobotNode.h @@ -58,7 +58,7 @@ class RobotNodeActuator; */ -class VIRTUAL_ROBOT_IMPORT_EXPORT RobotNode : /*public boost::enable_shared_from_this<RobotNode>,*/ public SceneObject +class VIRTUAL_ROBOT_IMPORT_EXPORT RobotNode : public SceneObject { public: friend class Robot; @@ -68,6 +68,14 @@ public: friend class RobotNodeActuator; EIGEN_MAKE_ALIGNED_OPERATOR_NEW + enum RobotNodeType + { + Generic, //! No constraints + Joint, //! Only pre-joint transformations allowed (e.g. DH-theta for revolute joints). No visualization/collision models. + Body, //! No transformations allowed. Only visualization and/or collision models together with physic information. + Transform //! Only transformations allowed. No joint or model tags. + }; + /*! Constructor with settings. */ @@ -80,7 +88,8 @@ public: CollisionModelPtr collisionModel = CollisionModelPtr(), float jointValueOffset = 0.0f, const SceneObject::Physics &p = SceneObject::Physics(), - CollisionCheckerPtr colChecker = CollisionCheckerPtr()); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), + RobotNodeType type = Generic); /*! */ @@ -176,18 +185,6 @@ public: */ virtual void print(bool printChildren = false, bool printDecoration = true) const; - //virtual void addChildNode(RobotNodePtr child); - - /* - Returns true when child is a children of this node. If recursive is true, all children of children etc are also queried. - */ - //virtual bool hasChildNode(const RobotNodePtr child, bool recursive = false) const; - /* - Returns true when child is a children of this node. If recursive is true, all children of children etc are also queried. - */ - //virtual bool hasChildNode(const std::string &child, bool recursive = false) const; - - float getJointLimitLo(); float getJointLimitHi(); @@ -259,13 +256,22 @@ public: */ float getMaxTorque(); + RobotNodeType getType(); + //! Forbid cloning method from SceneObject. We need to know the new robot for cloning SceneObjectPtr clone( const std::string &name, CollisionCheckerPtr colChecker = CollisionCheckerPtr() ) const {THROW_VR_EXCEPTION("Cloning not allowed this way...");} -private: // Use the private setters and getters instead - //std::vector<std::string> childrenNames; - //std::vector< RobotNodePtr > children; - //RobotNodeWeakPtr parent; + /*! + When joint was created via DH parameters, they can be accessed here. + */ + const DHParameter& getOptionalDHParameters() {return optionalDHParameter;} + + + /*! + Compute/Update the transformations of this joint and all child joints. Therefore the parent is queried for its pose. + This method is called by the robot in order to update the pose matrices. + */ + virtual void updatePose(bool updateChildren = true); protected: @@ -281,13 +287,14 @@ protected: */ virtual void setJointValueNoUpdate(float q); - /*! - Compute/Update the transformations of this joint and all child joints. This method is called by the robot in order to update the pose matrices. - */ - void updatePose(bool updateChildren = true); + + /*! + Queries parent for global pose and updates visualization accordingly + */ + virtual void updateTransformationMatrices(); /*! - Update the pose of the robot + Update the pose according to parent */ virtual void updatePose( const Eigen::Matrix4f &parentPose, bool updateChildren = true ); @@ -303,6 +310,9 @@ protected: virtual void updateVisualizationPose(const Eigen::Matrix4f &globalPose, bool updateChildren = false); virtual void updateVisualizationPose(const Eigen::Matrix4f &globalPose, float jointValue, bool updateChildren = false); + //! Checks if nodeType constraints are fulfilled. Otherwise an exception is thrown. Called on initialization. + virtual void checkValidRobotNodeType(); + ///////////////////////// SETUP //////////////////////////////////// RobotNode(){}; @@ -316,18 +326,19 @@ protected: Eigen::Matrix4f postJointTransformation; ///////////////////////// SETUP //////////////////////////////////// - virtual void updateTransformationMatrices(); virtual void updateTransformationMatrices(const Eigen::Matrix4f &parentPose); RobotWeakPtr robot; + RobotNodeType nodeType; + - Eigen::Matrix4f globalPosePostJoint; //< The postJoint transformation applied to transformationJoint. Defines the starting pose for all child joints. + Eigen::Matrix4f globalPosePostJoint; //< The postJoint transformation applied to globalPose. Defines the starting pose for all child joints. float jointValue; //< The joint value /*! Derived classes must implement their clone method here. */ - virtual RobotNodePtr _clone(const RobotPtr newRobot, /*const std::vector<std::string> newChildren,*/ const VisualizationNodePtr visualizationModel, const CollisionModelPtr collisionModel, CollisionCheckerPtr colChecker) = 0; + virtual RobotNodePtr _clone(const RobotPtr newRobot, const VisualizationNodePtr visualizationModel, const CollisionModelPtr collisionModel, CollisionCheckerPtr colChecker) = 0; virtual SceneObject* _clone( const std::string &name, CollisionCheckerPtr colChecker = CollisionCheckerPtr() ) const {THROW_VR_EXCEPTION("Cloning not allowed this way...");} diff --git a/VirtualRobot/Nodes/RobotNodeFactory.h b/VirtualRobot/Nodes/RobotNodeFactory.h index 00183f743..6edcfcf3c 100644 --- a/VirtualRobot/Nodes/RobotNodeFactory.h +++ b/VirtualRobot/Nodes/RobotNodeFactory.h @@ -26,13 +26,14 @@ #include "../VirtualRobotImportExport.h" #include "../AbstractFactoryMethod.h" #include "../Transformation/DHParameter.h" +#include "RobotNode.h" #include <Eigen/Core> #include <boost/shared_ptr.hpp> + namespace VirtualRobot { -class RobotNode; class VIRTUAL_ROBOT_IMPORT_EXPORT RobotNodeFactory : public AbstractFactoryMethod<RobotNodeFactory, void*> { @@ -40,8 +41,8 @@ public: RobotNodeFactory() {;} virtual ~RobotNodeFactory() {;} - virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p) const {return RobotNodePtr();} - virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p) const {return RobotNodePtr();} + virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const {return RobotNodePtr();} + virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic ) const {return RobotNodePtr();} }; } // namespace VirtualRobot diff --git a/VirtualRobot/Nodes/RobotNodeFixed.cpp b/VirtualRobot/Nodes/RobotNodeFixed.cpp index 3285f986b..8a1a8b88f 100644 --- a/VirtualRobot/Nodes/RobotNodeFixed.cpp +++ b/VirtualRobot/Nodes/RobotNodeFixed.cpp @@ -17,12 +17,14 @@ RobotNodeFixed::RobotNodeFixed(RobotWeakPtr rob, VisualizationNodePtr visualization, CollisionModelPtr collisionModel, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker - ) : RobotNode(rob,name,0.0f,0.0f,visualization,collisionModel,0.0f,p,colChecker) + CollisionCheckerPtr colChecker, + RobotNodeType type + ) : RobotNode(rob,name,0.0f,0.0f,visualization,collisionModel,0.0f,p,colChecker,type) { optionalDHParameter.isSet = false; this->preJointTransformation = preJointTransform; this->postJointTransformation = postJointTransform; + checkValidRobotNodeType(); } RobotNodeFixed::RobotNodeFixed(RobotWeakPtr rob, @@ -31,8 +33,9 @@ RobotNodeFixed::RobotNodeFixed(RobotWeakPtr rob, VisualizationNodePtr visualization, CollisionModelPtr collisionModel, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker - ) : RobotNode(rob,name,0.0f,1.0f,visualization,collisionModel,0.0f,p,colChecker) + CollisionCheckerPtr colChecker, + RobotNodeType type + ) : RobotNode(rob,name,0.0f,1.0f,visualization,collisionModel,0.0f,p,colChecker,type) { initialized = false; optionalDHParameter.isSet = true; @@ -100,12 +103,18 @@ RobotNodePtr RobotNodeFixed::_clone(const RobotPtr newRobot, /*const std::vector RobotNodePtr result; if (optionalDHParameter.isSet) - result.reset(new RobotNodeFixed(newRobot,name,optionalDHParameter.aMM(),optionalDHParameter.dMM(), optionalDHParameter.alphaRadian(), optionalDHParameter.thetaRadian(),visualizationModel,collisionModel,physics,colChecker)); + result.reset(new RobotNodeFixed(newRobot,name,optionalDHParameter.aMM(),optionalDHParameter.dMM(), optionalDHParameter.alphaRadian(), optionalDHParameter.thetaRadian(),visualizationModel,collisionModel,physics,colChecker,nodeType)); else - result.reset(new RobotNodeFixed(newRobot,name,getPreJointTransformation(),getPostJointTransformation(),visualizationModel,collisionModel,physics,colChecker)); + result.reset(new RobotNodeFixed(newRobot,name,getPreJointTransformation(),getPostJointTransformation(),visualizationModel,collisionModel,physics,colChecker,nodeType)); return result; } +void RobotNodeFixed::checkValidRobotNodeType() +{ + RobotNode::checkValidRobotNodeType(); + THROW_VR_EXCEPTION_IF (nodeType==Joint, "RobotNodeFixed not compatible with JointNode"); +} + } // namespace diff --git a/VirtualRobot/Nodes/RobotNodeFixed.h b/VirtualRobot/Nodes/RobotNodeFixed.h index caa0186e6..937741dab 100644 --- a/VirtualRobot/Nodes/RobotNodeFixed.h +++ b/VirtualRobot/Nodes/RobotNodeFixed.h @@ -53,8 +53,8 @@ public: VisualizationNodePtr visualization = VisualizationNodePtr(),//!< A visualization model CollisionModelPtr collisionModel = CollisionModelPtr(), //!< A collision model const SceneObject::Physics &p = SceneObject::Physics(), //!< physics information - CollisionCheckerPtr colChecker = CollisionCheckerPtr() //!< A collision checker instance (if not set, the global col checker is used) - ); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), //!< A collision checker instance (if not set, the global col checker is used) + RobotNodeType type = Generic); /*! Initialize with DH parameters. @@ -73,8 +73,8 @@ public: VisualizationNodePtr visualization = VisualizationNodePtr(), //!< A visualization model CollisionModelPtr collisionModel = CollisionModelPtr(), //!< A collision model const SceneObject::Physics &p = SceneObject::Physics(), //!< physics information - CollisionCheckerPtr colChecker = CollisionCheckerPtr() //!< A collision checker instance (if not set, the global col checker is used) - ); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), //!< A collision checker instance (if not set, the global col checker is used) + RobotNodeType type = Generic); /*! */ @@ -88,6 +88,8 @@ public: virtual void print(bool printChildren = false, bool printDecoration = true) const; protected: + //! Checks if nodeType constraints are fulfilled. Otherwise an exception is thrown. Called on initialization. + virtual void checkValidRobotNodeType(); RobotNodeFixed(){}; virtual void updateTransformationMatrices(const Eigen::Matrix4f &parentPose); diff --git a/VirtualRobot/Nodes/RobotNodeFixedFactory.cpp b/VirtualRobot/Nodes/RobotNodeFixedFactory.cpp index df8ae3eea..212e4e9d6 100644 --- a/VirtualRobot/Nodes/RobotNodeFixedFactory.cpp +++ b/VirtualRobot/Nodes/RobotNodeFixedFactory.cpp @@ -26,9 +26,9 @@ RobotNodeFixedFactory::~RobotNodeFixedFactory() * * \return instance of VirtualRobot::RobotNodeFixed. */ -RobotNodePtr RobotNodeFixedFactory::createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p) const +RobotNodePtr RobotNodeFixedFactory::createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p, RobotNode::RobotNodeType rntype) const { - RobotNodePtr robotNode(new RobotNodeFixed(robot, nodeName, preJointTransform, postJointTransform, visualizationModel, collisionModel, p)); + RobotNodePtr robotNode(new RobotNodeFixed(robot, nodeName, preJointTransform, postJointTransform, visualizationModel, collisionModel, p, CollisionCheckerPtr(), rntype)); return robotNode; } @@ -39,9 +39,9 @@ RobotNodePtr RobotNodeFixedFactory::createRobotNode(RobotPtr robot, const std::s * * \return instance of VirtualRobot::RobotNodeFixed. */ -RobotNodePtr RobotNodeFixedFactory::createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p) const +RobotNodePtr RobotNodeFixedFactory::createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p, RobotNode::RobotNodeType rntype) const { - RobotNodePtr robotNode(new RobotNodeFixed(robot, nodeName,dhParameters.aMM(), dhParameters.dMM(), dhParameters.alphaRadian(), dhParameters.thetaRadian(), visualizationModel, collisionModel, p)); + RobotNodePtr robotNode(new RobotNodeFixed(robot, nodeName,dhParameters.aMM(), dhParameters.dMM(), dhParameters.alphaRadian(), dhParameters.thetaRadian(), visualizationModel, collisionModel, p, CollisionCheckerPtr(), rntype)); return robotNode; /* diff --git a/VirtualRobot/Nodes/RobotNodeFixedFactory.h b/VirtualRobot/Nodes/RobotNodeFixedFactory.h index 6331096f6..89b466fdb 100644 --- a/VirtualRobot/Nodes/RobotNodeFixedFactory.h +++ b/VirtualRobot/Nodes/RobotNodeFixedFactory.h @@ -40,8 +40,8 @@ public: RobotNodeFixedFactory(); virtual ~RobotNodeFixedFactory(); - virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics()) const; - virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics()) const; + virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const; + virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const; // AbstractFactoryMethod public: static std::string getName(); diff --git a/VirtualRobot/Nodes/RobotNodePrismatic.cpp b/VirtualRobot/Nodes/RobotNodePrismatic.cpp index 881c204f6..dd3eb411b 100644 --- a/VirtualRobot/Nodes/RobotNodePrismatic.cpp +++ b/VirtualRobot/Nodes/RobotNodePrismatic.cpp @@ -20,17 +20,16 @@ RobotNodePrismatic::RobotNodePrismatic(RobotWeakPtr rob, CollisionModelPtr collisionModel, float jointValueOffset, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker - ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker) - + CollisionCheckerPtr colChecker, + RobotNodeType type + ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker,type) { initialized = false; optionalDHParameter.isSet = false; this->preJointTransformation = preJointTransform; this->postJointTransformation = postJointTransform; - //this->setPreJointTransformation(preJointTransform); this->jointTranslationDirection = translationDirection; - //this->setPostJointTransformation(postJointTransform); + checkValidRobotNodeType(); } RobotNodePrismatic::RobotNodePrismatic(RobotWeakPtr rob, @@ -42,9 +41,9 @@ RobotNodePrismatic::RobotNodePrismatic(RobotWeakPtr rob, CollisionModelPtr collisionModel, float jointValueOffset, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker - ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker) - + CollisionCheckerPtr colChecker, + RobotNodeType type + ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker,type) { initialized = false; optionalDHParameter.isSet = true; @@ -70,11 +69,12 @@ RobotNodePrismatic::RobotNodePrismatic(RobotWeakPtr rob, RotAlpha(2,2) = cos(alpha); // fixed rotation around theta - this->preJointTransformation = RotTheta; + this->preJointTransformation = RotTheta*TransD; // joint setup jointTranslationDirection = Eigen::Vector3f(0,0,1); // translation along the z axis // compute postJointTransformation - this->postJointTransformation = TransD*TransA*RotAlpha; + this->postJointTransformation = TransA*RotAlpha; + checkValidRobotNodeType(); } RobotNodePrismatic::~RobotNodePrismatic() @@ -120,9 +120,9 @@ RobotNodePtr RobotNodePrismatic::_clone(const RobotPtr newRobot, /*const std::ve ReadLockPtr lock = getRobot()->getReadLock(); if (optionalDHParameter.isSet) - result.reset(new RobotNodePrismatic(newRobot,name, jointLimitLo,jointLimitHi,optionalDHParameter.aMM(),optionalDHParameter.dMM(), optionalDHParameter.alphaRadian(), optionalDHParameter.thetaRadian(),visualizationModel,collisionModel, jointValueOffset,physics,colChecker)); + result.reset(new RobotNodePrismatic(newRobot,name, jointLimitLo,jointLimitHi,optionalDHParameter.aMM(),optionalDHParameter.dMM(), optionalDHParameter.alphaRadian(), optionalDHParameter.thetaRadian(),visualizationModel,collisionModel, jointValueOffset,physics,colChecker,nodeType)); else - result.reset(new RobotNodePrismatic(newRobot,name,jointLimitLo,jointLimitHi,getPreJointTransformation(),jointTranslationDirection,getPostJointTransformation(),visualizationModel,collisionModel,jointValueOffset,physics,colChecker)); + result.reset(new RobotNodePrismatic(newRobot,name,jointLimitLo,jointLimitHi,getPreJointTransformation(),jointTranslationDirection,getPostJointTransformation(),visualizationModel,collisionModel,jointValueOffset,physics,colChecker,nodeType)); return result; } @@ -184,6 +184,12 @@ Eigen::Vector3f RobotNodePrismatic::getJointTranslationDirectionJointCoordSystem return jointTranslationDirection; } +void RobotNodePrismatic::checkValidRobotNodeType() +{ + RobotNode::checkValidRobotNodeType(); + THROW_VR_EXCEPTION_IF (nodeType==Body || nodeType==Transform, "RobotNodePrismatic must be a JointNode or a GenericNode"); +} + } // namespace diff --git a/VirtualRobot/Nodes/RobotNodePrismatic.h b/VirtualRobot/Nodes/RobotNodePrismatic.h index 01f06e6e1..956e8635c 100644 --- a/VirtualRobot/Nodes/RobotNodePrismatic.h +++ b/VirtualRobot/Nodes/RobotNodePrismatic.h @@ -58,8 +58,8 @@ public: CollisionModelPtr collisionModel = CollisionModelPtr(), //!< A collision model float jointValueOffset = 0.0f, //!< An offset that is internally added to the joint value const SceneObject::Physics &p = SceneObject::Physics(), //!< physics information - CollisionCheckerPtr colChecker = CollisionCheckerPtr() //!< A collision checker instance (if not set, the global col checker is used) - ); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), //!< A collision checker instance (if not set, the global col checker is used) + RobotNodeType type = Generic); RobotNodePrismatic( RobotWeakPtr rob, //!< The robot const std::string &name, //!< The name float jointLimitLo, //!< lower joint limit @@ -72,8 +72,8 @@ public: CollisionModelPtr collisionModel = CollisionModelPtr(), //!< A collision model float jointValueOffset = 0.0f, //!< An offset that is internally added to the joint value const SceneObject::Physics &p = SceneObject::Physics(), //!< physics information - CollisionCheckerPtr colChecker = CollisionCheckerPtr() //!< A collision checker instance (if not set, the global col checker is used) - ); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), //!< A collision checker instance (if not set, the global col checker is used) + RobotNodeType type = Generic); /*! */ virtual ~RobotNodePrismatic(); @@ -107,6 +107,9 @@ protected: */ virtual void updateVisualizationPose(const Eigen::Matrix4f &globalPose, bool updateChildren = false); + //! Checks if nodeType constraints are fulfilled. Otherwise an exception is thrown. Called on initialization. + virtual void checkValidRobotNodeType(); + RobotNodePrismatic(){}; virtual void updateTransformationMatrices(const Eigen::Matrix4f &parentPose); diff --git a/VirtualRobot/Nodes/RobotNodePrismaticFactory.cpp b/VirtualRobot/Nodes/RobotNodePrismaticFactory.cpp index 445c4e2ea..d488ca9f9 100644 --- a/VirtualRobot/Nodes/RobotNodePrismaticFactory.cpp +++ b/VirtualRobot/Nodes/RobotNodePrismaticFactory.cpp @@ -26,9 +26,9 @@ RobotNodePrismaticFactory::~RobotNodePrismaticFactory() * * \return instance of VirtualRobot::RobotNodePrismatic. */ -RobotNodePtr RobotNodePrismaticFactory::createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p) const +RobotNodePtr RobotNodePrismaticFactory::createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p, RobotNode::RobotNodeType rntype) const { - RobotNodePtr robotNode(new RobotNodePrismatic(robot, nodeName, limitLow, limitHigh, preJointTransform, translationDirection, postJointTransform, visualizationModel, collisionModel, jointValueOffset,p)); + RobotNodePtr robotNode(new RobotNodePrismatic(robot, nodeName, limitLow, limitHigh, preJointTransform, translationDirection, postJointTransform, visualizationModel, collisionModel, jointValueOffset,p,CollisionCheckerPtr(), rntype)); return robotNode; } @@ -39,9 +39,9 @@ RobotNodePtr RobotNodePrismaticFactory::createRobotNode(RobotPtr robot, const st * * \return instance of VirtualRobot::RobotNodePrismatic. */ -RobotNodePtr RobotNodePrismaticFactory::createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p) const +RobotNodePtr RobotNodePrismaticFactory::createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p, RobotNode::RobotNodeType rntype) const { - RobotNodePtr robotNode(new RobotNodePrismatic(robot, nodeName, limitLow, limitHigh, dhParameters.aMM(), dhParameters.dMM(), dhParameters.alphaRadian(), dhParameters.thetaRadian(), visualizationModel, collisionModel, jointValueOffset,p)); + RobotNodePtr robotNode(new RobotNodePrismatic(robot, nodeName, limitLow, limitHigh, dhParameters.aMM(), dhParameters.dMM(), dhParameters.alphaRadian(), dhParameters.thetaRadian(), visualizationModel, collisionModel, jointValueOffset,p,CollisionCheckerPtr(), rntype)); return robotNode; } diff --git a/VirtualRobot/Nodes/RobotNodePrismaticFactory.h b/VirtualRobot/Nodes/RobotNodePrismaticFactory.h index db3a2d5d1..5081a8007 100644 --- a/VirtualRobot/Nodes/RobotNodePrismaticFactory.h +++ b/VirtualRobot/Nodes/RobotNodePrismaticFactory.h @@ -40,8 +40,8 @@ public: RobotNodePrismaticFactory(); virtual ~RobotNodePrismaticFactory(); - virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics()) const; - virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics()) const; + virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const; + virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const; // AbstractFactoryMethod public: static std::string getName(); diff --git a/VirtualRobot/Nodes/RobotNodeRevolute.cpp b/VirtualRobot/Nodes/RobotNodeRevolute.cpp index d5a6c8aa3..db810c57c 100644 --- a/VirtualRobot/Nodes/RobotNodeRevolute.cpp +++ b/VirtualRobot/Nodes/RobotNodeRevolute.cpp @@ -21,15 +21,16 @@ RobotNodeRevolute::RobotNodeRevolute(RobotWeakPtr rob, CollisionModelPtr collisionModel, float jointValueOffset, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker - ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker) - + CollisionCheckerPtr colChecker, + RobotNodeType type + ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker,type) { initialized = false; optionalDHParameter.isSet = false; this->preJointTransformation = preJointTransform; this->jointRotationAxis = axis; this->postJointTransformation = postJointTransform; + checkValidRobotNodeType(); } RobotNodeRevolute::RobotNodeRevolute(RobotWeakPtr rob, @@ -41,8 +42,9 @@ RobotNodeRevolute::RobotNodeRevolute(RobotWeakPtr rob, CollisionModelPtr collisionModel, float jointValueOffset, const SceneObject::Physics &p, - CollisionCheckerPtr colChecker - ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker) + CollisionCheckerPtr colChecker, + RobotNodeType type + ) : RobotNode(rob,name,jointLimitLo,jointLimitHi,visualization,collisionModel,jointValueOffset,p,colChecker,type) { initialized = false; @@ -68,9 +70,10 @@ RobotNodeRevolute::RobotNodeRevolute(RobotWeakPtr rob, RotAlpha(2,1) = sin(alpha); RotAlpha(2,2) = cos(alpha); - this->preJointTransformation = RotTheta;//Eigen::Matrix4f::Identity(); // no pre transformation->why? + this->preJointTransformation = RotTheta; this->jointRotationAxis = Eigen::Vector3f(0,0,1); // rotation around z axis this->postJointTransformation = TransD*TransA*RotAlpha; + checkValidRobotNodeType(); } @@ -115,9 +118,9 @@ RobotNodePtr RobotNodeRevolute::_clone(const RobotPtr newRobot, /*const std::vec RobotNodePtr result; if (optionalDHParameter.isSet) - result.reset(new RobotNodeRevolute(newRobot,name, jointLimitLo,jointLimitHi,optionalDHParameter.aMM(),optionalDHParameter.dMM(), optionalDHParameter.alphaRadian(), optionalDHParameter.thetaRadian(),visualizationModel,collisionModel, jointValueOffset,physics,colChecker)); + result.reset(new RobotNodeRevolute(newRobot,name, jointLimitLo,jointLimitHi,optionalDHParameter.aMM(),optionalDHParameter.dMM(), optionalDHParameter.alphaRadian(), optionalDHParameter.thetaRadian(),visualizationModel,collisionModel, jointValueOffset,physics,colChecker,nodeType)); else - result.reset(new RobotNodeRevolute(newRobot,name,jointLimitLo,jointLimitHi,getPreJointTransformation(),jointRotationAxis,getPostJointTransformation(),visualizationModel,collisionModel,jointValueOffset,physics,colChecker)); + result.reset(new RobotNodeRevolute(newRobot,name,jointLimitLo,jointLimitHi,getPreJointTransformation(),jointRotationAxis,getPostJointTransformation(),visualizationModel,collisionModel,jointValueOffset,physics,colChecker,nodeType)); return result; } @@ -179,4 +182,10 @@ Eigen::Vector3f RobotNodeRevolute::getJointRotationAxisInJointCoordSystem() cons return jointRotationAxis; } +void RobotNodeRevolute::checkValidRobotNodeType() +{ + RobotNode::checkValidRobotNodeType(); + THROW_VR_EXCEPTION_IF (nodeType==Body || nodeType==Transform, "RobotNodeRevolute must be a JointNode or a GenericNode"); +} + } // namespace diff --git a/VirtualRobot/Nodes/RobotNodeRevolute.h b/VirtualRobot/Nodes/RobotNodeRevolute.h index 1ece8d072..fcca1098d 100644 --- a/VirtualRobot/Nodes/RobotNodeRevolute.h +++ b/VirtualRobot/Nodes/RobotNodeRevolute.h @@ -59,8 +59,8 @@ public: CollisionModelPtr collisionModel = CollisionModelPtr(), //!< A collision model float jointValueOffset = 0.0f, //!< An offset that is internally added to the joint value const SceneObject::Physics &p = SceneObject::Physics(), //!< physics information - CollisionCheckerPtr colChecker = CollisionCheckerPtr() //!< A collision checker instance (if not set, the global col checker is used) - ); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), //!< A collision checker instance (if not set, the global col checker is used) + RobotNodeType type = Generic); RobotNodeRevolute( RobotWeakPtr rob, //!< The robot const std::string &name, //!< The name float jointLimitLo, //!< lower joint limit @@ -73,8 +73,8 @@ public: CollisionModelPtr collisionModel = CollisionModelPtr(), //!< A collision model float jointValueOffset = 0.0f, //!< An offset that is internally added to the joint value const SceneObject::Physics &p = SceneObject::Physics(), //!< physics information - CollisionCheckerPtr colChecker = CollisionCheckerPtr() //!< A collision checker instance (if not set, the global col checker is used) - ); + CollisionCheckerPtr colChecker = CollisionCheckerPtr(), //!< A collision checker instance (if not set, the global col checker is used) + RobotNodeType type = Generic); /*! */ virtual ~RobotNodeRevolute(); @@ -106,6 +106,8 @@ protected: */ virtual void updateVisualizationPose(const Eigen::Matrix4f &globalPose, bool updateChildren = false); + //! Checks if nodeType constraints are fulfilled. Otherwise an exception is thrown. Called on initialization. + virtual void checkValidRobotNodeType(); RobotNodeRevolute(){}; diff --git a/VirtualRobot/Nodes/RobotNodeRevoluteFactory.cpp b/VirtualRobot/Nodes/RobotNodeRevoluteFactory.cpp index 3c9a7cd1f..1cb0d19ac 100644 --- a/VirtualRobot/Nodes/RobotNodeRevoluteFactory.cpp +++ b/VirtualRobot/Nodes/RobotNodeRevoluteFactory.cpp @@ -26,9 +26,9 @@ RobotNodeRevoluteFactory::~RobotNodeRevoluteFactory() * * \return instance of VirtualRobot::RobotNodeRevolute. */ -RobotNodePtr RobotNodeRevoluteFactory::createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p) const +RobotNodePtr RobotNodeRevoluteFactory::createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p, RobotNode::RobotNodeType rntype) const { - RobotNodePtr robotNode(new RobotNodeRevolute(robot, nodeName, limitLow, limitHigh, preJointTransform, axis, postJointTransform, visualizationModel, collisionModel, jointValueOffset, p)); + RobotNodePtr robotNode(new RobotNodeRevolute(robot, nodeName, limitLow, limitHigh, preJointTransform, axis, postJointTransform, visualizationModel, collisionModel, jointValueOffset, p, CollisionCheckerPtr(), rntype)); return robotNode; } @@ -39,9 +39,9 @@ RobotNodePtr RobotNodeRevoluteFactory::createRobotNode(RobotPtr robot, const std * * \return instance of VirtualRobot::RobotNodeRevolute. */ -RobotNodePtr RobotNodeRevoluteFactory::createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p) const +RobotNodePtr RobotNodeRevoluteFactory::createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p, RobotNode::RobotNodeType rntype) const { - RobotNodePtr robotNode(new RobotNodeRevolute(robot, nodeName, limitLow, limitHigh, dhParameters.aMM(), dhParameters.dMM(), dhParameters.alphaRadian(), dhParameters.thetaRadian(), visualizationModel, collisionModel, jointValueOffset, p)); + RobotNodePtr robotNode(new RobotNodeRevolute(robot, nodeName, limitLow, limitHigh, dhParameters.aMM(), dhParameters.dMM(), dhParameters.alphaRadian(), dhParameters.thetaRadian(), visualizationModel, collisionModel, jointValueOffset, p, CollisionCheckerPtr(), rntype)); return robotNode; } diff --git a/VirtualRobot/Nodes/RobotNodeRevoluteFactory.h b/VirtualRobot/Nodes/RobotNodeRevoluteFactory.h index db77e5882..793c8e574 100644 --- a/VirtualRobot/Nodes/RobotNodeRevoluteFactory.h +++ b/VirtualRobot/Nodes/RobotNodeRevoluteFactory.h @@ -38,8 +38,8 @@ public: RobotNodeRevoluteFactory(); virtual ~RobotNodeRevoluteFactory(); - virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics()) const; - virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics()) const; + virtual RobotNodePtr createRobotNode(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const Eigen::Matrix4f& preJointTransform, const Eigen::Vector3f& axis, const Eigen::Matrix4f& postJointTransform, const Eigen::Vector3f& translationDirection, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const; + virtual RobotNodePtr createRobotNodeDH(RobotPtr robot, const std::string& nodeName, VisualizationNodePtr visualizationModel, CollisionModelPtr collisionModel, float limitLow, float limitHigh, float jointValueOffset, const DHParameter& dhParameters, const SceneObject::Physics &p = SceneObject::Physics(), RobotNode::RobotNodeType rntype = RobotNode::Generic) const; // AbstractFactoryMethod public: static std::string getName(); diff --git a/VirtualRobot/SceneObject.cpp b/VirtualRobot/SceneObject.cpp index 47ff473b7..985139f05 100644 --- a/VirtualRobot/SceneObject.cpp +++ b/VirtualRobot/SceneObject.cpp @@ -634,4 +634,10 @@ void SceneObject::attached( SceneObjectPtr parent ) } + +std::vector<std::string> SceneObject::getIgnoredCollisionModels() +{ + return physics.ignoreCollisions; +} + } // namespace diff --git a/VirtualRobot/SceneObject.h b/VirtualRobot/SceneObject.h index 886260009..248138d7e 100644 --- a/VirtualRobot/SceneObject.h +++ b/VirtualRobot/SceneObject.h @@ -70,11 +70,17 @@ public: std::cout << " ** Mass: " << massKg << " [kg]" << std::endl; std::cout << " ** local CoM [mm]: " << localCoM(0) << localCoM(1) << localCoM(2) << std::endl; std::cout << " ** inertia matrix [kg*m^2] :\n " << intertiaMatrix << std::endl; + if (ignoreCollisions.size()>0) + { + std::cout << " ** Ignore Collisions with:" << std::endl; + for (size_t i=0;i<ignoreCollisions.size();i++) + std::cout << " **** " << ignoreCollisions[i] << std::endl; + } } bool isSet() { - return (massKg!=0.0f || comLocation!=eCustom || !localCoM.isZero() || !intertiaMatrix.isIdentity()); + return (massKg!=0.0f || comLocation!=eCustom || !localCoM.isZero() || !intertiaMatrix.isIdentity() || ignoreCollisions.size()>0); } std::string getXMLString(int tabs) @@ -95,6 +101,8 @@ public: ss << ta << "\t<InertiaMatrix>\n"; ss << MathTools::getTransformXMLString(intertiaMatrix,tabs+2,true); ss << ta << "\t</InertiaMatrix>\n"; + for (size_t i=0;i<ignoreCollisions.size();i++) + ss << ta << "\t<IgnoreCollisions name='" << ignoreCollisions[i] << "'/>\n"; ss << ta << "</Physics>\n"; return ss.str(); } @@ -103,6 +111,7 @@ public: float massKg; //!< The mass of this object CoMLocation comLocation; //!< Where is the CoM located Eigen::Matrix3f intertiaMatrix; //! in kg*m^2 + std::vector< std::string > ignoreCollisions; // ignore collisions with other objects (only used within collision engines) }; /*! @@ -268,6 +277,11 @@ public: void setInertiaMatrix(const Eigen::Matrix3f &im); + /*! + Collisions with these models are ignored by physics engine (only considered within the SimDynamics package!). + */ + std::vector<std::string> getIgnoredCollisionModels(); + virtual void print(bool printChildren = false, bool printDecoration = true) const; @@ -330,6 +344,9 @@ public: virtual std::vector<SceneObjectPtr> getChildren() const {return children;} + //! Compute the global pose of this object + virtual void updatePose( bool updateChildren = true); + protected: virtual SceneObject* _clone( const std::string &name, CollisionCheckerPtr colChecker = CollisionCheckerPtr() ) const; @@ -338,8 +355,6 @@ protected: //! Parent attached this object virtual void attached(SceneObjectPtr parent); - //! Compute the global pose of this object - virtual void updatePose( bool updateChildren = true); virtual void updatePose( const Eigen::Matrix4f &parentPose, bool updateChildren = true ); diff --git a/VirtualRobot/Transformation/DHParameter.h b/VirtualRobot/Transformation/DHParameter.h index 5d8a265d0..33b808c01 100644 --- a/VirtualRobot/Transformation/DHParameter.h +++ b/VirtualRobot/Transformation/DHParameter.h @@ -36,6 +36,10 @@ public: DHParameter() { _a = _d = _alpha = _theta = 0; + _thetaRotation = Eigen::Matrix4f::Identity(); + _dTranslation = Eigen::Matrix4f::Identity(); + _aTranslation = Eigen::Matrix4f::Identity(); + _alphaRotation = Eigen::Matrix4f::Identity(); isSet = false; }; @@ -78,6 +82,14 @@ public: return _alphaRotation; } + //! The complete transformation + Eigen::Matrix4f transformation() const + { + return _thetaRotation*_dTranslation*_aTranslation*_alphaRotation; + } + + + bool isSet; protected: void updateTransformations() diff --git a/VirtualRobot/XML/BaseIO.cpp b/VirtualRobot/XML/BaseIO.cpp index 0a7c32c29..fe0393569 100644 --- a/VirtualRobot/XML/BaseIO.cpp +++ b/VirtualRobot/XML/BaseIO.cpp @@ -290,6 +290,51 @@ void BaseIO::processTransformNode(rapidxml::xml_node<char> *transformXMLNode, co } } } + + // DH + rapidxml::xml_node<> *dhXMLNode = trXMLNode->first_node("dh",0,false); + THROW_VR_EXCEPTION_IF((dhXMLNode && (rotation||translation)), "Multiple rotations/translations defined in <Transformation> tag: " << tagName << "! Ignoring DH node." << endl); + + if (dhXMLNode) + { + DHParameter dh; + processDHNode(dhXMLNode,dh); + transform = dh.transformation(); + rotation = true; + translation = true; + } +} + + +void BaseIO::processDHNode(rapidxml::xml_node<char> *dhXMLNode, DHParameter &dh) +{ + rapidxml::xml_attribute<> *attr; + std::vector< Units > unitsAttr = getUnitsAttributes(dhXMLNode); + Units uAngle("rad"); + Units uLength("mm"); + for (size_t i=0;i<unitsAttr.size();i++) + { + if (unitsAttr[i].isAngle()) + uAngle = unitsAttr[i]; + if (unitsAttr[i].isLength()) + uLength = unitsAttr[i]; + } + + dh.isSet = true; + bool isRadian = uAngle.isRadian(); + + attr = dhXMLNode->first_attribute("a", 0, false); + if (attr) + dh.setAInMM(uLength.toMillimeter(convertToFloat(attr->value()))); + attr = dhXMLNode->first_attribute("d", 0, false); + if (attr) + dh.setDInMM(uLength.toMillimeter(convertToFloat(attr->value()))); + attr = dhXMLNode->first_attribute("alpha", 0, false); + if (attr) + dh.setAlphaRadian(convertToFloat(attr->value()), isRadian); + attr = dhXMLNode->first_attribute("theta", 0, false); + if (attr) + dh.setThetaRadian(convertToFloat(attr->value()), isRadian); } bool BaseIO::hasUnitsAttribute(rapidxml::xml_node<char> *node) @@ -880,23 +925,15 @@ void BaseIO::processPhysicsTag(rapidxml::xml_node<char> *physicsXMLNode, const s physics.intertiaMatrix *= factor; } - /*rapidxml::xml_node<> *velXMLNode = physicsXMLNode->first_node("maxVelocity",0,false); - if (velXMLNode) - { - physics.maxVelocity = getFloatByAttributeName(velXMLNode,"value"); + rapidxml::xml_node<> *ignoreColXMLNode = physicsXMLNode->first_node("ignorecollision",0,false); + while (ignoreColXMLNode) + { + rapidxml::xml_attribute<> *attr = ignoreColXMLNode->first_attribute("name", 0, false); + THROW_VR_EXCEPTION_IF(!attr, "Expecting 'name' attribute in <IgnoreCollision> tag..." << endl) + std::string s(attr->value()); + physics.ignoreCollisions.push_back(s); + ignoreColXMLNode = ignoreColXMLNode->next_sibling("ignorecollision",0,false); } - rapidxml::xml_node<> *accXMLNode = physicsXMLNode->first_node("maxAcceleration",0,false); - if (accXMLNode) - { - physics.maxAcceleration = getFloatByAttributeName(accXMLNode,"value"); - } - - rapidxml::xml_node<> *torXMLNode = physicsXMLNode->first_node("maxTorque",0,false); - if (torXMLNode) - { - physics.maxTorque = getFloatByAttributeName(torXMLNode,"value"); - } */ - } std::string BaseIO::processFileNode( rapidxml::xml_node<char> *fileNode, const std::string &basePath ) diff --git a/VirtualRobot/XML/BaseIO.h b/VirtualRobot/XML/BaseIO.h index 4764ca2e1..09fbe95eb 100644 --- a/VirtualRobot/XML/BaseIO.h +++ b/VirtualRobot/XML/BaseIO.h @@ -101,7 +101,8 @@ protected: static bool hasUnitsAttribute(rapidxml::xml_node<char> *node); static std::vector< Units > getUnitsAttributes(rapidxml::xml_node<char> *node); static void getAllAttributes(rapidxml::xml_node<char> *node, const std::string &attrString, std::vector<std::string> &storeValues); - static boost::mutex mutex; + static void processDHNode(rapidxml::xml_node<char> *dhXMLNode, DHParameter &dh); + static boost::mutex mutex; }; } diff --git a/VirtualRobot/XML/RobotIO.cpp b/VirtualRobot/XML/RobotIO.cpp index a00cf22ed..16a7409bc 100644 --- a/VirtualRobot/XML/RobotIO.cpp +++ b/VirtualRobot/XML/RobotIO.cpp @@ -140,7 +140,9 @@ RobotNodePtr RobotIO::processJointNode(rapidxml::xml_node<char> *jointXMLNode, c RobotPtr robot, VisualizationNodePtr visualizationNode, CollisionModelPtr collisionModel, - SceneObject::Physics &physics + SceneObject::Physics &physics, + RobotNode::RobotNodeType rntype, + Eigen::Matrix4f &transformationMatrix ) { float jointLimitLow = (float)-M_PI; @@ -161,9 +163,10 @@ RobotNodePtr RobotIO::processJointNode(rapidxml::xml_node<char> *jointXMLNode, c if (!jointXMLNode) { // no <Joint> tag -> fixed joint + postJointTransform = transformationMatrix; // used by TransformationNodes RobotNodeFactoryPtr fixedNodeFactory = RobotNodeFactory::fromName(RobotNodeFixedFactory::getName(), NULL); if (fixedNodeFactory) - robotNode = fixedNodeFactory->createRobotNode(robot, robotNodeName, visualizationNode, collisionModel, jointLimitLow, jointLimitHigh, jointOffset, preJointTransform, axis, postJointTransform, translationDir, physics); + robotNode = fixedNodeFactory->createRobotNode(robot, robotNodeName, visualizationNode, collisionModel, jointLimitLow, jointLimitHigh, jointOffset, preJointTransform, axis, postJointTransform, translationDir, physics, rntype); return robotNode; } @@ -302,33 +305,8 @@ RobotNodePtr RobotIO::processJointNode(rapidxml::xml_node<char> *jointXMLNode, c { // check for wrongly defined nodes THROW_VR_EXCEPTION_IF((prejointTransformNode || tmpXMLNodeAxis || tmpXMLNodeTranslation || postjointTransformNode), "DH specification can not be used together with Axis, TranslationDirection, PreJointTransform or PostJointTransform definitions in <Joint> tag of node " << robotNodeName << endl); - - std::vector< Units > unitsAttr = getUnitsAttributes(dhXMLNode); - Units uAngle("rad"); - Units uLength("mm"); - for (size_t i=0;i<unitsAttr.size();i++) - { - if (unitsAttr[i].isAngle()) - uAngle = unitsAttr[i]; - if (unitsAttr[i].isLength()) - uLength = unitsAttr[i]; - } - - dh.isSet = true; - bool isRadian = uAngle.isRadian(); - - attr = dhXMLNode->first_attribute("a", 0, false); - if (attr) - dh.setAInMM(uLength.toMillimeter(convertToFloat(attr->value()))); - attr = dhXMLNode->first_attribute("d", 0, false); - if (attr) - dh.setDInMM(uLength.toMillimeter(convertToFloat(attr->value()))); - attr = dhXMLNode->first_attribute("alpha", 0, false); - if (attr) - dh.setAlphaRadian(convertToFloat(attr->value()), isRadian); - attr = dhXMLNode->first_attribute("theta", 0, false); - if (attr) - dh.setThetaRadian(convertToFloat(attr->value()), isRadian); + processDHNode(dhXMLNode,dh); + } else { dh.isSet = false; @@ -365,11 +343,11 @@ RobotNodePtr RobotIO::processJointNode(rapidxml::xml_node<char> *jointXMLNode, c { if (dh.isSet) { - robotNode = robotNodeFactory->createRobotNodeDH(robot, robotNodeName, visualizationNode, collisionModel, jointLimitLow, jointLimitHigh, jointOffset, dh, physics); + robotNode = robotNodeFactory->createRobotNodeDH(robot, robotNodeName, visualizationNode, collisionModel, jointLimitLow, jointLimitHigh, jointOffset, dh, physics, rntype); } else { // create nodes that are not defined via DH parameters - robotNode = robotNodeFactory->createRobotNode(robot, robotNodeName, visualizationNode, collisionModel, jointLimitLow, jointLimitHigh, jointOffset, preJointTransform, axis, postJointTransform, translationDir, physics); + robotNode = robotNodeFactory->createRobotNode(robot, robotNodeName, visualizationNode, collisionModel, jointLimitLow, jointLimitHigh, jointOffset, preJointTransform, axis, postJointTransform, translationDir, physics, rntype); } } else @@ -382,13 +360,15 @@ RobotNodePtr RobotIO::processJointNode(rapidxml::xml_node<char> *jointXMLNode, c } + RobotNodePtr RobotIO::processRobotNode(rapidxml::xml_node<char> *robotNodeXMLNode, RobotPtr robo, const std::string &basePath, int &robotNodeCounter, std::vector< std::string > &childrenNames, std::vector< ChildFromRobotDef > &childrenFromRobot, - RobotDescription loadMode) + RobotDescription loadMode, + RobotNode::RobotNodeType rntype) { childrenFromRobot.clear(); THROW_VR_EXCEPTION_IF(!robotNodeXMLNode, "NULL data in processRobotNode"); @@ -418,6 +398,7 @@ RobotNodePtr RobotIO::processRobotNode(rapidxml::xml_node<char> *robotNodeXMLNod RobotNodePtr robotNode; SceneObject::Physics physics; bool physicsDefined = false; + Eigen::Matrix4f transformMatrix = Eigen::Matrix4f::Identity(); rapidxml::xml_node<>* node = robotNodeXMLNode->first_node(); rapidxml::xml_node<>* jointNodeXML = NULL; @@ -479,7 +460,10 @@ RobotNodePtr RobotIO::processRobotNode(rapidxml::xml_node<char> *robotNodeXMLNod THROW_VR_EXCEPTION_IF(physicsDefined, "Two physics tags defined in RobotNode '" << robotNodeName << "'." << endl); processPhysicsTag(node,robotNodeName,physics); physicsDefined= true; - } else + } else if (nodeName == "transform") + { + processTransformNode(robotNodeXMLNode,robotNodeName,transformMatrix); + } else { THROW_VR_EXCEPTION("XML definition <" << nodeName << "> not supported in RobotNode <" << robotNodeName << ">." << endl); } @@ -489,7 +473,7 @@ RobotNodePtr RobotIO::processRobotNode(rapidxml::xml_node<char> *robotNodeXMLNod //create joint from xml data - robotNode = processJointNode(jointNodeXML,robotNodeName, robo, visualizationNode, collisionModel, physics); + robotNode = processJointNode(jointNodeXML,robotNodeName, robo, visualizationNode, collisionModel, physics, rntype, transformMatrix); return robotNode; } @@ -694,11 +678,19 @@ void RobotIO::processRobotChildNodes(rapidxml::xml_node<char>* robotXMLNode, { std::string nodeName_ = XMLNode->name(); std::string nodeName = getLowerCase(XMLNode->name()); - if (nodeName == "robotnode") + if (nodeName == "robotnode" || nodeName == "jointnode" || nodeName == "transformationnode" || nodeName == "bodynode") { std::vector< ChildFromRobotDef > childrenFromRobot; std::vector< std::string > childrenNames; - RobotNodePtr n = processRobotNode(XMLNode, robo, basePath, robotNodeCounter, childrenNames, childrenFromRobot,loadMode); + // check for type + RobotNode::RobotNodeType rntype = RobotNode::Generic; + if (nodeName == "jointnode") + rntype = RobotNode::Joint; + if (nodeName == "bodynode") + rntype = RobotNode::Body; + if (nodeName == "transformationnode") + rntype = RobotNode::Transform; + RobotNodePtr n = processRobotNode(XMLNode, robo, basePath, robotNodeCounter, childrenNames, childrenFromRobot,loadMode,rntype); if (!n) { std::string failedNodeName = processNameAttribute(XMLNode); diff --git a/VirtualRobot/XML/RobotIO.h b/VirtualRobot/XML/RobotIO.h index 3347fc7b2..64f41401b 100644 --- a/VirtualRobot/XML/RobotIO.h +++ b/VirtualRobot/XML/RobotIO.h @@ -105,7 +105,8 @@ protected: int &robotNodeCounter, std::vector< std::string > &childrenNames, std::vector< ChildFromRobotDef > &childrenFromRobot, - RobotDescription loadMode = eFull); + RobotDescription loadMode = eFull, + RobotNode::RobotNodeType rntype = RobotNode::Generic); static EndEffectorPtr processEndeffectorNode(rapidxml::xml_node<char>* endeffectorXMLNode, RobotPtr robo); static EndEffectorActorPtr processEndeffectorActorNode(rapidxml::xml_node<char>* endeffectorActorXMLNode, RobotPtr robo); static void processEndeffectorStaticNode(rapidxml::xml_node<char>* endeffectorStaticXMLNode, RobotPtr robo, std::vector<RobotNodePtr>& staticNodesList); @@ -113,13 +114,13 @@ protected: static void processActorNodeList(rapidxml::xml_node<char>* parentNode, RobotPtr robot, std::vector<EndEffectorActor::ActorDefinition>& actorList, bool clearList = true); //static RobotNodeSetPtr processRobotNodeSet(rapidxml::xml_node<char> *setXMLNode, RobotPtr robo, const std::string &rootName, int &robotNodeSetCounter); static void processChildNode(rapidxml::xml_node<char> *childXMLNode, std::vector<std::string> &childrenNames); - static RobotNodePtr processJointNode(rapidxml::xml_node<char> *jointXMLNode, const std::string& robotNodeName, - RobotPtr robot, VisualizationNodePtr visualizationNode, CollisionModelPtr collisionModel, SceneObject::Physics &physics); + static RobotNodePtr processJointNode( rapidxml::xml_node<char> *jointXMLNode, const std::string& robotNodeName, + RobotPtr robot, VisualizationNodePtr visualizationNode, CollisionModelPtr collisionModel, + SceneObject::Physics &physics, RobotNode::RobotNodeType rntype,Eigen::Matrix4f &transformationMatrix); static void processChildFromRobotNode(rapidxml::xml_node<char> *childXMLNode, const std::string &nodeName, std::vector< ChildFromRobotDef > &childrenFromRobot); static void processLimitsNode(rapidxml::xml_node<char> *limitsXMLNode, float &jointLimitLo, float &jointLimitHi); static std::map<std::string,int> robot_name_counter; static VisualizationNodePtr checkUseAsColModel(rapidxml::xml_node<char>* visuXMLNode, const std::string &robotNodeName, const std::string &basePath); - }; } diff --git a/VirtualRobot/data/robots/ArmarIII/ArmarIII-Head.xml b/VirtualRobot/data/robots/ArmarIII/ArmarIII-Head.xml index 551d9153a..9dd9dcff8 100644 --- a/VirtualRobot/data/robots/ArmarIII/ArmarIII-Head.xml +++ b/VirtualRobot/data/robots/ArmarIII/ArmarIII-Head.xml @@ -36,6 +36,7 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="4" units="kg" /> + <IgnoreCollision name="Hip Yaw"/> </Physics> <CollisionModel> @@ -58,6 +59,8 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="2" units="kg" /> + <IgnoreCollision name="Hip Yaw"/> + <IgnoreCollision name="Head Base"/> </Physics> <CollisionModel> @@ -98,6 +101,8 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="6.79877000" units="kg" /> + <IgnoreCollision name="Neck_2_Roll"/> + <IgnoreCollision name="Hip Yaw"/> </Physics> <Visualization> diff --git a/VirtualRobot/data/robots/ArmarIII/ArmarIII-LeftArm.xml b/VirtualRobot/data/robots/ArmarIII/ArmarIII-LeftArm.xml index 6180587cd..1de6bc1d9 100644 --- a/VirtualRobot/data/robots/ArmarIII/ArmarIII-LeftArm.xml +++ b/VirtualRobot/data/robots/ArmarIII/ArmarIII-LeftArm.xml @@ -53,6 +53,7 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="1.55685000" units="kg" /> + <IgnoreCollision name="Shoulder 1 L"/> </Physics> <Visualization enable="true"> <File type="Inventor">fullmodel/upperarm_l.iv</File> @@ -129,6 +130,7 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="2.59945309" units="kg" /> + <IgnoreCollision name="Underarm L"/> </Physics> <Visualization enable="true"> <CoordinateAxis type="Inventor" enable="false" scaling="8"/> diff --git a/VirtualRobot/data/robots/ArmarIII/ArmarIII-RightArm.xml b/VirtualRobot/data/robots/ArmarIII/ArmarIII-RightArm.xml index 67167acb2..4761bac35 100644 --- a/VirtualRobot/data/robots/ArmarIII/ArmarIII-RightArm.xml +++ b/VirtualRobot/data/robots/ArmarIII/ArmarIII-RightArm.xml @@ -52,6 +52,7 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="1.55685000" units="kg" /> + <IgnoreCollision name="Shoulder 1 R"/> </Physics> <Visualization enable="true"> <File type="Inventor">fullmodel/upperarm_r.iv</File> @@ -134,6 +135,7 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="2.59945309" units="kg" /> + <IgnoreCollision name="Underarm R"/> </Physics> <ChildFromRobot> <File importEEF="true">ArmarIII-RightHand.xml</File> diff --git a/VirtualRobot/data/robots/ArmarIII/ArmarIII.xml b/VirtualRobot/data/robots/ArmarIII/ArmarIII.xml index 49a5f4372..24d2e4b1b 100644 --- a/VirtualRobot/data/robots/ArmarIII/ArmarIII.xml +++ b/VirtualRobot/data/robots/ArmarIII/ArmarIII.xml @@ -18,9 +18,9 @@ </RobotNode> <RobotNode name="X_Platform"> - <Joint type="prismatic"> + <Joint type="fixed"> <DH a="0" d="0" theta="90" alpha="-90" units="degree"/> - <Limits unit="mm" lo="-10000" hi="10000"/> + <!--Limits unit="mm" lo="-10000" hi="10000"/--> </Joint> <Visualization enable="true"> <CoordinateAxis type="Inventor" enable="false" scaling="8"/> @@ -29,9 +29,9 @@ </RobotNode> <RobotNode name="Y_Platform"> - <Joint type="prismatic"> + <Joint type="fixed"> <DH a="0" d="0" theta="-90" alpha="90" units="degree"/> - <Limits unit="mm" lo="-10000" hi="10000"/> + <!--Limits unit="mm" lo="-10000" hi="10000"/--> </Joint> <Visualization enable="true"> <CoordinateAxis type="Inventor" enable="false" scaling="8"/> @@ -102,6 +102,7 @@ </Visualization> <Physics> <Mass value="10" units="kg" /> + <IgnoreCollision name="Platform"/> </Physics> <CollisionModel> <File type="Inventor">convexModel/platform_roll_link.iv</File> @@ -117,6 +118,8 @@ <Physics> <CoM location="VisualizationBBoxCenter"/> <Mass value="15.415" units="kg" /> + <IgnoreCollision name="Hip Pitch"/> + <IgnoreCollision name="Platform"/> </Physics> <Visualization enable="true"> <CoordinateAxis type="Inventor" enable="false" scaling="8"/> diff --git a/VirtualRobot/examples/RobotViewer/showRobotWindow.cpp b/VirtualRobot/examples/RobotViewer/showRobotWindow.cpp index 0403aeab3..26be1ecf8 100644 --- a/VirtualRobot/examples/RobotViewer/showRobotWindow.cpp +++ b/VirtualRobot/examples/RobotViewer/showRobotWindow.cpp @@ -402,6 +402,11 @@ void showRobotWindow::loadRobot() { robotSep->removeAllChildren(); cout << "Loading Robot from " << m_sRobotFilename << endl; + currentEEF.reset(); + currentRobotNode.reset(); + currentRobotNodes.clear(); + currentRobotNodeSet.reset(); + robot.reset(); try { @@ -475,6 +480,38 @@ void showRobotWindow::closeHand() void showRobotWindow::openHand() { +#if 1 + if (robot) + { + float randMult = (float)(1.0/(double)(RAND_MAX)); + std::vector<RobotNodePtr> rn = robot->getRobotNodes(); + std::vector<RobotNodePtr> rnJoints; + for (size_t j=0;j<rn.size();j++) + { + if (rn[j]->isRotationalJoint()) + rnJoints.push_back(rn[j]); + } + int loops = 10000; + clock_t startT = clock(); + for (int i=0;i<loops;i++) + { + std::vector<float> jv; + for (size_t j=0;j<rnJoints.size();j++) + { + float t = (float)rand() * randMult; // value from 0 to 1 + t = rnJoints[j]->getJointLimitLo() + (rnJoints[j]->getJointLimitHi() - rnJoints[j]->getJointLimitLo())*t; + jv.push_back(t); + } + robot->setJointValues(rnJoints,jv); + } + clock_t endT = clock(); + + float diffClock = (float)(((float)(endT - startT) / (float)CLOCKS_PER_SEC) * 1000.0f); + cout << "RobotNodes:" << rn.size() << endl; + cout << "Joints:" << rnJoints.size() << endl; + cout << "loops:" << loops << ". time (ms):" << diffClock << ". Per loop:" << diffClock/(float)loops << endl; + } +#endif if (currentEEF) currentEEF->openActors(); } -- GitLab