In [1]:
import sys
sys.path.append('../build') #rai/lib')
import numpy as np
import libry as ry
In [2]:
C = ry.Config()
D = C.view()
C.addFile('../rai-robotModels/pr2/pr2.g')
C.addFile('../rai-robotModels/objects/kitchen.g')
For simplicity, let's add a frame that represents goals
In [3]:
goal = C.addFrame("goal")
goal.setShape(ry.ST.sphere, [.05])
goal.setColor([.5,1,1])
goal.setPosition([1,.5,1])
X0 = C.getFrameState() #store the initial configuration
We create an IK engine. The only objective is that the positionDiff
(position difference in world coordinates) between pr2L
(the yellow blob in the left hand) and goal
is equal to zero:
In [4]:
IK = C.komo_IK(False)
IK.addObjective(type=ry.OT.eq, feature=ry.FS.positionDiff, frames=['pr2L', 'goal'])
We now call the optimizer (True means with random initialization/restart).
In [5]:
IK.optimize()
IK.getReport()
Out[5]:
The best way to retrieve the result is to copy the optimized IK configuration back into your working configuration C, which is now also displayed
In [6]:
C.setFrameState( IK.getConfiguration(0) )
We can redo the optimization, but for a different configuration, namely a configuration where the goal is in another location. For this we move goal in our working configuration C, then copy C back into the IK engine's configurations:
In [7]:
## (iterate executing this cell for different goal locations!)
# move goal
goal.setPosition([.8,.2,1.5])
# copy C into the IK's internal configuration(s)
IK.setConfigurations(C)
# reoptimize
IK.optimize(0.) # 0: no adding of noise for a random restart
print(IK.getReport())
# grab result
C.setFrameState( IK.getConfiguration(0) )
Let's solve some other problems, always creating a novel IK engine:
The relative position of goal
in pr2R
coordinates equals [0,0,-.2] (which is 20cm straight in front of the yellow blob)
In [8]:
C.setFrameState(X0)
IK = C.komo_IK(False)
IK.addObjective(type=ry.OT.eq, feature=ry.FS.positionRel, frames=['goal','pr2R'], target=[0,0,-.2])
IK.optimize()
C.setFrameState( IK.getConfiguration(0) )
The distance between pr2R
and pr2L
is zero:
In [9]:
C.setFrameState(X0)
IK = C.komo_IK(False)
IK.addObjective(type=ry.OT.eq, feature=ry.FS.distance, frames=['pr2L','pr2R'])
IK.optimize()
C.setFrameState( IK.getConfiguration(0) )
The 3D difference between the z-vector of pr2R
and the z-vector of goal
:
In [10]:
C.setFrameState(X0)
IK = C.komo_IK(False)
IK.addObjective(type=ry.OT.eq, feature=ry.FS.vectorZDiff, frames=['pr2R', 'goal'])
IK.optimize()
C.setFrameState( IK.getConfiguration(0) )
The scalar product between the z-vector of pr2R
and the z-vector of goal
is zero:
In [11]:
C.setFrameState(X0)
IK = C.komo_IK(False)
IK.addObjective(type=ry.OT.eq, feature=ry.FS.scalarProductZZ, frames=['pr2R', 'goal'])
IK.optimize()
C.setFrameState( IK.getConfiguration(0) )
etc etc
All methods to compute paths or configurations solve constrained optimization problems. To use them, you need to learn to define constrained optimization problems. Some definitions:
sos
(sum-of-squares), eq
, or ineq
, referring to the three cases.pos
for position), typically by a set of frame names that tell which objects we refer to (e.g., pr2L
for the left hand of the pr2), optionally some modifiers (e.g., a scale or target, which linearly transform the feature map), and the set of configuration IDs or time slices the feature is to be computed from (e.g., confs=[15]
if the feat is to be computed from the 15th time slice in a path optimization problem).times=[1., 2.]
, so that the objective is added to each configuration in this time interval.confs=[13, 14, 15]
. Or if you use times=[1.,1.]
, the acceleration features is computed from the configuration that corresponds to time=1 and the two configurations before.sos
, eq
, and ineq
always refer to the feature map to be zero, e.g., constraining all features to be equal to zero with eq
. This is natural for many features, esp. when they refer to differences (e.g. posDiff
or posRel
, which compute the relative position between two frames). However, when one aims to constrain the feature to a non-zero constant value, one can modify the objective with a target
specification.scale
specification. Rescaling changes the costs that arise from sos
objectives. Rescaling also has significant impact on the convergence behavior for eq
and ineq
constraints. As a guide: scale constraints so that if they would be treated as squared penalties (squaredPenalty optim mode, to be made accessible) convergence to reasonable approximate solutions is efficient. Then the AugLag will also converge efficiently to precise constraints.
In [12]:
# Designing a cylinder grasp
In [13]:
D=0
C=0
In [14]:
C = ry.Config()
D = C.view()
C.addFile('../rai-robotModels/pr2/pr2.g')
C.addFile('../rai-robotModels/objects/kitchen.g')
C.setJointState([.7], ["l_gripper_l_finger_joint"])
In [15]:
goal = C.addFrame("goal")
goal.setShape(ry.ST.cylinder, [0,0,.2, .03])
goal.setColor([.5,1,1])
goal.setPosition([1,.5,1])
X0 = C.getFrameState()
In [16]:
C.setFrameState(X0)
goal.setPosition([1,.5,1.2])
IK = C.komo_IK(False)
IK.addObjective(type=ry.OT.eq, feature=ry.FS.positionDiff, frames=['pr2L', 'goal'], scaleTrans=[[1,0,0],[0,1,0]])
IK.addObjective(type=ry.OT.ineq, feature=ry.FS.positionDiff, frames=['pr2L', 'goal'], scaleTrans=[[0,0,1]], target=[0,0,.05])
IK.addObjective(type=ry.OT.ineq, feature=ry.FS.positionDiff, frames=['pr2L', 'goal'], scaleTrans=[[0,0,-1]], target=[0,0,-.05])
IK.addObjective(type=ry.OT.sos, feature=ry.FS.scalarProductZZ, frames=['pr2L', 'goal'], scale=[0.1])
IK.addObjective(type=ry.OT.eq, feature=ry.FS.scalarProductXZ, frames=['pr2L', 'goal'])
IK.optimize()
C.setFrameState( IK.getConfiguration(0) )
IK.getReport()
Out[16]:
In [ ]:
In [ ]: