diff --git a/CMakeLists.txt b/CMakeLists.txt index 83f1408f8372f35500b6217eaaf3dd267b65a2b5..4fb17c66efe4c08637d69ab38a5304346ecdbe57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,8 @@ ADD_REQUIRED_DEPENDENCY("jrl-dynamics >= 1.16.1") ADD_REQUIRED_DEPENDENCY("hrp2-dynamics >= 1.3.0") ADD_REQUIRED_DEPENDENCY("hrp2-10-optimized >= 1.0") -ADD_REQUIRED_DEPENDENCY("hrp2_10 >= 1.0.0") -ADD_REQUIRED_DEPENDENCY("hrp2_14 >= 1.0.0") +ADD_REQUIRED_DEPENDENCY("hrp2-10 >= 1.0.0") +ADD_REQUIRED_DEPENDENCY("hrp2-14 >= 1.0.0") ADD_REQUIRED_DEPENDENCY("dynamic-graph >= 1.0.0") ADD_REQUIRED_DEPENDENCY("sot-core >= 1.0.0") diff --git a/include/sot-dynamic/angle-estimator.h b/include/sot-dynamic/angle-estimator.h index 70153b372dfb6f3fabf4a8c322e3374a75df62b9..169d4389c238ff481415cbc69f806b0b7ea17754 100644 --- a/include/sot-dynamic/angle-estimator.h +++ b/include/sot-dynamic/angle-estimator.h @@ -66,6 +66,7 @@ class SOTANGLEESTIMATOR_EXPORT AngleEstimator { public: static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } public: /* --- CONSTRUCTION --- */ diff --git a/include/sot-dynamic/dynamic-hrp2.h b/include/sot-dynamic/dynamic-hrp2.h index 12f1a0d4118a3d4648f48df6471d506a1c5ed747..416016b900c4c00112c8664300c57e84a5ce9ee0 100644 --- a/include/sot-dynamic/dynamic-hrp2.h +++ b/include/sot-dynamic/dynamic-hrp2.h @@ -65,6 +65,10 @@ class SOTDYNAMICHRP2_EXPORT DynamicHrp2 { public: + virtual const std::string& getClassName () const + { + return CLASS_NAME; + } static const std::string CLASS_NAME; public: /* --- CONSTRUCTION --- */ diff --git a/include/sot-dynamic/dynamic-hrp2_10.h b/include/sot-dynamic/dynamic-hrp2_10.h index a3908f6980fb5ec98b274f71cf2068133f910cc0..2d97df514545ad7f0df03a6a0d3c83eecb41e315 100644 --- a/include/sot-dynamic/dynamic-hrp2_10.h +++ b/include/sot-dynamic/dynamic-hrp2_10.h @@ -67,6 +67,10 @@ class DYNAMICHRP2_10_EXPORT DynamicHrp2_10 DynamicHrp2_10( const std::string& name ); virtual ~DynamicHrp2_10( void ); + virtual const std::string& getClassName () const + { + return CLASS_NAME; + } public: /* --- MODEL CREATION --- */ diff --git a/include/sot-dynamic/dynamic.h b/include/sot-dynamic/dynamic.h index 7aa63f10ad4d79791acf012697e88c0dfb6111f1..a21c5bbdbe16354541660da4a81dce5b1e84eef4 100644 --- a/include/sot-dynamic/dynamic.h +++ b/include/sot-dynamic/dynamic.h @@ -93,7 +93,7 @@ class SOTDYNAMIC_EXPORT Dynamic friend class sot::command::InitializeRobot; public: - static const std::string CLASS_NAME; + DYNAMIC_GRAPH_ENTITY_DECL(); protected: public: diff --git a/include/sot-dynamic/force-compensation.h b/include/sot-dynamic/force-compensation.h index bc7e72c8da14d2c1a42c964c02d2b4d9d767e93d..09fd8405e41721b0488c706f14633b0aaecc5545 100644 --- a/include/sot-dynamic/force-compensation.h +++ b/include/sot-dynamic/force-compensation.h @@ -136,6 +136,7 @@ namespace dynamicgraph { namespace sot { { public: static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } bool calibrationStarted; diff --git a/include/sot-dynamic/integrator-force.h b/include/sot-dynamic/integrator-force.h index 5b9af5ea826a2e21c82efe5af2033aaefa2a8016..6abc8e2edde5b26569a2b138d7e0e81f904db24c 100644 --- a/include/sot-dynamic/integrator-force.h +++ b/include/sot-dynamic/integrator-force.h @@ -67,6 +67,7 @@ class SOTINTEGRATORFORCE_EXPORT IntegratorForce { public: static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } protected: double timeStep; diff --git a/include/sot-dynamic/mass-apparent.h b/include/sot-dynamic/mass-apparent.h index e54fa65e1274ae2556b4c6e17cdc5f012617b0c7..0d5d77617006dbf77a3fa15053a3066dddd219a7 100644 --- a/include/sot-dynamic/mass-apparent.h +++ b/include/sot-dynamic/mass-apparent.h @@ -66,6 +66,7 @@ namespace dynamicgraph { namespace sot { { public: static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } public: /* --- CONSTRUCTION --- */ diff --git a/include/sot-dynamic/waist-attitude-from-sensor.h b/include/sot-dynamic/waist-attitude-from-sensor.h index 2a74e30dd7071a40fa091a3f414581076cf77f09..ee96d97a125648d6ec6fd3f83b202f2129af7ede 100644 --- a/include/sot-dynamic/waist-attitude-from-sensor.h +++ b/include/sot-dynamic/waist-attitude-from-sensor.h @@ -66,6 +66,7 @@ class SOTWAISTATTITUDEFROMSENSOR_EXPORT WaistAttitudeFromSensor { public: static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } public: /* --- CONSTRUCTION --- */ diff --git a/include/sot-dynamic/zmpreffromcom.h b/include/sot-dynamic/zmpreffromcom.h index 2f75df546b4c2a9a343bdb1f27a266206a8d88c2..58e78e4aec7d0154f4504dd18787b6a1a491cbaa 100644 --- a/include/sot-dynamic/zmpreffromcom.h +++ b/include/sot-dynamic/zmpreffromcom.h @@ -64,6 +64,8 @@ class SOTZMPREFFROMCOM_EXPORT ZmprefFromCom { public: static const std::string CLASS_NAME; + virtual const std::string& getClassName( void ) const { return CLASS_NAME; } + public: double dt; const static double DT_DEFAULT; // = 5e-3; // 5ms double footHeight; diff --git a/src/dynamic_graph/sot/dynamics/hrp2.py.in b/src/dynamic_graph/sot/dynamics/hrp2.py.in index 1a71185624e585728632dda618947c4af1f7662d..93e8ed2c5200fbd062060c343ddb4c597b90efe0 100755 --- a/src/dynamic_graph/sot/dynamics/hrp2.py.in +++ b/src/dynamic_graph/sot/dynamics/hrp2.py.in @@ -22,6 +22,7 @@ from dynamic_graph import enableTrace, plug from dynamic_graph.sot.se3 import R3, SO3, SE3 from dynamic_graph.sot.dynamics.dynamic_hrp2 import DynamicHrp2 +from dynamic_graph.sot.dynamics.dynamic_hrp2_10 import DynamicHrp2_10 from dynamic_graph.sot.dynamics.humanoid_robot import AbstractHumanoidRobot @@ -38,7 +39,7 @@ class Hrp2(AbstractHumanoidRobot): res = (config + 10*(0.,)) return res - def __init__(self, name, modelDir, xmlDir, device): + def __init__(self, name, modelDir, xmlDir, device, dynamicType): AbstractHumanoidRobot.__init__ (self, name) self.OperationalPoints.append('waist') @@ -47,10 +48,14 @@ class Hrp2(AbstractHumanoidRobot): specificitiesPath = xmlDir + '/HRP2SpecificitiesSmall.xml' jointRankPath = xmlDir + '/HRP2LinkJointRankSmall.xml' - self.dynamic = DynamicHrp2(self.name + '_dynamic') - self.dynamic.setFiles(modelDir, modelName, - specificitiesPath, jointRankPath) - self.dynamic.parse() + self.dynamic = self.loadModelFromJrlDynamics( + self.name + '_dynamic', + modelDir, + modelName, + specificitiesPath, + jointRankPath, + dynamicType) + self.dimension = self.dynamic.getDimension() if self.dimension != len(self.halfSitting): raise RuntimeError("invalid half-sitting pose") @@ -80,7 +85,7 @@ class Hrp2Jrl (Hrp2): modelDir = hrp2_10_pkgdatarootdir, xmlDir = hrp2_10_pkgdatarootdir, device = None): - Hrp2.__init__(self, name, modelDir, xmlDir, device) + Hrp2.__init__(self, name, modelDir, xmlDir, device, DynamicHrp2_10) class Hrp2Laas (Hrp2): """ @@ -106,4 +111,4 @@ class Hrp2Laas (Hrp2): modelDir = hrp2_14_pkgdatarootdir, xmlDir = hrp2_14_pkgdatarootdir, device = None): - Hrp2.__init__(self, name, modelDir, xmlDir, device) + Hrp2.__init__(self, name, modelDir, xmlDir, device, DynamicHrp2) diff --git a/src/dynamic_graph/sot/dynamics/humanoid_robot.py b/src/dynamic_graph/sot/dynamics/humanoid_robot.py index 03c376d26c81d960678809a9a202fb6e7ca926b3..05634fe8d9b0deab749ec6759307f5e7a030e2a4 100755 --- a/src/dynamic_graph/sot/dynamics/humanoid_robot.py +++ b/src/dynamic_graph/sot/dynamics/humanoid_robot.py @@ -124,7 +124,8 @@ class AbstractHumanoidRobot (object): return model def loadModelFromJrlDynamics(self, name, modelDir, modelName, - specificitiesPath, jointRankPath): + specificitiesPath, jointRankPath, + dynamicType): """ Load a model using the jrl-dynamics parser. This parser looks for VRML files in which kinematics and dynamics information @@ -134,12 +135,11 @@ class AbstractHumanoidRobot (object): Additional information are located in two different XML files. """ - #FIXME: add support for hrp2-10 here. - model = DynamicHrp2(name) + model = dynamicType(name) model.setFiles(modelDir, modelName, specificitiesPath, jointRankPath) model.parse() - return + return model def initializeOpPoints(self, model): for op in self.OperationalPoints: @@ -212,6 +212,28 @@ class AbstractHumanoidRobot (object): def __init__(self, name): self.name = name + def reset(self, posture = None): + """ + Restart the control from another position. + + This method has not been extensively tested and + should be used carefully. + + In particular, tasks should be removed from the + solver before attempting a reset. + """ + if not posture: + posture = self.halfSitting + self.device.set(posture) + + self.dynamic.com.recompute(self.device.state.time+1) + self.dynamic.Jcom.recompute(self.device.state.time+1) + self.featureComDes.errorIN.value = self.dynamic.com.value + + for op in self.OperationalPoints: + self.dynamic.signal(op).recompute(self.device.state.time+1) + self.dynamic.signal('J'+op).recompute(self.device.state.time+1) + self.features[op].reference.value = self.dynamic.signal(op).value class HumanoidRobot(AbstractHumanoidRobot): diff --git a/src/dynamic_graph/sot/dynamics/solver.py b/src/dynamic_graph/sot/dynamics/solver.py index 51b27b183d464277cf2884b8dabc742cb4c0abd7..1be5988b798546111fbaa6c5d8da98ad521cb95b 100644 --- a/src/dynamic_graph/sot/dynamics/solver.py +++ b/src/dynamic_graph/sot/dynamics/solver.py @@ -16,7 +16,7 @@ # dynamic-graph. If not, see <http://www.gnu.org/licenses/>. from dynamic_graph import plug -from dynamic_graph.sot.core import SOT +from dynamic_graph.sot.core import JointLimitator, SOT class Solver: robot = None @@ -24,14 +24,28 @@ class Solver: def __init__(self, robot): self.robot = robot + + # Make sure control does not exceed joint limits. + self.jointLimitator = JointLimitator('joint_limitator') + plug(self.robot.dynamic.position, self.jointLimitator.joint) + plug(self.robot.dynamic.upperJl, self.jointLimitator.upperJl) + plug(self.robot.dynamic.lowerJl, self.jointLimitator.lowerJl) + + # Create the solver. self.sot = SOT('solver') self.sot.signal('damping').value = 1e-6 self.sot.setNumberDofs(self.robot.dimension) + # Plug the solver control into the filter. + plug(self.sot.control, self.jointLimitator.controlIN) + + # Important: always use 'jointLimitator.control' + # and NOT 'sot.control'! + if robot.device: - plug(self.sot.signal('control'), robot.device.signal('control')) - plug(self.robot.device.state, - self.robot.dynamic.position) + plug(self.jointLimitator.control, robot.device.control) + plug(self.robot.device.state, self.robot.dynamic.position) + def push(self, taskName): """ Proxy method to push a task in the sot diff --git a/src/dynamic_graph/sot/dynamics/tools.py b/src/dynamic_graph/sot/dynamics/tools.py index 5b1f80c9aa131296d762357962d2e7ef83f29960..b4e670bec200bf23236b9686d11da43449ae8d99 100755 --- a/src/dynamic_graph/sot/dynamics/tools.py +++ b/src/dynamic_graph/sot/dynamics/tools.py @@ -151,6 +151,9 @@ if 'argv' in sys.__dict__: parser.add_option("-d", "--display", action="store_true", dest="display", default=False, help="enable display using robotviewer") + parser.add_option("-r", "--robot", + action="store", dest="robot", default="Hrp2Laas", + help="Specify which robot model to use") (options, args) = parser.parse_args() if options.display: @@ -162,6 +165,13 @@ if 'argv' in sys.__dict__: # Initialize the stack of tasks. - robot = Hrp2Laas("robot") + robots = { + "Hrp2Laas" : Hrp2Laas, + "Hrp2Jrl" : Hrp2Jrl + } + if not options.robot in robots: + raise RuntimeError ( + "invalid robot name (should by Hrp2Laas or Hrp2Jrl)") + robot = robots[options.robot]("robot") timeStep = .005 solver = Solver(robot) diff --git a/unitTesting/python/dynamic_walk.py b/unitTesting/python/dynamic_walk.py index 7b36e463a5d210b8efd83cfe1a944da75176d477..23699b17e16be0923a936717643729ae6faa97b3 100755 --- a/unitTesting/python/dynamic_walk.py +++ b/unitTesting/python/dynamic_walk.py @@ -24,8 +24,7 @@ from dynamic_graph.sot.dynamics.hrp2 import Hrp2 from dynamic_graph import enableTrace, plug -from tools import * - +from dynamic_graph.sot.dynamics.tools import * class HalfStep: startX = 0. diff --git a/unitTesting/python/feet_follower.py b/unitTesting/python/feet_follower.py index 043179d7160ddf257bd08f8fd01af8f10071eb0b..1576e439103ae95954ee4d9f29536ea8b2a3e279 100755 --- a/unitTesting/python/feet_follower.py +++ b/unitTesting/python/feet_follower.py @@ -15,7 +15,7 @@ # received a copy of the GNU Lesser General Public License along with # dynamic-graph. If not, see <http://www.gnu.org/licenses/>. -from tools import * +from dynamic_graph.sot.dynamics.tools import * from dynamic_graph.sot.dynamics.feet_follower import FeetFollowerFromFile feetFollower = FeetFollowerFromFile('feet-follower') diff --git a/unitTesting/python/quasistatic_walking.py b/unitTesting/python/quasistatic_walking.py index e3608d4576cf60093e5301eb49cfa672b1321b4b..3de2bc0e4f003cd8626be8cf1a26d63aec18780d 100755 --- a/unitTesting/python/quasistatic_walking.py +++ b/unitTesting/python/quasistatic_walking.py @@ -21,8 +21,7 @@ from dynamic_graph.sot.dynamics.hrp2 import Hrp2 from dynamic_graph import enableTrace, plug -from tools import * - +from dynamic_graph.sot.dynamics.tools import * class QuasiStaticWalking: leftFoot = 0 @@ -155,13 +154,12 @@ class QuasiStaticWalking: # Push tasks # Feet tasks. -solver.sot.push(robot.name + '.task.right-ankle') -solver.sot.push(robot.name + '.task.left-ankle') +solver.sot.push(robot.tasks['right-ankle'].name) +solver.sot.push(robot.tasks['left-ankle'].name) # Center of mass # FIXME: trigger segv at exit. -solver.sot.push(robot.name + '.task.com') - +solver.sot.push(robot.comTask.name) # Main. diff --git a/unitTesting/python/reach_both_hands.py b/unitTesting/python/reach_both_hands.py index 9658c8d6473096541d3559e8df957c6cd892d6c4..ab853dc52f0f4aed7927affe4c16e08e437c4b0a 100755 --- a/unitTesting/python/reach_both_hands.py +++ b/unitTesting/python/reach_both_hands.py @@ -16,7 +16,7 @@ # dynamic-graph. If not, see <http://www.gnu.org/licenses/>. import sys -from tools import * +from dynamic_graph.sot.dynamics.tools import * # Move left wrist reach(robot, 'left-wrist', 0.25, 0.25, 0.5) @@ -24,13 +24,13 @@ reach(robot, 'right-wrist', 0.25, -0.25, 0.5) # Push tasks # Operational points tasks -solver.sot.push(robot.name + '.task.right-ankle') -solver.sot.push(robot.name + '.task.left-ankle') -solver.sot.push(robot.name + '.task.left-wrist') -solver.sot.push(robot.name + '.task.right-wrist') +solver.sot.push(robot.tasks['right-ankle'].name) +solver.sot.push(robot.tasks['left-ankle'].name) +solver.sot.push(robot.tasks['right-wrist'].name) +solver.sot.push(robot.tasks['left-wrist'].name) # Center of mass -solver.sot.push(robot.name + '.task.com') +solver.sot.push(robot.comTask.name) # Main. # Main loop diff --git a/unitTesting/python/reach_left_hand.py b/unitTesting/python/reach_left_hand.py index 941024745059cf6901a9e0f46d749cf38fec355c..bbb8e0e35613e2347cd98a39f7227a7ffd0bf099 100755 --- a/unitTesting/python/reach_left_hand.py +++ b/unitTesting/python/reach_left_hand.py @@ -16,20 +16,20 @@ # dynamic-graph. If not, see <http://www.gnu.org/licenses/>. import sys -from tools import * +from dynamic_graph.sot.dynamics.tools import * # Move left wrist reach(robot, 'left-wrist', 0.25, 0, 0.1) # Push tasks # Operational points tasks -solver.sot.push(robot.name + '.task.right-ankle') -solver.sot.push(robot.name + '.task.left-ankle') -solver.sot.push(robot.name + '.task.left-wrist') -solver.sot.push(robot.name + '.task.right-wrist') +solver.sot.push(robot.tasks['right-ankle'].name) +solver.sot.push(robot.tasks['left-ankle'].name) +solver.sot.push(robot.tasks['right-wrist'].name) +solver.sot.push(robot.tasks['left-wrist'].name) # Center of mass -solver.sot.push(robot.name + '.task.com') +solver.sot.push(robot.comTask.name) # Main. # Main loop diff --git a/unitTesting/python/reach_right_hand.py b/unitTesting/python/reach_right_hand.py index 834cef6d4f2d72f0e224b093a10a0588b2ec5c73..e6fb07f7ec9ae07514be505b1543e7e39e72556c 100755 --- a/unitTesting/python/reach_right_hand.py +++ b/unitTesting/python/reach_right_hand.py @@ -15,20 +15,20 @@ # received a copy of the GNU Lesser General Public License along with # dynamic-graph. If not, see <http://www.gnu.org/licenses/>. -from tools import * +from dynamic_graph.sot.dynamics.tools import * # Move right wrist reach(robot, 'right-wrist', 0.25, 0, 0.1) # Push tasks # Operational points tasks -solver.sot.push(robot.name + '.task.right-ankle') -solver.sot.push(robot.name + '.task.left-ankle') -solver.sot.push(robot.name + '.task.left-wrist') -solver.sot.push(robot.name + '.task.right-wrist') +solver.sot.push(robot.tasks['right-ankle'].name) +solver.sot.push(robot.tasks['left-ankle'].name) +solver.sot.push(robot.tasks['right-wrist'].name) +solver.sot.push(robot.tasks['left-wrist'].name) # Center of mass -solver.sot.push(robot.name + '.task.com') +solver.sot.push(robot.comTask.name) # Main. # Main loop