diff --git a/python/walktrans.py b/python/walktrans.py new file mode 100644 index 0000000000000000000000000000000000000000..5feabf8691240fb3ab6822bf17088fafca0a1a7c --- /dev/null +++ b/python/walktrans.py @@ -0,0 +1,347 @@ +from dynamic_graph import plug +from dynamic_graph.sot.core import * +from dynamic_graph.sot.core.math_small_entities import Derivator_of_Matrix +from dynamic_graph.sot.dynamics import * +import dynamic_graph.script_shortcuts +from dynamic_graph.script_shortcuts import optionalparentheses +from dynamic_graph.matlab import matlab +from dynamic_graph.sot.core.meta_task_6d import MetaTask6d,toFlags +from numpy import * +from matrix_util import matrixToTuple, vectorToTuple,rotate, matrixToRPY, RPYToMatrix +from history import History +from zmp_estimator import ZmpEstimator +from viewer_helper import addRobotViewer,VisualPinger +from attime import attime + +from robotSpecific import pkgDataRootDir,modelName,robotDimension,initialConfig,gearRatio,inertiaRotor +robotName = 'hrp14small' + +initialConfig.clear() +initialConfig['hrp14small'] = (0,0,0.648697398115,0,0,0)+(0, 0, -0.4538, 0.8727, -0.4189, 0, 0, 0, -0.4538, 0.8727, -0.4189, 0, 0, 0, 0, 0, 0.2618, -0.1745, 0, -0.5236, 0, 0, 0.17453, 0.2618, 0.1745, 0, -0.5236, 0, 0, 0.17453 ) + +finalConfig = (0,0,0.648697398115,0,0,0)+(-0.00028574496353194379, 0.003829437078692717, -0.64798319907006197, 1.0552418879543297, -0.44497846451811773, -0.0038397195926406333, -0.00028578259876648154, 0.00382843982057902, -0.64712828870988759, 1.053420252598515, -0.44401173937761496, -0.0038387216246142633, 0.00014352031102940873, 0.013151503268542629, -0.00057411504064778878, -0.050871000025830684, 0.21782780288468376, -0.37965640592660427, -0.14072647716205641, -1.1942332339535875, 0.0055454863752303456, -0.66956710808063102, 0.17479818266043898, 0.21400703176401134, 0.38370527720074465, 0.14620204468511225, -1.1873407322936731, -0.0038746980026916284, -0.6643017236637716, 0.17500428384102076) + +qf=array(finalConfig) +qf[6]-=1 +finalConfig = tuple(qf.tolist()) + +# --- ROBOT SIMU --------------------------------------------------------------- + +robotDim=robotDimension[robotName] +robot = RobotSimu("robot") +robot.resize(robotDim) +addRobotViewer(robot,small=True,verbose=False) + +robot.set( initialConfig[robotName] ) +dt=5e-3 + +# --- MAIN LOOP ------------------------------------------ +def inc(): + robot.increment(dt) + attime.run(robot.control.time) + #robot.viewer.updateElementConfig('zmp',[zmp.zmp.value[0],zmp.zmp.value[1],0,0,0,0]) + if dyn.com.time >0: + robot.viewer.updateElementConfig('com',[dyn.com.value[0],dyn.com.value[1],0,0,0,0]) + +from ThreadInterruptibleLoop import * +@loopInThread +def loop(): + inc() +runner=loop() + +@optionalparentheses +def go(): runner.play() +@optionalparentheses +def stop(): runner.pause() +@optionalparentheses +def next(): inc() #runner.once() + +# --- shortcuts ------------------------------------------------- +@optionalparentheses +def n(): + inc() + qdot() +@optionalparentheses +def n5(): + for loopIdx in range(5): inc() +@optionalparentheses +def n10(): + for loopIdx in range(10): inc() +@optionalparentheses +def q(): + if 'dyn' in globals(): print dyn.ffposition.__repr__() + print robot.state.__repr__() +@optionalparentheses +def qdot(): print robot.control.__repr__() +@optionalparentheses +def t(): print robot.state.time-1 +@optionalparentheses +def iter(): print 'iter = ',robot.state.time +@optionalparentheses +def status(): print runner.isPlay + +# --- DYN ---------------------------------------------------------------------- +modelDir = pkgDataRootDir[robotName] +xmlDir = pkgDataRootDir[robotName] +specificitiesPath = xmlDir + '/HRP2SpecificitiesSmall.xml' +jointRankPath = xmlDir + '/HRP2LinkJointRankSmall.xml' + +dyn = Dynamic("dyn") +dyn.setFiles(modelDir, modelName[robotName],specificitiesPath,jointRankPath) +dyn.parse() + +dyn.inertiaRotor.value = inertiaRotor[robotName] +dyn.gearRatio.value = gearRatio[robotName] + +plug(robot.state,dyn.position) +dyn.velocity.value = robotDim*(0.,) +dyn.acceleration.value = robotDim*(0.,) + +dyn.ffposition.unplug() +dyn.ffvelocity.unplug() +dyn.ffacceleration.unplug() +robot.control.unplug() + +# --- PG --------------------------------------------------------- +from dynamic_graph.sot.pattern_generator import PatternGenerator,Selector + +pg = PatternGenerator('pg') +pg.setVrmlDir(modelDir+'/') +pg.setVrml(modelName[robotName]) +pg.setXmlSpec(specificitiesPath) +pg.setXmlRank(jointRankPath) +pg.buildModel() + +# Standard initialization +pg.parseCmd(":samplingperiod 0.005") +pg.parseCmd(":previewcontroltime 1.6") +pg.parseCmd(":comheight 0.814") +pg.parseCmd(":omega 0.0") +pg.parseCmd(":stepheight 0.05") +pg.parseCmd(":singlesupporttime 0.780") +pg.parseCmd(":doublesupporttime 0.020") +pg.parseCmd(":armparameters 0.5") +pg.parseCmd(":LimitsFeasibility 0.0") +pg.parseCmd(":ZMPShiftParameters 0.015 0.015 0.015 0.015") +pg.parseCmd(":TimeDistributeParameters 2.0 3.5 1.0 3.0") +pg.parseCmd(":UpperBodyMotionParameters 0.0 -0.5 0.0") +pg.parseCmd(":comheight 0.814") +pg.parseCmd(":SetAlgoForZmpTrajectory Morisawa") + +plug(dyn.position,pg.position) +plug(dyn.com,pg.com) +pg.motorcontrol.value = robotDim*(0,) +pg.zmppreviouscontroller.value = (0,0,0) + +pg.initState() + +# --- PG INIT FRAMES --- +geom = Dynamic("geom") +geom.setFiles(modelDir, modelName[robotName],specificitiesPath,jointRankPath) +geom.parse() +geom.createOpPoint('rf','right-ankle') +geom.createOpPoint('lf','left-ankle') +plug(dyn.position,geom.position) +geom.ffposition.value = 6*(0,) +geom.velocity.value = robotDim*(0,) +geom.acceleration.value = robotDim*(0,) + +# --- Selector of Com Ref: when pg is stopped, pg.inprocess becomes 0 +comRef = Selector('comRef' + ,['vector','ref',dyn.com,pg.comref]) +plug(pg.inprocess,comRef.selec) + +selecSupportFoot = Selector('selecSupportFoot' + ,['matrixHomo','pg_H_sf',pg.rightfootref,pg.leftfootref] + ,['matrixHomo','wa_H_sf',geom.rf,geom.lf] + ) +plug(pg.SupportFoot,selecSupportFoot.selec) +sf_H_wa = Inverse_of_matrixHomo('sf_H_wa') +plug(selecSupportFoot.wa_H_sf,sf_H_wa.sin) +pg_H_wa = Multiply_of_matrixHomo('pg_H_wa') +plug(selecSupportFoot.pg_H_sf,pg_H_wa.sin1) +plug(sf_H_wa.sout,pg_H_wa.sin2) + +# --- Compute the ZMP ref in the Waist reference frame. +wa_H_pg = Inverse_of_matrixHomo('wa_H_pg') +plug(pg_H_wa.sout,wa_H_pg.sin) +wa_zmp = Multiply_matrixHomo_vector('wa_zmp') +plug(wa_H_pg.sout,wa_zmp.sin1) +plug(pg.zmpref,wa_zmp.sin2) +# Connect the ZMPref to OpenHRP in the waist reference frame. +pg.parseCmd(':SetZMPFrame world') +plug(wa_zmp.sout,robot.zmp) + +# ---- TASKS ------------------------------------------------------------------- + +# ---- WAIST TASK --- +taskWaist=MetaTask6d('waist',dyn,'waist','waist') + +# Build the reference waist pos homo-matrix from PG. +waistReferenceVector = Stack_of_vector('waistReferenceVector') +plug(pg.initwaistposref,waistReferenceVector.sin1) +plug(pg.initwaistattref,waistReferenceVector.sin2) +waistReferenceVector.selec1(0,3) +waistReferenceVector.selec2(0,3) +waistReference=PoseRollPitchYawToMatrixHomo('waistReference') +plug(waistReferenceVector.sout,waistReference.sin) +plug(waistReference.sout,taskWaist.featureDes.position) + +taskWaist.feature.selec.value = '011100' +taskWaist.task.controlGain.value = 5 + +# --- TASK COM --- +featureCom = FeatureGeneric('featureCom') +plug(dyn.com,featureCom.errorIN) +plug(dyn.Jcom,featureCom.jacobianIN) +featureComDes = FeatureGeneric('featureComDes') +featureCom.sdes.value = 'featureComDes' +plug(comRef.ref,featureComDes.errorIN) +featureCom.selec.value = '011' +taskCom = Task('taskCom') +taskCom.add('featureCom') +taskCom.controlGain.value = 40 + +# --- TASK POSTURE --- +featurePosture = FeatureGeneric('featurePosture') +plug(dyn.position,featurePosture.errorIN) +featurePosture.jacobianIN.value = matrixToTuple(eye(robotDim)) +featurePostureDes = FeatureGeneric('featurePostureDes') +featurePosture.sdes.value = 'featurePostureDes' +featurePostureDes.errorIN.value = finalConfig + +gainPosture = GainAdaptive('gainPosture') +gainPosture.setByPoint(10,0.1,0.1,0.8) + +taskPosture = Task('taskPosture') +taskPosture.add('featurePosture') +plug(taskPosture.error,gainPosture.error) +plug(gainPosture.gain,taskPosture.controlGain) + +# --- TASK RIGHT FOOT +# Task right hand +taskRF=MetaTask6d('rf',dyn,'rf','right-ankle') +taskLF=MetaTask6d('lf',dyn,'lf','left-ankle') + +plug(pg.rightfootref,taskRF.featureDes.position) +taskRF.task.controlGain.value = 5 +plug(pg.leftfootref,taskLF.featureDes.position) +taskLF.task.controlGain.value = 5 + +# ---- SOT --------------------------------------------------------------------- +# The solver SOTH of dyninv is used, but normally, the SOT solver should be sufficient +from dynamic_graph.sot.dyninv import SolverKine +sot = SolverKine('sot') +sot.setSize(robotDim) +#sot.push(taskWaist.task.name) +sot.push(taskRF.task.name) +sot.push(taskLF.task.name) +sot.push(taskCom.name) + +plug(sot.control,robot.control) + + + + +# --- TRACER ----------------------------------------------------------------- +from dynamic_graph.tracer import * +from dynamic_graph.tracer_real_time import * +tr = Tracer('tr') +tr.open('/tmp/','','.dat') +tr.start() +robot.after.addSignal('tr.triger') + +#tr.add(dyn.name+'.ffposition','ff') +tr.add(taskRF.featureDes.name+'.position','refr') +tr.add(taskLF.featureDes.name+'.position','refl') + + +# --- DYN ---------------------------------------------------------------------- +inv=linalg.inv + +q={}; geom={}; rf={}; lf={}; + +q[0] = initialConfig[robotName] +q[1] = finalConfig +for i in range(2): + geom[i] = Dynamic("geom"+str(i)) + geom[i].setFiles(modelDir, modelName[robotName],specificitiesPath,jointRankPath) + geom[i].parse() + geom[i].position.value = q[i] + geom[i].velocity.value = robotDim*(0.,) + geom[i].acceleration.value = robotDim*(0.,) + geom[i].createPosition('rf','right-ankle') + geom[i].createPosition('lf','left-ankle') + geom[i].rf.recompute(0) + geom[i].lf.recompute(0) + rf[i]= array(geom[i].rf.value) + lf[i]= array(geom[i].lf.value) + + + +aMm0 = eye(4); aMm0[0:2,3] = (rf[0][0:2,3]+lf[0][0:2,3])/2 +bMm1 = eye(4); bMm1[0:2,3] = (rf[1][0:2,3]+lf[1][0:2,3])/2 +wMa = inv(aMm0) +wMm1 = eye(4); wMm1[0,3]=0.2 +wMb = dot(wMm1,inv(bMm1)) + +wMr0 = dot( wMa, rf[0] ) +wMl0 = dot( wMa, lf[0] ) +wMr1 = dot( wMb, rf[1] ) +wMl1 = dot( wMb, lf[1] ) + +if abs(wMr0[2,2]-1)>1e-3 or abs(wMl0[2,2]-1)>1e-3 or abs(wMr1[2,2]-1)>1e-3 or abs(wMl1[2,2]-1)>1e-3 : + print 'Error: the feet ' + +step1 = ( dot(wMa,lf[0]) )[0:2,3] +step2 = ( dot( inv( dot(wMa,lf[0]) ), (dot( wMb,rf[1])) ) ) [0:2,3] +step3 = ( dot( inv(rf[1]), lf[1] ))[0:2,3] + +''' +seqpart = '' +for s in [step1,step2, step3]: + seqpart+= str(s[0])+' '+str(s[1])+' '+str(0)+' ' +pg.parseCmd(":stepseq " + seqpart) +''' + +rMl0 = dot( inv(rf[0]), lf[0] ) +rMl1 = dot( inv(rf[1]), lf[1] ) +if abs(rMl1[2,2]-1)>1e-3 or abs(rMl1[2,3])>1e-3: + print 'Error: the feet should be parallele on a same Z plane (final pose)' +if abs(rMl0[2,2]-1)>1e-3 or abs(rMl0[2,3])>1e-3: + print 'Error: the feet should be parallele on a same Z plane (initial pose)' + +a0 = arctan2(rMl0[1,0],rMl0[0,0])/2 +a1 = arctan2(rMl1[1,0],rMl1[0,0])/2 +t0 = rMl0[0:3,3] +t1 = rMl1[0:3,3] + +Ma0 = array(rotate('z',a0)) +Ma0[0:3,3] = t0/2 +Ma1 = array(rotate('z',a1)) +Ma1[0:3,3] = t1/2 + +wMa = inv(dot(Ma0,rf[0])) +wMb = inv(dot(Ma1,rf[1])) + +#robot.set( tuple(matrixToRPY( dot(wMa,RPYToMatrix(q[0][0:6])) ))+q[0][6:] ) +#robot.set( tuple(matrixToRPY( dot(wMb,RPYToMatrix(q[1][0:6])) ))+q[1][6:] ) + +step1 = ( dot(wMa,lf[0]) ) +step2 = ( dot( inv( dot(wMa,lf[0]) ), (dot( wMb,rf[1])) ) ) +step3 = ( dot( inv(rf[1]), lf[1] )) + +seqpart = '' +for s in [step1,step2, step3]: + seqpart+= str(s[0,3])+' '+str(s[1,3])+' '+str(arctan2(s[1,0],s[0,0])*180/pi)+' ' +pg.parseCmd(":stepseq " + seqpart) + + +# --- RUN ----------------------------------------------------------------- + +go() + + +featurePosture.selec.value = toFlags( range(6,36) ) +attime(300,lambda: sot.push(taskPosture.name),'Add Posture') +attime(500,lambda: sot.rm(taskCom.name),'rm com')