def gen_mul(a,b):
	"""Multiplies lists or scalars in a unified way.  With lists
	the multiplication is elementwise."""
	if isinstance(a,np.ndarray):
		return np.dot(a,b)
	elif hasattr(a,'__iter__'):
		return vectorops.mul(a,b)
	elif hasattr(b,'__iter__'):
		return vectorops.mul(b,a)
	return a*b
Example #2
0
def gen_mul(a, b):
    """Multiplies lists or scalars in a unified way.  With lists
	the multiplication is elementwise."""
    if isinstance(a, np.ndarray):
        return np.dot(a, b)
    elif hasattr(a, '__iter__'):
        return vectorops.mul(a, b)
    elif hasattr(b, '__iter__'):
        return vectorops.mul(b, a)
    return a * b
Example #3
0
 def process(self, inputs):
     if self.value == None or len(self.value) != len(inputs):
         self.value = inputs
     else:
         x = vectorops.mul(self.value, 1 - self.rate)
         self.value = vectorops.madd(x, inputs, self.rate)
     return self.value
Example #4
0
def spawn_item_in_world(item,world):
    """Given an ItemInBin instance, spawns a RigidObject in the Klamp't
    world with its same geometry / size / mass properties.
    Returns the new object."""
    obj = world.makeRigidObject(item.info.name)
    bmin,bmax = item.info.bmin,item.info.bmax
    center = vectorops.div(vectorops.add(bmin,bmax),2.0)
    m = obj.getMass()
    m.setMass(item.info.mass)
    m.setCom([0,0,0])
    m.setInertia(vectorops.mul([bmax[0]-bmin[0],bmax[1]-bmin[1],bmax[2]-bmin[2]],item.info.mass/12.0))
    obj.setMass(m)
    c = obj.getContactParameters()
    #TODO: make these parameters dynamic
    c.kFriction = 0.6
    c.kRestitution = 0.1;
    c.kStiffness = 100000
    c.kDamping = 100000
    obj.setContactParameters(c)
    simgeometry = obj.geometry()
    #either copy directly (this line)...
    simgeometry.set(item.info.geometry)
    #or reload from file (this line)
    #load_item_geometry(item.info,simgeometry)
    obj.setTransform(item.xform[0],item.xform[1])
    return obj
def scaleToBounds( val, bmin, bmax, origin=None):
	"""Cap the ray starting origin in the direction val against bounding box limits.
	"""
	if origin != None:
		if isinstance(bmin,np.ndarray):
			bmin -= origin
		else:
			bmin = vectorops.sub(bmin,origin)
		if isinstance(bmax,np.ndarray):
			bmax -= origin
		else:
			bmax = vectorops.sub(bmax,origin)
		return scaleToBounds(val,bmin,bmax)
	umax = 1.0
	for vali,ai,bi in zip(val,bmin,bmax):
		assert bi >= ai
		if vali < ai:
			umax = ai/vali
		if vali > bi:
			umax = bi/vali
	if umax==1.0: return val
	assert umax >= 0
	print "Scaling to velocity maximum, factor",umax
	if isinstance(val,np.ndarray):
		return val*umax
	else:
		return vectorops.mul(val,umax)
Example #6
0
 def putSensedObjectInWorld(self,item):
     #put this obejct in the world
     obj = self.world.makeRigidObject(item.info.name)
     bmin,bmax = item.info.bmin,item.info.bmax
     center = vectorops.div(vectorops.add(bmin,bmax),2.0)
     m = obj.getMass()
     m.setMass(item.info.mass)
     m.setCom([0,0,0])
     m.setInertia(vectorops.mul([bmax[0]-bmin[0],bmax[1]-bmin[1],bmax[2]-bmin[2]],item.info.mass/12.0))
     obj.setMass(m)
     c = obj.getContactParameters()
     c.kFriction = 0.6
     c.kRestitution = 0.1;
     c.kStiffness = 100000
     c.kDamping = 100000
     obj.setContactParameters(c)
     cube = obj.geometry()
     if not cube.loadFile(os.path.join(model_dir,"cube.tri")):
         print "Error loading cube file",os.path.join(model_dir,"cube.tri")
         exit(1)
     scale = [bmax[0]-bmin[0],0,0,0,bmax[1]-bmin[1],0,0,0,bmax[2]-bmin[2]]
     translate = vectorops.sub(bmin,center)
     cube.transform(scale,translate)
     mesh = cube.getTriangleMesh()
     obj.setTransform(item.xform[0],item.xform[1])
Example #7
0
def load_item_geometry(item,geometry_ptr = None):
    """Loads the geometry of the given item and returns it.  If geometry_ptr
    is provided, then it is assumed to be a Geometry3D object and the object
    geometry is loaded into it."""
    if geometry_ptr == None:
        geometry_ptr = Geometry3D()
    if item.info.geometryFile == None:
        return None
    elif item.info.geometryFile == 'box':
        fn = "../klampt_models/cube.tri"
        if not geometry_ptr.loadFile(fn):
            print "Error loading cube file",fn
            exit(1)
        bmin,bmax = item.info.bmin,item.info.bmax
        center = vectorops.mul(vectorops.add(bmin,bmax),0.5)
        scale = [bmax[0]-bmin[0],0,0,0,bmax[1]-bmin[1],0,0,0,bmax[2]-bmin[2]]
        translate = vectorops.sub(bmin,center)
        geometry_ptr.transform(scale,translate)
        geometry_ptr.setCurrentTransform(item.xform[0],item.xform[1])
        return geometry_ptr
    else:
        if not geometry_ptr.loadFile(item.info.geometryFile):
            print "Error loading geometry file",item.info.geometryFile
            exit(1)
        return geometry_ptr
	def printStatus(self,q):
		"""Prints a status printout summarizing all tasks' errors."""
		priorities = set()
		names = dict()
		errors = dict()
		totalerrors = dict()
		for t in self.taskList:
			if t.weight==0: continue
			priorities.add(t.level)
			s = t.name
			if len(s) > 8:
				s = s[0:8]
			err = t.getSensedError(q)
			names.setdefault(t.level,[]).append(s)
			errors.setdefault(t.level,[]).append("%.3f"%(vectorops.norm(err)),)
			werrsq = vectorops.normSquared(vectorops.mul(err,t.weight))
			totalerrors[t.level] = totalerrors.get(t.level,0.0) + werrsq
		cols = 5
		colwidth = 10
		for p in priorities:
			print "Priority",p,"weighted error^2",totalerrors[p]
			pnames = names[p]
			perrs = errors[p]
			start = 0
			while start < len(pnames):
				last = min(start+cols,len(pnames))
				print "  Name:  ",
				for i in range(start,last):
					print pnames[i],' '*(colwidth-len(pnames[i])),
				print
				print "  Error: ",
				for i in range(start,last):
					print perrs[i],' '*(colwidth-len(perrs[i])),
				print
				start=last
def spawn_objects(world):
    """For all ground_truth_items, spawns RigidObjects in the world
    according to their sizes / mass properties"""

    print "Initializing world objects"

    obj = world.makeRigidObject('object1')
    bmin = [0,0,0]
    bmax = [0.08,0.08,0.3]

    mass = 0.001
    m = obj.getMass()
    m.setMass(mass)
    m.setCom([0,0,0])
    m.setInertia(vectorops.mul([bmax[0]-bmin[0],bmax[1]-bmin[1],bmax[2]-bmin[2]],mass/12.0))
    obj.setMass(m)

    c = obj.getContactParameters()
    c.kFriction = 10
    c.kRestitution = 0.1;
    c.kStiffness = 100
    c.kDamping = 10
    obj.setContactParameters(c)

    load_item_geometry(bmin,bmax,obj.geometry())

    obj.setTransform(so3.identity(),[0,-0.2,0.155])
    obj.geometry().setCollisionMargin(0)

    return obj
Example #10
0
def spawn_objects_from_ground_truth(world):
    """For all ground_truth_items, spawns RigidObjects in the world
    according to their sizes / mass properties"""
    global ground_truth_items
    print "Initializing world objects"
    for item in ground_truth_items:
        obj = world.makeRigidObject(item.info.name)
        bmin,bmax = item.info.bmin,item.info.bmax
        center = vectorops.div(vectorops.add(bmin,bmax),2.0)
        m = obj.getMass()
        m.setMass(item.info.mass)
        m.setCom([0,0,0])
        m.setInertia(vectorops.mul([bmax[0]-bmin[0],bmax[1]-bmin[1],bmax[2]-bmin[2]],item.info.mass/12.0))
        obj.setMass(m)
        c = obj.getContactParameters()
        c.kFriction = 0.6
        c.kRestitution = 0.1;
        c.kStiffness = 100000
        c.kDamping = 100000
        obj.setContactParameters(c)
        cube = obj.geometry()
        if not cube.loadFile(os.path.join(model_dir,"cube.tri")):
            print "Error loading cube file",os.path.join(model_dir,"cube.tri")
            exit(1)
        scale = [bmax[0]-bmin[0],0,0,0,bmax[1]-bmin[1],0,0,0,bmax[2]-bmin[2]]
        translate = vectorops.sub(bmin,center)
        cube.transform(scale,translate)
        mesh = cube.getTriangleMesh()
        obj.setTransform(item.xform[0],item.xform[1])
    return
Example #11
0
	def printStatus(self,q):
		"""Prints a status printout summarizing all tasks' errors."""
		priorities = set()
		names = dict()
		errors = dict()
		totalerrors = dict()
		for t in self.taskList:
			if t.weight==0: continue
			priorities.add(t.level)
			s = t.name
			if len(s) > 8:
				s = s[0:8]
			err = t.getSensedError(q)
			names.setdefault(t.level,[]).append(s)
			errors.setdefault(t.level,[]).append("%.3f"%(vectorops.norm(err)),)
			werrsq = vectorops.normSquared(vectorops.mul(err,t.weight))
			totalerrors[t.level] = totalerrors.get(t.level,0.0) + werrsq
		cols = 5
		colwidth = 10
		for p in priorities:
			print "Priority",p,"weighted error^2",totalerrors[p]
			pnames = names[p]
			perrs = errors[p]
			start = 0
			while start < len(pnames):
				last = min(start+cols,len(pnames))
				print "  Name:  ",
				for i in range(start,last):
					print pnames[i],' '*(colwidth-len(pnames[i])),
				print
				print "  Error: ",
				for i in range(start,last):
					print perrs[i],' '*(colwidth-len(perrs[i])),
				print
				start=last
	def getCommandVelocity(self, q, dq, dt):
		"""Gets the command velocity from the current state of the
		robot.
		"""
		eP = self.getSensedError(q)
		#vcmd = hP*eP + hD*eV + hI*eI
		vP = gen_mul(self.hP,eP)
		vcmd = vP
		#D term
		vcur = self.getSensedVelocity(q,dq,dt)
		eD = None
		if vcur != None:
			eD = vectorops.sub(vcur, self.dxdes)
			vD = gen_mul(self.hD,eD)
			vcmd = vectorops.add(vcmd, vD)
		#I term
		if self.eI != None:
			vI = gen_mul(self.hI,self.eI)
			vcmd = vectorops.add(vcmd, vI)
		#print "task",self.name,"error P=",eP,"D=",eD,"E=",self.eI
		#do acceleration limiting
		if vcur != None:
			dvcmd = vectorops.div(vectorops.sub(vcmd,vcur),dt)
			dvnorm = vectorops.norm(dvcmd)
			if dvnorm > self.dvcmdmax:
				vcmd = vectorops.madd(vcur,dvcmd,self.dvcmdmax/dvnorm*dt)
				print self.name,"acceleration limited by factor",self.dvcmdmax/dvnorm*dt,"to",vcmd
		#do velocity limiting
		vnorm = vectorops.norm(vcmd)
		if vnorm > self.vcmdmax:
			vcmd = vectorops.mul(vcmd,self.vcmdmax/vnorm)
			print self.name,"velocity limited by factor",self.vcmdmax/vnorm,"to",vcmd
		return vcmd
Example #13
0
    def getCommandVelocity(self, q, dq, dt):
        """Gets the command velocity from the current state of the
		robot.
		"""
        eP = self.getSensedError(q)
        #vcmd = hP*eP + hD*eV + hI*eI
        vP = gen_mul(self.hP, eP)
        vcmd = vP
        #D term
        vcur = self.getSensedVelocity(q, dq, dt)
        eD = None
        if vcur != None:
            eD = vectorops.sub(vcur, self.dxdes)
            vD = gen_mul(self.hD, eD)
            vcmd = vectorops.add(vcmd, vD)
        #I term
        if self.eI != None:
            vI = gen_mul(self.hI, self.eI)
            vcmd = vectorops.add(vcmd, vI)
        #print "task",self.name,"error P=",eP,"D=",eD,"E=",self.eI
        #do acceleration limiting
        if vcur != None:
            dvcmd = vectorops.div(vectorops.sub(vcmd, vcur), dt)
            dvnorm = vectorops.norm(dvcmd)
            if dvnorm > self.dvcmdmax:
                vcmd = vectorops.madd(vcur, dvcmd, self.dvcmdmax / dvnorm * dt)
                print self.name, "acceleration limited by factor", self.dvcmdmax / dvnorm * dt, "to", vcmd
        #do velocity limiting
        vnorm = vectorops.norm(vcmd)
        if vnorm > self.vcmdmax:
            vcmd = vectorops.mul(vcmd, self.vcmdmax / vnorm)
            print self.name, "velocity limited by factor", self.vcmdmax / vnorm, "to", vcmd
        return vcmd
Example #14
0
def scaleToBounds(val, bmin, bmax, origin=None):
    """Cap the ray starting origin in the direction val against bounding box limits.
	"""
    if origin != None:
        if isinstance(bmin, np.ndarray):
            bmin -= origin
        else:
            bmin = vectorops.sub(bmin, origin)
        if isinstance(bmax, np.ndarray):
            bmax -= origin
        else:
            bmax = vectorops.sub(bmax, origin)
        return scaleToBounds(val, bmin, bmax)
    umax = 1.0
    for vali, ai, bi in zip(val, bmin, bmax):
        assert bi >= ai
        if vali < ai:
            umax = ai / vali
        if vali > bi:
            umax = bi / vali
    if umax == 1.0: return val
    assert umax >= 0
    print "Scaling to velocity maximum, factor", umax
    if isinstance(val, np.ndarray):
        return val * umax
    else:
        return vectorops.mul(val, umax)
Example #15
0
    def advance(self, q, dq, dt):
        """ Updates internal state: accumulates iterm and updates x_last
		"""
        if self.weight > 0:
            eP = self.getSensedError(q)
            # update iterm
            if self.eI == None:
                self.eI = vectorops.mul(eP, dt)
            else:
                self.eI = vectorops.madd(self.eI, eP, dt)
            einorm = vectorops.norm(self.eI)
            if einorm > self.eImax:
                self.eI = vectorops.mul(self.eI, self.eImax / einorm)

        #update qLast
        self.qLast = q
        return
	def advance(self, q, dq, dt):
		""" Updates internal state: accumulates iterm and updates x_last
		"""
		if self.weight > 0:
			eP = self.getSensedError(q)
			# update iterm
			if self.eI == None:
				self.eI = vectorops.mul(eP,dt)
			else:
				self.eI = vectorops.madd(self.eI, eP, dt)
			einorm = vectorops.norm(self.eI)
			if einorm > self.eImax:
				self.eI = vectorops.mul(self.eI,self.eImax/einorm)

		#update qLast
		self.qLast = q
		return
    def apply_tendon_forces(self,link1,link2,rest_length):
        tendon_c2 = 30000.0
        tendon_c1 = 100000.0
        b1 = self.sim.body(self.model.robot.link(link1))
        b2 = self.sim.body(self.model.robot.link(link2))
        p1w = se3.apply(b1.getTransform(),self.tendon1_local)
        p2w = se3.apply(b2.getTransform(),self.tendon2_local)

        d = vectorops.distance(p1w,p2w)
        if d > rest_length:
            #apply tendon force
            direction = vectorops.unit(vectorops.sub(p2w,p1w))
            f = tendon_c2*(d - rest_length)**2+tendon_c1*(d - rest_length)
            b1.applyForceAtPoint(vectorops.mul(direction,f),p1w)
            b2.applyForceAtPoint(vectorops.mul(direction,-f),p2w)
        else:
            pass
Example #18
0
 def process(self, inputs):
     #do a filter
     if self.value == None:
         self.value = inputs
     else:
         #exponential filter
         x = vectorops.mul(self.value, 1.0 - self.rate)
         self.value = vectorops.madd(x, inputs, self.rate)
     return self.value
Example #19
0
 def process(self,inputs):
     #do a filter
     if self.value == None:
         self.value = inputs
     else:
         #exponential filter
         x = vectorops.mul(self.value,1.0-self.rate)
         self.value = vectorops.madd(x,inputs,self.rate)
     return self.value
def append_debounced_command(qend,vend,qdes,motion_queue):
    """Appends a debounced command from qend,vend to qdes,vdes (with vdes=0) 
    to the given motion queue.  Assumes qend,vend is the end of the motion
    queue."""
    global vmax
    #hack: estimate time of motion
    L = Linf_norm(vend) 
    p = vectorops.madd(qend,vend,0.5)
    L += Linf_norm(vectorops.sub(qdes,p))
    T = math.sqrt(L / vmax)
    if T == 0:
        return
    temp = vectorops.madd(qend,vectorops.sub(qdes,qend),0.85)
    motion_queue.appendCubic(T,temp,vectorops.mul(vectorops.sub(qdes,qend),1.0/T*0.25))
    temp2 = vectorops.madd(qend,vectorops.sub(qdes,qend),0.95)
    motion_queue.appendCubic(T*0.75,temp2,vectorops.mul(vectorops.sub(qdes,qend),1.0/T*0.05))
    motion_queue.appendCubic(T*0.5,qdes,[0]*len(qdes))
    return
Example #21
0
    def apply_tendon_forces(self,link1,link2,rest_length):
        tendon_c2 = 30000.0
        tendon_c1 = 100000.0
        b1 = self.sim.getBody(self.model.robot.getLink(link1))
        b2 = self.sim.getBody(self.model.robot.getLink(link2))
        p1w = se3.apply(b1.getTransform(),self.tendon1_local)
        p2w = se3.apply(b2.getTransform(),self.tendon2_local)

        d = vectorops.distance(p1w,p2w)
        if d > rest_length:
            #apply tendon force
            direction = vectorops.unit(vectorops.sub(p2w,p1w))
            f = tendon_c2*(d - rest_length)**2+tendon_c1*(d - rest_length)
            #print "d",d,"rest length",rest_length,"force",f
            b1.applyForceAtPoint(vectorops.mul(direction,f),p1w)
            b2.applyForceAtPoint(vectorops.mul(direction,-f),p2w)
        else:
            #print "d",d,"rest length",rest_length
            pass
def send_debounced_command(qcur,vcur,qdes,motion_queue):
    """Sends a debounced command from qcur,vcur to qdes,vdes (with vdes=0) 
    to the given motion queue"""
    global vmax
    #hack: estimate time of motion
    L = Linf_norm(vcur) 
    p = vectorops.madd(qcur,vcur,0.5)
    L += Linf_norm(vectorops.sub(qdes,p))
    T = math.sqrt(L / vmax)
    if T == 0:
        return
    temp = vectorops.madd(qcur,vectorops.sub(qdes,qcur),0.85)
    motion_queue.setCubic(T,temp,vectorops.mul(vectorops.sub(qdes,qcur),1.0/T*0.25))
    temp2 = vectorops.madd(qcur,vectorops.sub(qdes,qcur),0.95)
    motion_queue.appendCubic(T*0.75,temp2,vectorops.mul(vectorops.sub(qdes,qcur),1.0/T*0.05))
    motion_queue.appendCubic(T*0.5,qdes,[0]*len(qdes))
    return

    #old: trying quintic motion
    """
	def getStackedVelocity(self, q, dq, dt, priority):
		"""Formulates dx to calculate dqdes
		"""
		Vlist = []
		for taski in self.taskList:
			if taski.weight == 0 or taski.level != priority:
				continue
			#scale by weight
			Vtemp = vectorops.mul(taski.getCommandVelocity(q, dq, dt),taski.weight)
			Vlist.append(Vtemp)
		if len(Vlist)==0: return None
		V = np.hstack(Vlist)
		return V
Example #24
0
	def getStackedVelocity(self, q, dq, dt, priority):
		"""Formulates dx to calculate dqdes
		"""
		Vlist = []
		for taski in self.taskList:
			if taski.weight == 0 or taski.level != priority:
				continue
			#scale by weight
			Vtemp = vectorops.mul(taski.getCommandVelocity(q, dq, dt),taski.weight)
			Vlist.append(Vtemp)
		if len(Vlist)==0: return None
		V = np.hstack(Vlist)
		return V
Example #25
0
    def control_loop(self):
        sim = self.sim
        world = self.world
        controller = sim.getController(0)
        robotModel = world.robot(0)
        t = self.ttotal
        #Problem 1: tune the values in this line
        if problem == "1a" or problem == "1b":
            kP = 1
            kI = 1
            kD = 1
            controller.setPIDGains([kP], [kI], [kD])

        #Problem 2: use setTorque to implement a control loop with feedforward
        #torques
        if problem == "2a" or problem == "2b":
            qcur = controller.getSensedConfig()
            dqcur = controller.getSensedVelocity()
            qdes = [0]
            dqdes = [0]
            robotModel.setConfig(qcur)
            robotModel.setVelocity(dqcur)
            while qcur[0] - qdes[0] > math.pi:
                qcur[0] -= 2 * math.pi
            while qcur[0] - qdes[0] < -math.pi:
                qcur[0] += 2 * math.pi
            ddq = vectorops.mul(vectorops.sub(qdes, qcur), 100.0)
            ddq = vectorops.madd(ddq, vectorops.sub(dqdes, dqcur), 20.0)
            #TODO: solve the dynamics equation to fill this in
            T = [3]
            controller.setTorque(T)

        #Problem 3: drive the robot so its end effector goes
        #smoothly toward the target point
        if problem == "3":
            target = [1.0, 0.0, 0.0]
            qdes = [0.7, -2.3]
            dqdes = [0, 0]
            controller.setPIDCommand(qdes, dqdes)
Example #26
0
File: ex.py Project: arocchi/Klampt
    def control_loop(self):
        sim = self.sim
        world = self.world
        controller = sim.getController(0)
        robotModel = world.robot(0)
        t = self.ttotal
        #Problem 1: tune the values in this line
        if problem == "1a" or problem == "1b":
            kP = 1
            kI = 1
            kD = 1
            controller.setPIDGains([kP],[kI],[kD])
        
        #Problem 2: use setTorque to implement a control loop with feedforward
        #torques
        if problem == "2a" or problem == "2b":
            qcur = controller.getSensedConfig()
            dqcur = controller.getSensedVelocity()
            qdes = [0]
            dqdes = [0]
            robotModel.setConfig(qcur)
            robotModel.setVelocity(dqcur)
            while qcur[0]-qdes[0] > math.pi:
                qcur[0] -= 2*math.pi
            while qcur[0]-qdes[0] < -math.pi:
                qcur[0] += 2*math.pi
            ddq = vectorops.mul(vectorops.sub(qdes,qcur),100.0)
            ddq = vectorops.madd(ddq,vectorops.sub(dqdes,dqcur),20.0)
            #TODO: solve the dynamics equation to fill this in
            T = [3]
            controller.setTorque(T)

        #Problem 3: drive the robot so its end effector goes
        #smoothly toward the target point
        if problem == "3":
            target = [1.0,0.0,0.0]
            qdes = [0.7,-2.3]
            dqdes = [0,0]
            controller.setPIDCommand(qdes,dqdes)
Example #27
0
def load_item_geometry(bmin,bmax,geometry_ptr = None):
    """Loads the geometry of the given item and returns it.  If geometry_ptr
    is provided, then it is assumed to be a Geometry3D object and the object
    geometry is loaded into it."""
    if geometry_ptr == None:
        geometry_ptr = Geometry3D()

    # fn = model_dir + "cylinder.tri"
    fn = model_dir + "cube.tri"
    # fn = model_dir + "/objects/teapot/pots.tri"
    # bmin = [0,0,0]
    # bmax = [1.2,1.5,1.25]
    # fn = model_dir + "items/rollodex_mesh_collection_jumbo_pencil_cup/textured_meshes/optimized_poisson_textured_mesh.ply"

    if not geometry_ptr.loadFile(fn):
        print "Error loading cube file",fn
        exit(1)
    center = vectorops.mul(vectorops.add(bmin,bmax),0.5)
    scale = [bmax[0]-bmin[0],0,0,0,bmax[1]-bmin[1],0,0,0,bmax[2]-bmin[2]]
    translate = vectorops.sub(bmin,center)
    geometry_ptr.transform(so3.mul(scale,so3.rotation([0,0,1],math.pi/180*0)),translate)
    geometry_ptr.setCurrentTransform(so3.identity(),[0,0,0])
    return geometry_ptr
    def apply_tendon_forces(self, i, link1, link2, rest_length):
        tendon_c2 = 30000.0
        tendon_c1 = 10000.0
        b0 = self.sim.body(
            self.model.robot.link(self.model.proximal_links[0] - 3))
        b1 = self.sim.body(self.model.robot.link(link1))
        b2 = self.sim.body(self.model.robot.link(link2))
        p0w = se3.apply(b1.getTransform(), self.tendon0_local)
        p1w = se3.apply(b1.getTransform(), self.tendon1_local)
        p2w = se3.apply(b2.getTransform(), self.tendon2_local)

        d = vectorops.distance(p1w, p2w)
        if d > rest_length:
            #apply tendon force
            direction = vectorops.unit(vectorops.sub(p2w, p1w))
            f = tendon_c2 * (d - rest_length)**2 + tendon_c1 * (d -
                                                                rest_length)
            #print d,rest_length
            #print "Force magnitude",self.model.robot.link(link1).getName(),":",f
            f = min(f, 100)
            #tendon routing force
            straight = vectorops.unit(vectorops.sub(p2w, p0w))
            pulley_direction = vectorops.unit(vectorops.sub(p1w, p0w))
            pulley_axis = so3.apply(b1.getTransform()[0], (0, 1, 0))
            tangential_axis = vectorops.cross(pulley_axis, pulley_direction)
            cosangle = vectorops.dot(straight, tangential_axis)
            #print "Cosine angle",self.model.robot.link(link1).getName(),cosangle
            base_direction = so3.apply(b0.getTransform()[0], [0, 0, -1])
            b0.applyForceAtLocalPoint(
                vectorops.mul(base_direction, -f),
                vectorops.madd(p0w, base_direction, 0.04))
            b1.applyForceAtLocalPoint(
                vectorops.mul(tangential_axis, cosangle * f),
                self.tendon1_local)
            b1.applyForceAtLocalPoint(
                vectorops.mul(tangential_axis, -cosangle * f),
                self.tendon0_local)
            b2.applyForceAtLocalPoint(vectorops.mul(direction, -f),
                                      self.tendon2_local)
            self.forces[i][1] = vectorops.mul(tangential_axis, cosangle * f)
            self.forces[i][2] = vectorops.mul(direction, f)
        else:
            self.forces[i] = [None, None, None]
        return
Example #29
0
    def move_to_grasp_object(self,object):
        """Sets the robot's configuration so the gripper grasps object at
        one of its potential grasp locations.  Might change self.active_limb
        to the appropriate limb.

        If successful, changes self.config and returns True.
        Otherwise, does not change self.config and returns False.
        """
      
        # the gripper center transform is given in the camera frame
        # so use the camera link and give the fix point as the gripper center
        for link, gripper_center, side in [ (self.left_gripper_link, left_gripper_center_xform[1], 'left'), \
                                            (self.right_gripper_link, right_gripper_center_xform[1], 'right') ]:    
            # check all possible grasp points
            for grasp_xform in self.knowledge.grasp_xforms(object):
                # compute the grasp point using the gripper center offset
                grasp_point = se3.apply(grasp_xform, vectorops.mul(gripper_center, -1))
                #grasp_point = vectorops.sub(grasp_xform[1], gripper_center)
                # move the gripper center to grasp point aligned with the grasp frame
                # note use of the camera link frame since the grasp offset is specified in that frame
                goal = ik.objective(link, R=grasp_xform[0], t=grasp_point)
                # reset the robot to the starting config
                goal.robot.setConfig(self.config)
                # try with 50 attempts
                # randomize after each failed attempt        
                for attempts in range(50):
                    # solve the inverse kinematics with 1 mm accuracy
                    if ik.solve(goal, tol=0.001):
                        self.active_limb = side
                        self.config = goal.robot.getConfig()
                        return True
                    else:
                        # randomize this limb
                        randomize_links(goal.robot, arm_link_names[side])
        
        return False
Example #30
0
def spawn_objects_from_ground_truth(world):
    """For all ground_truth_items, spawns RigidObjects in the world
    according to their sizes / mass properties"""

    print "Initializing world objects"
    for item in ground_truth_items:
        obj = world.makeRigidObject(item.info.name)
        bmin,bmax = item.info.bmin,item.info.bmax
        center = vectorops.div(vectorops.add(bmin,bmax),2.0)
        m = obj.getMass()
        m.setMass(item.info.mass)
        m.setCom([0,0,0])
        m.setInertia(vectorops.mul([bmax[0]-bmin[0],bmax[1]-bmin[1],bmax[2]-bmin[2]],item.info.mass/12.0))
        obj.setMass(m)
        c = obj.getContactParameters()
        c.kFriction = 0.6
        c.kRestitution = 0.1;
        c.kStiffness = 100000
        c.kDamping = 100000
        obj.setContactParameters(c)
        simgeometry = obj.geometry()
        load_item_geometry(item,simgeometry)
        obj.setTransform(item.xform[0],item.xform[1])
    return
    def onMessage(self, msg):
        global deviceState, defaultDeviceState
        #print "Getting haptic message"
        #print msg
        if msg['type'] != 'MultiHapticState':
            print "Strange message type", msg['type']
            return
        if len(deviceState) == 0:
            print "Adding", len(
                msg['devices']) - len(deviceState), "haptic devices"
            while len(deviceState) < len(msg['devices']):
                deviceState.append(defaultDeviceState.copy())

        if len(msg['devices']) != len(deviceState):
            print "Incorrect number of devices in message:", len(
                msg['devices'])
            return

        #change overall state depending on button 2
        if 'events' in msg:
            for e in msg['events']:
                #print e['type']
                if e['type'] == 'b2_down':
                    dstate = deviceState[e['device']]
                    toggleMode(dstate)
                    print 'Changing device', e['device'], 'to state', dstate[
                        'mode']

        for i in range(len(deviceState)):
            dmsg = msg['devices'][i]
            dstate = deviceState[i]
            if dmsg['button1'] == 1:
                #drag widget if button 1 is down
                oldButtonDown = dstate['buttonDown']
                dstate['buttonDown'] = True
                #moving
                if dstate['mode'] == 'normal':
                    if not oldButtonDown:
                        dstate['moveStartDeviceTransform'] = (so3.from_moment(
                            dmsg['rotationMoment']), dmsg['position'])
                        if self.widgetGetters == None:
                            dstate['moveStartWidgetTransform'] = dstate[
                                'widgetTransform']
                        else:
                            Twidget = self.widgetGetters[i]()
                            if Twidget != None:
                                dstate['moveStartWidgetTransform'] = Twidget
                            else:
                                dstate['moveStartWidgetTransform'] = dstate[
                                    'widgetTransform']
#================================================================================================
#                    #perform transformation of widget
#                    deviceTransform = (so3.from_moment(dmsg['rotationMoment']),dmsg['position'])
#                    #compute relative motion
#                    Tdev = se3.mul(deviceToWidgetTransform,deviceTransform)
#                    TdevStart = se3.mul(deviceToWidgetTransform,dstate['moveStartDeviceTransform'])
#                    relDeviceTransform = (so3.mul(Tdev[0],so3.inv(TdevStart[0])),vectorops.sub(Tdev[1],TdevStart[1]))
#                    #scale relative motion
#                    Rrel,trel = relDeviceTransform
#                    wrel = so3.moment(Rrel)
#                    wrel = vectorops.mul(wrel,dstate['rotationScale'])
#                    trel = vectorops.mul(trel,dstate['positionScale'])
#                    #print "Moving",trel,"rotating",wrel
#                    relDeviceTransform = (so3.from_moment(wrel),trel)
#                    #perform transform
#                    dstate['widgetTransform'] = se3.mul(dstate['moveStartWidgetTransform'],relDeviceTransform)
#================================================================================================
#- perform transformation of widget
                    deviceTransform = (so3.from_moment(dmsg['rotationMoment']),
                                       dmsg['position'])
                    # delta_device = vectorops.sub(deviceTransform[1],dstate['moveStartDeviceTransform'][1])
                    # print "haptic moves: ", delta_device
                    delta_device_R_matrix = so3.mul(
                        deviceTransform[0],
                        so3.inv(dstate['moveStartDeviceTransform'][0]))
                    #                    delta_device_R = so3.moment(delta_device_R_matrix)
                    #                    norm_delta_R = vectorops.norm(delta_device_R)
                    #                    if norm_delta_R != 0:
                    #                        vec_delta_R = vectorops.div(delta_device_R, norm_delta_R)
                    #                    else:
                    #                        vec_delta_R = [0,0,0]
                    #
                    #                    print "haptic rotate: norm = ", norm_delta_R, ", vec = ", vec_delta_R

                    #- compute relative motion
                    Tdev = se3.mul(deviceToBaxterBaseTransform,
                                   deviceTransform)
                    TdevStart = se3.mul(deviceToBaxterBaseTransform,
                                        dstate['moveStartDeviceTransform'])
                    # delta_widget = vectorops.sub(Tdev[1],TdevStart[1])
                    # print "Baxter moves: ", delta_widget
                    #                    delta_widget_R_matrix = so3.mul(Tdev[0],so3.inv(TdevStart[0]))
                    #                    delta_widget_R = so3.moment(delta_widget_R_matrix)
                    #                    norm_widget_R = vectorops.norm(delta_widget_R)
                    #                    if norm_widget_R != 0:
                    #                        vec_widget_R = vectorops.div(delta_widget_R, norm_widget_R)
                    #                    else:
                    #                        vec_widget_R = [0,0,0]

                    #                    print "Baxter rotate: norm = ", norm_widget_R, ", vec = ", vec_widget_R

                    relDeviceTransform = (so3.mul(Tdev[0],
                                                  so3.inv(TdevStart[0])),
                                          vectorops.sub(Tdev[1], TdevStart[1]))

                    #- scale relative motion
                    Rrel, trel = relDeviceTransform
                    wrel = so3.moment(Rrel)
                    wrel = vectorops.mul(wrel, dstate['rotationScale'])
                    trel = vectorops.mul(trel, dstate['positionScale'])

                    #- print "Moving",trel,"rotating",wrel
                    relDeviceTransform = (so3.from_moment(wrel), trel)

                    #- perform transform
                    # dstate['widgetTransform'] = se3.mul(dstate['moveStartWidgetTransform'],relDeviceTransform)
                    dstate['widgetTransform'] = (
                        so3.mul(dstate['moveStartWidgetTransform'][0],
                                relDeviceTransform[0]),
                        vectorops.add(dstate['moveStartWidgetTransform'][1],
                                      relDeviceTransform[1]))


#================================================================================================

                elif dstate['mode'] == 'scaling':
                    if not oldButtonDown:
                        dstate['moveStartDeviceTransform'] = (so3.from_moment(
                            dmsg['rotationMoment']), dmsg['position'])
                    #perform scaling
                    deviceTransform = (so3.from_moment(dmsg['rotationMoment']),
                                       dmsg['position'])
                    oldDeviceTransform = dstate['moveStartDeviceTransform']
                    znew = deviceTransform[1][1]
                    zold = oldDeviceTransform[1][1]
                    posscalerange = [1e-2, 20]
                    rotscalerange = [0.5, 2]
                    newposscale = min(
                        max(
                            dstate['positionScale'] * math.exp(
                                (znew - zold) * 10), posscalerange[0]),
                        posscalerange[1])
                    newrotscale = min(
                        max(
                            dstate['rotationScale'] * math.exp(
                                (znew - zold) * 4), rotscalerange[0]),
                        rotscalerange[1])
                    if any(newposscale == v for v in posscalerange) or any(
                            newrotscale == v for v in rotscalerange):
                        pass  #dont change the scale
                    else:
                        dstate['positionScale'] = newposscale
                        dstate['rotationScale'] = newrotscale
                    print "Setting position scale to", dstate[
                        'positionScale'], "rotation scale to", dstate[
                            'rotationScale']
                    #update start device transform
                    dstate['moveStartDeviceTransform'] = deviceTransform
                elif dstate['mode'] == 'gripper':
                    print "Gripper mode not available"
                    dstate['mode'] = 'normal'
                    dstate['buttonDown'] = False
            else:
                dstate['buttonDown'] = False
        if self.viewer: self.viewer.update(deviceState)
        else: print "No viewer..."
	def solve(self, q,dq,dt):
		"""Takes sensed q,dq, timestep dt and returns qdes and dqdes
		in joint space.
		"""

		for task in self.taskList:
			task.updateState(q,dq,dt)
		# priority 1
		if not hasattr(self,'timingStats'):
			self.timingStats = defaultdict(int)
		self.timingStats['count'] += 1
		t1 = time.time()
		J1 = self.getStackedJacobian(q,dq,1)
		v1 = self.getStackedVelocity(q,dq,dt,1)
		(A,b) = self.getMotionModel(q,dq,dt)
		if self.activeDofs != None:
			A = select_cols(A,self.activeDofs)
		if sparse.isspmatrix_coo(A) or sparse.isspmatrix_dia(A):
			A = A.tocsr()
		t2 = time.time()
		self.timingStats['get jac/vel p1'] += t2-t1
		
		J2 = self.getStackedJacobian(q,dq,2)
		if J2 is not None:
			V2 = self.getStackedVelocity(q,dq,dt,2)
		t3 = time.time()
		self.timingStats['get jac/vel p2'] += t3-t2

		#compute velocity limits
		vmax = self.robot.getVelocityLimits()
		vmin = vectorops.mul(vmax,-1.0)
		amax = self.robot.getAccelerationLimits()
		vref = dq if self.ulast == None else self.ulast
		for i,(v,vm,am) in enumerate(zip(vref,vmin,amax)):
			if v-dt*am > vm:
				vmin[i] = v-dt*am
			elif v < vm:
				#accelerate!
				vmin[i] = min(vm,v+dt*am)
		for i,(v,vm,am) in enumerate(zip(vref,vmax,amax)):
			if v-dt*am < vm:
				vmax[i] = v+dt*am
			elif v > vm:
				#decelerate!
				vmax[i] = max(vm,v-dt*am)
		for i,(l,u) in enumerate(zip(vmin,vmax)):
			assert l <= u
			if l > 0 or u < 0:
				print "Moving link:",self.robot.getLink(i).getName(),"speed",vref[i]
		#print zip(vmin,vmax)
		Aumin = np.array(vmin) - b
		Aumax = np.array(vmax) - b
		#print zip(Aumin.tolist(),Aumax.tolist())
			
		J1A = J1.dot(A)
		J1b = J1.dot(b)
		if J2 == None:
			#just solve constrained least squares
			#J1*(A*u+b) = v1
			#vmin < A*u + b < vmax
			u1 = constrained_lsqr(J1A,v1-J1b,A,Aumin,Aumax)[0]
			u2 = [0.0]*len(u1)
			t4 = time.time()
			self.timingStats['pinv jac p1'] += t4-t3
		else:			
			#solve equality constrained least squares
			#dq = A*u + b
			#J1*dq = v1
			#J1*A*u + J1*b = v1
			#least squares solve for u1:
			#J1*A*u1 = v1 - J1*b
			#vmin < A*u1 + b < vmax
			#need u to satisfy
			#Aact*u = bact
			#we know that u1 satisfies Aact*u = bact
			#let u = u1+u2
			#=> u2 = (I - Aact^+ Aact) z = N*z
			#least squares solve for z:
			#J2*A*(u1+u2+b) = v2
			#J2*A*N z = v2 - J2*(A*u1+b)
			(u1, active, activeRhs) = constrained_lsqr(J1A,v1-J1b,A,Aumin,Aumax)
			Aact = sparse.vstack([J1A]+[A[crow,:] for crow in active]).todense()
			#bact = np.hstack((v1-J1b,activeRhs))
			J1Ainv = np.linalg.pinv(Aact)
			dq1 = A.dot(u1)+b
			if len(active)>0:
				print "Priority 1 active constraints:"
				for a in active:
					print self.robot.getLink(a).getName(),vmin[a],dq1[a],vmax[a]

			r1 = J1.dot(dq1)-v1
			print "Op space controller solve"
			print "  Residual 1",np.linalg.norm(r1)

			# priority 2
			N = np.eye(len(dq)) - np.dot(J1Ainv, Aact)
			t4 = time.time()
			self.timingStats['pinv jac p1'] += t4-t3

			u2 = [0.0]*len(u1)
			#print "  Initial priority 2 task error",np.linalg.norm(V2-J2.dot(dq1))
			J2A = J2.dot(A)
			J2AN = J2A.dot(N)
			AN = sparse.csr_matrix(np.dot(A.todense(),N))
			#Note: N destroys sparsity
			V2_m_resid = np.ravel(V2 - J2.dot(dq1))
			(z,active,activeRhs) = constrained_lsqr(J2AN,V2_m_resid,AN,vmin-dq1,vmax-dq1)
			t5 = time.time()
			self.timingStats['ls jac p2'] += t5-t4
			u2 = np.ravel(np.dot(N, z))

			#debug, should be close to zero
			#print "  Nullspace projection error:",np.linalg.norm(J1A.dot(u2))
			#this is the error in the nullspace of the first priority tasks
			dq2 = A.dot(u2) + dq1

			#debug, should be equal to residual 2 printout above
			print "  Residual 2",np.linalg.norm(J2.dot(dq2)-V2)
			#debug should be close to zero
			#print "  Residual 2 in priority 1 frame",np.linalg.norm(J1.dot(dq2)-v1)
			if len(active)>0:
				print "Priority 2 active constraints:"
				for a in active:
					print self.robot.getLink(a).getName(),vmin[a],dq2[a],vmax[a]

		#compose the velocities together
		u = np.ravel((u1 + u2))
		dqpred = A.dot(u)+b
		print "  Residual 1 final",np.linalg.norm(np.ravel(J1.dot(dqpred))-v1)
		if J2 != None:
			print "  Residual 2 final",np.linalg.norm(np.ravel(J2.dot(dqpred))-V2)
		
		u = u.tolist()
		#if self.activeDofs != None:
		#	print "dqdes:",[self.dqdes[v] for v in self.activeDofs]
		self.qdes = vectorops.madd(q, u, dt)
		self.ulast = u

		t6 = time.time()
		self.timingStats['total']+=t6-t1
		if self.timingStats['count']%10==0:
			n=self.timingStats['count']
			print "OpSpace times (ms): vel/jac 1 %.2f inv 1 %.2f vel/jac 2 %.2f inv 2 %.2f total %.2f"%(self.timingStats['get jac/vel p1']/n*1000,self.timingStats['pinv jac p1']/n*1000,self.timingStats['get jac/vel p2']/n*1000,self.timingStats['ls jac p2']/n*1000,self.timingStats['total']/n*1000)
			
		return (self.qdes,u)
Example #33
0
 def autoInertia(self):
     bmin,bmax = self.bmin,self.bmax
     self.inertia = vectorops.mul([bmax[0]-bmin[0],bmax[1]-bmin[1],bmax[2]-bmin[2]],self.mass/12.0)
Example #34
0
    def solve(self, q, dq, dt):
        """Takes sensed q,dq, timestep dt and returns qdes and dqdes
		in joint space.
		"""

        for task in self.taskList:
            task.updateState(q, dq, dt)
        # priority 1
        if not hasattr(self, 'timingStats'):
            self.timingStats = defaultdict(int)
        self.timingStats['count'] += 1
        t1 = time.time()
        J1 = self.getStackedJacobian(q, dq, 1)
        v1 = self.getStackedVelocity(q, dq, dt, 1)
        (A, b) = self.getMotionModel(q, dq, dt)
        if self.activeDofs != None:
            A = select_cols(A, self.activeDofs)
        if sparse.isspmatrix_coo(A) or sparse.isspmatrix_dia(A):
            A = A.tocsr()
        t2 = time.time()
        self.timingStats['get jac/vel p1'] += t2 - t1

        J2 = self.getStackedJacobian(q, dq, 2)
        if J2 is not None:
            V2 = self.getStackedVelocity(q, dq, dt, 2)
        t3 = time.time()
        self.timingStats['get jac/vel p2'] += t3 - t2

        #compute velocity limits
        vmax = self.robot.getVelocityLimits()
        vmin = vectorops.mul(vmax, -1.0)
        amax = self.robot.getAccelerationLimits()
        vref = dq if self.ulast == None else self.ulast
        for i, (v, vm, am) in enumerate(zip(vref, vmin, amax)):
            if v - dt * am > vm:
                vmin[i] = v - dt * am
            elif v < vm:
                #accelerate!
                vmin[i] = min(vm, v + dt * am)
        for i, (v, vm, am) in enumerate(zip(vref, vmax, amax)):
            if v - dt * am < vm:
                vmax[i] = v + dt * am
            elif v > vm:
                #decelerate!
                vmax[i] = max(vm, v - dt * am)
        for i, (l, u) in enumerate(zip(vmin, vmax)):
            assert l <= u
            if l > 0 or u < 0:
                print "Moving link:", self.robot.getLink(
                    i).getName(), "speed", vref[i]
        #print zip(vmin,vmax)
        Aumin = np.array(vmin) - b
        Aumax = np.array(vmax) - b
        #print zip(Aumin.tolist(),Aumax.tolist())

        J1A = J1.dot(A)
        J1b = J1.dot(b)
        if J2 == None:
            #just solve constrained least squares
            #J1*(A*u+b) = v1
            #vmin < A*u + b < vmax
            u1 = constrained_lsqr(J1A, v1 - J1b, A, Aumin, Aumax)[0]
            u2 = [0.0] * len(u1)
            t4 = time.time()
            self.timingStats['pinv jac p1'] += t4 - t3
        else:
            #solve equality constrained least squares
            #dq = A*u + b
            #J1*dq = v1
            #J1*A*u + J1*b = v1
            #least squares solve for u1:
            #J1*A*u1 = v1 - J1*b
            #vmin < A*u1 + b < vmax
            #need u to satisfy
            #Aact*u = bact
            #we know that u1 satisfies Aact*u = bact
            #let u = u1+u2
            #=> u2 = (I - Aact^+ Aact) z = N*z
            #least squares solve for z:
            #J2*A*(u1+u2+b) = v2
            #J2*A*N z = v2 - J2*(A*u1+b)
            (u1, active, activeRhs) = constrained_lsqr(J1A, v1 - J1b, A, Aumin,
                                                       Aumax)
            Aact = sparse.vstack([J1A] + [A[crow, :]
                                          for crow in active]).todense()
            #bact = np.hstack((v1-J1b,activeRhs))
            J1Ainv = np.linalg.pinv(Aact)
            dq1 = A.dot(u1) + b
            if len(active) > 0:
                print "Priority 1 active constraints:"
                for a in active:
                    print self.robot.getLink(
                        a).getName(), vmin[a], dq1[a], vmax[a]

            r1 = J1.dot(dq1) - v1
            print "Op space controller solve"
            print "  Residual 1", np.linalg.norm(r1)

            # priority 2
            N = np.eye(len(dq)) - np.dot(J1Ainv, Aact)
            t4 = time.time()
            self.timingStats['pinv jac p1'] += t4 - t3

            u2 = [0.0] * len(u1)
            #print "  Initial priority 2 task error",np.linalg.norm(V2-J2.dot(dq1))
            J2A = J2.dot(A)
            J2AN = J2A.dot(N)
            AN = sparse.csr_matrix(np.dot(A.todense(), N))
            #Note: N destroys sparsity
            V2_m_resid = np.ravel(V2 - J2.dot(dq1))
            (z, active, activeRhs) = constrained_lsqr(J2AN, V2_m_resid, AN,
                                                      vmin - dq1, vmax - dq1)
            t5 = time.time()
            self.timingStats['ls jac p2'] += t5 - t4
            u2 = np.ravel(np.dot(N, z))

            #debug, should be close to zero
            #print "  Nullspace projection error:",np.linalg.norm(J1A.dot(u2))
            #this is the error in the nullspace of the first priority tasks
            dq2 = A.dot(u2) + dq1

            #debug, should be equal to residual 2 printout above
            print "  Residual 2", np.linalg.norm(J2.dot(dq2) - V2)
            #debug should be close to zero
            #print "  Residual 2 in priority 1 frame",np.linalg.norm(J1.dot(dq2)-v1)
            if len(active) > 0:
                print "Priority 2 active constraints:"
                for a in active:
                    print self.robot.getLink(
                        a).getName(), vmin[a], dq2[a], vmax[a]

        #compose the velocities together
        u = np.ravel((u1 + u2))
        dqpred = A.dot(u) + b
        print "  Residual 1 final", np.linalg.norm(
            np.ravel(J1.dot(dqpred)) - v1)
        if J2 != None:
            print "  Residual 2 final", np.linalg.norm(
                np.ravel(J2.dot(dqpred)) - V2)

        u = u.tolist()
        #if self.activeDofs != None:
        #	print "dqdes:",[self.dqdes[v] for v in self.activeDofs]
        self.qdes = vectorops.madd(q, u, dt)
        self.ulast = u

        t6 = time.time()
        self.timingStats['total'] += t6 - t1
        if self.timingStats['count'] % 10 == 0:
            n = self.timingStats['count']
            print "OpSpace times (ms): vel/jac 1 %.2f inv 1 %.2f vel/jac 2 %.2f inv 2 %.2f total %.2f" % (
                self.timingStats['get jac/vel p1'] / n * 1000,
                self.timingStats['pinv jac p1'] / n * 1000,
                self.timingStats['get jac/vel p2'] / n * 1000,
                self.timingStats['ls jac p2'] / n * 1000,
                self.timingStats['total'] / n * 1000)

        return (self.qdes, u)
def power_grasp_medial_axis(pc,bin,object,knowledgeBase):
    """Returns a power grasp for the Reflex gripper to grasp the medial axis
    of the  point cloud given in the Baxter's frame (i.e., x is forward, z
    is up).

    Input:
        - pc: a klampt.PointCloud object
        - bin: a bin name
        - object: an object name
        - knowledgeBase: an apc.KnowledgeBase object
        
    Returns a pair (g,s):
        - g: an apc.ItemGrasp member defining the grasp.  Its xform member is
          given in the Baxter's local frame.
        - s: a confidence score, with 0 = unconfident, 1 = confident
    """
    global gripper,depthmax,powerwidthmax
    points = []
    for i in xrange(0,len(pc.vertices),3):
        points.append([pc.vertices[i],pc.vertices[i+1],pc.vertices[i+2]])
    mean = [0,0,0]
    for p in points:
        mean = vectorops.add(mean,p)
    mean = vectorops.mul(mean,1.0/len(points))
    bmin,bmax = points[0][:],points[0][:]
    for p in points:
        if p[0] < bmin[0]: bmin[0]=p[0]
        elif p[0] > bmax[0]: bmax[0]=p[0]
        if p[1] < bmin[1]: bmin[1]=p[1]
        elif p[1] > bmax[1]: bmax[1]=p[1]
        if p[2] < bmin[2]: bmin[2]=p[2]
        elif p[2] > bmax[2]: bmax[2]=p[2]
    median = vectorops.mul(vectorops.add(bmin,bmax),0.5)
    width = bmax[1]-bmin[1]
    depth = bmax[0]-bmin[0]
    height = bmax[2]-bmin[2]

    #determine an adequate center
    graspcenter = median[:]
    if depth*0.5 > depthmax - center_to_finger:
        graspcenter[0] = bmin[0] + depthmax - center_to_finger
    
    graspfile = os.path.join("../resources",gripper,object,'default_power_grasp.json')
    try:
        f = open(graspfile,'r')
        contents = ''.join(f.readlines())
        g = apc.ItemGrasp()
        g.readFromJson(contents)
        #translate to center of point cloud
        g.grasp_xform = (g.grasp_xform[0],vectorops.add(g.grasp_xform[1],graspcenter))
        return (g,1)
    except IOError:
        print "No default grasp defined for object",object,"trying default"
        graspfile = os.path.join("../resources",gripper,'default_power_grasp.json')
        try:
            f = open(graspfile,'r')
            contents = ''.join(f.readlines())
            g = apc.ItemGrasp()
            g.readFromJson(contents)
            #translate to center of point cloud
            g.grasp_xform = (g.grasp_xform[0],vectorops.add(g.grasp_xform[1],graspcenter))
            #adjust grasp to size of object
            ratio = width/powerwidthmax
            if ratio > 1.0:
                g.gripper_close_command[0] = g.gripper_close_command[1] = g.gripper_close_command[2] = 0.7
                g.gripper_open_command[0] = g.gripper_open_command[1] = g.gripper_open_command[2] = g.gripper_close_command[2] = 1
                return (g,0.1)
            else:
                #simple approximation: angular interpolation
                angle = math.asin(ratio)
                g.gripper_close_command[0] = g.gripper_close_command[1] = g.gripper_close_command[2] = 0.7*angle/(math.pi*0.5)
                g.gripper_open_command[0] = g.gripper_open_command[1] = g.gripper_open_command[2] = g.gripper_open_command[2] = g.gripper_close_command[0]+0.2
            return (g,0.5)
        except IOError:
            print "Default power grasp file",graspfile,"not found"
            return (None,0)