diff --git a/src/dynamic_graph/sot/dynamics/hrp2.py.in b/src/dynamic_graph/sot/dynamics/hrp2.py.in index be7e7d23f26e112d211b77e6136fb3c4b1a45bcc..6398a5d71f3c375dde2fcf3ddfbfec79fca770e3 100755 --- a/src/dynamic_graph/sot/dynamics/hrp2.py.in +++ b/src/dynamic_graph/sot/dynamics/hrp2.py.in @@ -48,8 +48,9 @@ class Hrp2(AbstractHumanoidRobot): res = (config + 10*(0.,)) return res - def __init__(self, name, modelDir, xmlDir, device, dynamicType): - AbstractHumanoidRobot.__init__ (self, name) + def __init__(self, name, modelDir, xmlDir, device, dynamicType, + tracer = None): + AbstractHumanoidRobot.__init__ (self, name, tracer) self.OperationalPoints.append('waist') self.device = device @@ -93,8 +94,10 @@ class Hrp2Jrl (Hrp2): def __init__(self, name, modelDir = hrp2_10_pkgdatarootdir, xmlDir = hrp2_10_pkgdatarootdir, - device = None): - Hrp2.__init__(self, name, modelDir, xmlDir, device, DynamicHrp2_10) + device = None, + tracer = None): + Hrp2.__init__(self, name, modelDir, xmlDir, device, DynamicHrp2_10, + tracer) class Hrp2Laas (Hrp2): """ @@ -119,7 +122,8 @@ class Hrp2Laas (Hrp2): def __init__(self, name, modelDir = hrp2_14_pkgdatarootdir, xmlDir = hrp2_14_pkgdatarootdir, - device = None): + device = None, + tracer = None): # Define camera positions w.r.t gaze. @@ -165,14 +169,18 @@ class Hrp2Laas (Hrp2): camera = camera * c1_M_c self.AdditionalFrames.append( - ("cameraBottomLeft", matrixToTuple(cameraBottomLeftPosition), "gaze")) + ("cameraBottomLeft", + matrixToTuple(cameraBottomLeftPosition), "gaze")) self.AdditionalFrames.append( - ("cameraBottomRight", matrixToTuple(cameraBottomRightPosition), "gaze")) + ("cameraBottomRight", + matrixToTuple(cameraBottomRightPosition), "gaze")) self.AdditionalFrames.append( - ("cameraTopLeft", matrixToTuple(cameraTopLeftPosition), "gaze")) + ("cameraTopLeft", + matrixToTuple(cameraTopLeftPosition), "gaze")) self.AdditionalFrames.append( - ("cameraTopRight", matrixToTuple(cameraTopRightPosition), "gaze")) + ("cameraTopRight", + matrixToTuple(cameraTopRightPosition), "gaze")) - Hrp2.__init__(self, name, modelDir, xmlDir, device, DynamicHrp2) + Hrp2.__init__(self, name, modelDir, xmlDir, device, DynamicHrp2, tracer) __all__ = [Hrp2, Hrp2Jrl, Hrp2Laas] diff --git a/src/dynamic_graph/sot/dynamics/humanoid_robot.py b/src/dynamic_graph/sot/dynamics/humanoid_robot.py index e87c14cfa472b5edef4864e869b66f725c92f6b7..59e84a231578354101476f7c6df44dac0cac1a89 100755 --- a/src/dynamic_graph/sot/dynamics/humanoid_robot.py +++ b/src/dynamic_graph/sot/dynamics/humanoid_robot.py @@ -14,6 +14,10 @@ # received a copy of the GNU Lesser General Public License along with # dynamic-graph. If not, see <http://www.gnu.org/licenses/>. +from __future__ import print_function + +from dynamic_graph.tracer_real_time import TracerRealTime +from dynamic_graph.tools import addTrace from dynamic_graph.sot import SE3, R3, SO3 from dynamic_graph.sot.core import OpPointModifier from dynamic_graph.sot.core.derivator import Derivator_of_Vector @@ -136,6 +140,37 @@ class AbstractHumanoidRobot (object): """ enableZmpComputation = False + """ + Tracer used to log data. + """ + tracer = None + + """ + How much data will be logged. + """ + tracerSize = 2**20 + + """ + Automatically recomputed signals through the use + of device.after. + This list is maintained in order to clean the + signal list device.after before exiting. + """ + autoRecomputedSignals = [] + + """ + Which signals should be traced. + """ + tracedSignals = { + 'dynamic': ["com", "zmp", "angularmomentum", + "position", "velocity", "acceleration"], + 'device': ['zmp', 'control', 'state'] + } + + """ + Robot timestep + """ + timeStep = 0.005 def loadModelFromKxml(self, name, filename): """ @@ -173,7 +208,7 @@ class AbstractHumanoidRobot (object): return model def setProperties(self, model): - model.setProperty('TimeStep', '0.005') + model.setProperty('TimeStep', str(self.timeStep)) model.setProperty('ComputeAcceleration', 'false') model.setProperty('ComputeAccelerationCoM', 'false') @@ -223,7 +258,7 @@ class AbstractHumanoidRobot (object): if self.enableVelocityDerivator: self.velocityDerivator = Derivator_of_Vector('velocityDerivator') - self.velocityDerivator.dt.value = 0.005 + self.velocityDerivator.dt.value = self.timeStep plug(self.device.state, self.velocityDerivator.sin) plug(self.velocityDerivator.sout, self.dynamic.velocity) else: @@ -232,7 +267,7 @@ class AbstractHumanoidRobot (object): if self.enableAccelerationDerivator: self.accelerationDerivator = \ Derivator_of_Vector('accelerationDerivator') - self.accelerationDerivator.dt.value = 0.005 + self.accelerationDerivator.dt.value = self.timeStep plug(self.velocityDerivator.sout, self.accelerationDerivator.sin) plug(self.accelerationDerivator.sout, self.dynamic.acceleration) @@ -294,10 +329,83 @@ class AbstractHumanoidRobot (object): self.frames[frameName].jacobian.recompute( self.frames[frameName].jacobian.time + 1) + # Initialize tracer. + self.initializeTracer() + + def addTrace(self, entityName, signalName): + self.autoRecomputedSignals.append( + '{0}.{1}'.format(entityName, signalName)) + addTrace(self, self.tracer, entityName, signalName) + + def initializeTracer(self): + if not self.tracer: + self.tracer = TracerRealTime('trace') + self.tracer.setBufferSize(self.tracerSize) + self.tracer.open('/tmp/','dg_','.dat') + # Recompute trace.triger at each iteration to enable tracing. + self.device.after.addSignal('{0}.triger'.format(self.tracer.name)) + + # Geometry / operational points + for s in self.OperationalPoints + self.tracedSignals['dynamic']: + self.addTrace(self.dynamic.name, s) + + # Geometry / frames + for (frameName, _, _) in self.AdditionalFrames: + for s in ['position', 'jacobian']: + self.addTrace(self.frames[frameName].name, s) + + # Robot features + for s in self.OperationalPoints: + self.addTrace(self.features[s]._reference.name, 'position') + self.addTrace(self.tasks[s].name, 'error') + + # Com + self.addTrace(self.featureComDes.name, 'errorIN') + self.addTrace(self.comTask.name, 'error') + + # Device + for s in self.tracedSignals['device']: + self.addTrace(self.device.name, s) + if type(self.device) != RobotSimu: + self.addTrace(self.device.name, 'robotState') + + # Misc + if self.enableVelocityDerivator: + self.addTrace(self.velocityDerivator.name, 'sout') + if self.enableAccelerationDerivator: + self.addTrace(self.accelerationDerivator.name, 'sout') - def __init__(self, name): + + def __init__(self, name, tracer = None): self.name = name + # Initialize tracer if necessary. + if tracer: + self.tracer = tracer + + def __del__(self): + if self.tracer: + self.stopTracer() + + def startTracer(self): + """ + Start the tracer if it does not already been stopped. + """ + if self.tracer: + self.tracer.start() + + def stopTracer(self): + """ + Stop and destroy tracer. + """ + self.tracer.dump() + self.tracer.stop() + self.tracer.close() + self.tracer.clear() + for s in self.autoRecomputedSignals: + self.device.after.rmSignal(s) + self.tracer = None + def reset(self, posture = None): """ Restart the control from another position. @@ -328,8 +436,8 @@ class HumanoidRobot(AbstractHumanoidRobot): name = None filename = None - def __init__(self, name, filename): - AbstractHumanoidRobot.__init__(self, name) + def __init__(self, name, filename, tracer = None): + AbstractHumanoidRobot.__init__(self, name, tracer) self.filename = filename self.dynamic = \ self.loadModelFromKxml (self.name + '_dynamics', self.filename)