.
This commit is contained in:
parent
c422d12227
commit
a9c518e5c3
9 changed files with 366 additions and 0 deletions
23
Code/INSTALL
Normal file
23
Code/INSTALL
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
INSTALLATION INSTRUCTIONS
|
||||||
|
|
||||||
|
Robotpkg
|
||||||
|
|
||||||
|
sudo apt-get install cmake cmake-curses-gui cmake-qt-gui curl doxygen g++ ipython libassimp-dev assimp-utils libboost-dev omniidl-python omniorb omniorb-idl omniorb-nameserver python python-matplotlib python-numpy python-scipy python2.7 qgit libbz2-dev zlib1g-dev libssl-dev pax tar libeigen3-dev libtinyxml-dev liburdfdom-dev libboost-all-dev libpcre3-dev libopenscenegraph-dev libqt4-dev python-qt4-dev libomniorb4-dev libqt4-opengl-dev python-omniorb python-scipy
|
||||||
|
|
||||||
|
git clone https://git.openrobots.org/robots/robotpkg.git
|
||||||
|
cd robotpkg
|
||||||
|
git clone git://git.openrobots.org/robots/robotpkg/robotpkg-wip wip
|
||||||
|
export INSTALL_PREFIX=/usr/local/insa/openrobots
|
||||||
|
./bootstrap/bootstrap --prefix=$INSTALL_PREFIX
|
||||||
|
cd math/pinocchio; make install
|
||||||
|
cd graphics/collada-dom; make install
|
||||||
|
cd wip/osg-dae; make install
|
||||||
|
cd graphics/gepetto-viewer-corba; make install
|
||||||
|
|
||||||
|
Anaconda
|
||||||
|
|
||||||
|
- dependencies:
|
||||||
|
- pinocchio,
|
||||||
|
- gepetto-viewer-corba,
|
||||||
|
- numpy, scipy,
|
||||||
|
- matplotlib
|
6
Code/config.sh
Normal file
6
Code/config.sh
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export PYTHONPATH=/usr/local/insa/openrobots/lib/python2.7/site-packages
|
||||||
|
export LD_LIBRARY_PATH=/usr/local/insa/openrobots/lib
|
||||||
|
export PATH=/usr/local/insa/openrobots/bin:/usr/local/insa/openrobots/sbin:/bin
|
||||||
|
|
||||||
|
alias python='/usr/bin/python'
|
||||||
|
alias ipython='/usr/bin/ipython'
|
61
Code/display.py
Normal file
61
Code/display.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# Typical header of a Python script using Pinocchio
|
||||||
|
from pinocchio.utils import *
|
||||||
|
from pinocchio.explog import exp,log
|
||||||
|
from numpy.linalg import pinv,norm
|
||||||
|
from pinocchio import SE3ToXYZQUATtuple
|
||||||
|
import gepetto.corbaserver
|
||||||
|
|
||||||
|
# Example of a class Display that connect to Gepetto-viewer and implement a
|
||||||
|
# 'place' method to set the position/rotation of a 3D visual object in a scene.
|
||||||
|
class Display():
|
||||||
|
'''
|
||||||
|
Class Display: Example of a class implementing a client for the Gepetto-viewer server. The main
|
||||||
|
method of the class is 'place', that sets the position/rotation of a 3D visual object in a scene.
|
||||||
|
'''
|
||||||
|
def __init__(self,windowName = "pinocchio" ):
|
||||||
|
'''
|
||||||
|
This function connect with the Gepetto-viewer server and open a window with the given name.
|
||||||
|
If the window already exists, it is kept in the current state. Otherwise, the newly-created
|
||||||
|
window is set up with a scene named 'world'.
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Create the client and connect it with the display server.
|
||||||
|
try:
|
||||||
|
self.viewer=gepetto.corbaserver.Client()
|
||||||
|
except:
|
||||||
|
print("Error while starting the viewer client. ")
|
||||||
|
print("Check whether Gepetto-viewer is properly started")
|
||||||
|
|
||||||
|
# Open a window for displaying your model.
|
||||||
|
try:
|
||||||
|
# If the window already exists, do not do anything.
|
||||||
|
windowID = self.viewer.gui.getWindowID (windowName)
|
||||||
|
print("Warning: window '"+windowName+"' already created.")
|
||||||
|
print("The previously created objects will not be destroyed and do not have to be created again.")
|
||||||
|
except:
|
||||||
|
# Otherwise, create the empty window.
|
||||||
|
windowID = self.viewer.gui.createWindow (windowName)
|
||||||
|
# Start a new "scene" in this window, named "world", with just a floor.
|
||||||
|
self.viewer.gui.createSceneWithFloor("world")
|
||||||
|
self.viewer.gui.addSceneToWindow("world",windowID)
|
||||||
|
|
||||||
|
# Finally, refresh the layout to obtain your first rendering.
|
||||||
|
self.viewer.gui.refresh()
|
||||||
|
|
||||||
|
def nofloor(self):
|
||||||
|
'''
|
||||||
|
This function will hide the floor.
|
||||||
|
'''
|
||||||
|
self.viewer.gui.setVisibility('world/floor',"OFF")
|
||||||
|
self.viewer.gui.refresh()
|
||||||
|
|
||||||
|
def place(self,objName,M,refresh=True):
|
||||||
|
'''
|
||||||
|
This function places (ie changes both translation and rotation) of the object
|
||||||
|
names "objName" in place given by the SE3 object "M". By default, immediately refresh
|
||||||
|
the layout. If multiple objects have to be placed at the same time, do the refresh
|
||||||
|
only at the end of the list.
|
||||||
|
'''
|
||||||
|
self.viewer.gui.applyConfiguration(objName, SE3ToXYZQUATtuple(M))
|
||||||
|
if refresh: self.viewer.gui.refresh()
|
||||||
|
|
30
Code/example_display.py
Normal file
30
Code/example_display.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Example of creation of an object of class Display (implemented in the previous example, inside
|
||||||
|
# a file 'display.py'). Do not forget to start Gepetto-viewer server in another terminal before
|
||||||
|
# creating the client.
|
||||||
|
|
||||||
|
import pinocchio as se3
|
||||||
|
from pinocchio.utils import *
|
||||||
|
|
||||||
|
from display import Display
|
||||||
|
display = Display()
|
||||||
|
|
||||||
|
|
||||||
|
# Example of use of the class Display to create a box visual object.
|
||||||
|
boxid = 147
|
||||||
|
name = 'box' + str(boxid)
|
||||||
|
[w,h,d] = [1.0,1.0,1.0]
|
||||||
|
color = [red,green,blue,transparency] = [1,1,0.78,1.0]
|
||||||
|
display.viewer.gui.addBox('world/'+name, w,h,d,color)
|
||||||
|
|
||||||
|
# Example of use of the class Display to create a sphere visual object.
|
||||||
|
display.viewer.gui.addSphere('world/sphere', 1.0,color)
|
||||||
|
|
||||||
|
# Example of use of the class Display to create a cylinder visual object.
|
||||||
|
radius = 1.0
|
||||||
|
height = 1.0
|
||||||
|
display.viewer.gui.addCylinder('world/cylinder', radius,height,color)
|
||||||
|
|
||||||
|
# Example of use of the class display to place the previously-create object at random SE3 placements.
|
||||||
|
display.place("world/box147",se3.SE3.Random(),False)
|
||||||
|
display.place("world/sphere",se3.SE3.Random(),False)
|
||||||
|
display.place("world/cylinder",se3.SE3.Random())
|
27
Code/example_robot.py
Normal file
27
Code/example_robot.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Create a 7DOF manipulator robot and moves it along a constant (random) velocity during 10secs.
|
||||||
|
import numpy as np
|
||||||
|
from numpy.linalg import pinv,norm
|
||||||
|
from pinocchio import neutral
|
||||||
|
from robot_arm import Robot
|
||||||
|
import time
|
||||||
|
|
||||||
|
# Create a 7DOF robot.
|
||||||
|
robot = Robot()
|
||||||
|
|
||||||
|
# Hide the floor.
|
||||||
|
robot.viewer.viewer.gui.setVisibility('world/floor','OFF')
|
||||||
|
|
||||||
|
# Move the robot during 10secs at velocity v.
|
||||||
|
dt = 1e-3
|
||||||
|
for j in range (robot.model.nv):
|
||||||
|
v = np.array (robot.model.nv * [0])
|
||||||
|
v [j] = 1
|
||||||
|
q = neutral (robot.model)
|
||||||
|
for i in range(1000):
|
||||||
|
q += v*dt
|
||||||
|
robot.display(q)
|
||||||
|
time.sleep(dt)
|
||||||
|
for i in range(1000):
|
||||||
|
q -= v*dt
|
||||||
|
robot.display(q)
|
||||||
|
time.sleep(dt)
|
39
Code/example_scipy.py
Normal file
39
Code/example_scipy.py
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
import numpy as np
|
||||||
|
from scipy.optimize import fmin_bfgs, fmin_slsqp
|
||||||
|
|
||||||
|
def cost(x):
|
||||||
|
'''Cost f(x,y) = x^2 + 2y^2 - 2xy - 2x '''
|
||||||
|
x0 = x[0]
|
||||||
|
x1 = x[1]
|
||||||
|
return -1*(2*x0*x1 + 2*x0 - x0**2 - 2*x1**2)
|
||||||
|
|
||||||
|
def constraint_eq(x):
|
||||||
|
''' Constraint x^3 = y '''
|
||||||
|
return np.array([ x[0]**3-x[1] ])
|
||||||
|
|
||||||
|
def constraint_ineq(x):
|
||||||
|
'''Constraint x>=2, y>=2'''
|
||||||
|
return np.array([ x[0]-2,x[1]-2 ])
|
||||||
|
|
||||||
|
class CallbackLogger:
|
||||||
|
def __init__(self):
|
||||||
|
self.nfeval = 1
|
||||||
|
def __call__(self,x):
|
||||||
|
print('===CBK=== {0:4d} {1: 3.6f} {2: 3.6f} {3: 3.6f}'.format(self.nfeval, x[0], x[1], cost(x)))
|
||||||
|
self.nfeval += 1
|
||||||
|
|
||||||
|
x0 = np.array([0.0,0.0])
|
||||||
|
# Optimize cost without any constraints in BFGS, with traces.
|
||||||
|
xopt_bfgs = fmin_bfgs(cost, x0, callback=CallbackLogger())
|
||||||
|
print('\n *** Xopt in BFGS = ',xopt_bfgs,'\n\n\n\n')
|
||||||
|
|
||||||
|
# Optimize cost without any constraints in CLSQ
|
||||||
|
xopt_lsq = fmin_slsqp(cost,[-1.0,1.0], iprint=2, full_output=1)
|
||||||
|
print('\n *** Xopt in LSQ = ',xopt_lsq,'\n\n\n\n')
|
||||||
|
|
||||||
|
# Optimize cost with equality and inequality constraints in CLSQ
|
||||||
|
xopt_clsq = fmin_slsqp(cost,[-1.0,1.0],
|
||||||
|
f_eqcons=constraint_eq, f_ieqcons=constraint_ineq,
|
||||||
|
iprint=2, full_output=1)
|
||||||
|
print('\n *** Xopt in c-lsq = ',xopt_clsq,'\n\n\n\n')
|
||||||
|
|
37
Code/inverse_kinematics.py
Normal file
37
Code/inverse_kinematics.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import numpy as np
|
||||||
|
import numpy.linalg
|
||||||
|
from scipy.optimize import fmin_bfgs
|
||||||
|
from pinocchio import forwardKinematics, log, neutral
|
||||||
|
import eigenpy
|
||||||
|
eigenpy.switchToNumpyMatrix()
|
||||||
|
|
||||||
|
class CallbackLogger:
|
||||||
|
def __init__(self, ik):
|
||||||
|
self.nfeval = 1
|
||||||
|
self.ik = ik
|
||||||
|
def __call__(self,x):
|
||||||
|
print '===CBK=== {0:4d} {1}'.format(self.nfeval,
|
||||||
|
self.ik.latestCost)
|
||||||
|
self.nfeval += 1
|
||||||
|
|
||||||
|
class InverseKinematics (object):
|
||||||
|
leftFootJoint = 'left_leg_6_joint'
|
||||||
|
rightFootJoint = 'right_leg_6_joint'
|
||||||
|
waistJoint = 'waist_joint'
|
||||||
|
|
||||||
|
def __init__ (self, robot):
|
||||||
|
self.q = neutral (robot.model)
|
||||||
|
forwardKinematics (robot.model, robot.data, self.q)
|
||||||
|
self.robot = robot
|
||||||
|
# Initialize references of feet and center of mass with initial values
|
||||||
|
self.leftFootRefPose = robot.data.oMi [robot.leftFootJointId].copy ()
|
||||||
|
self.rightFootRefPose = robot.data.oMi [robot.rightFootJointId].copy ()
|
||||||
|
self.waistRefPose = robot.data.oMi [robot.waistJointId].copy ()
|
||||||
|
|
||||||
|
def cost (self, q):
|
||||||
|
# Write your code here
|
||||||
|
pass
|
||||||
|
|
||||||
|
def solve (self, q):
|
||||||
|
# Write your code here
|
||||||
|
pass
|
53
Code/legged_robot.py
Normal file
53
Code/legged_robot.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from pinocchio.utils import *
|
||||||
|
from pinocchio.explog import exp,log
|
||||||
|
from numpy.linalg import pinv,norm
|
||||||
|
from pinocchio import SE3, Model, Inertia, JointModelFreeFlyer, JointModelRX, \
|
||||||
|
JointModelRY, JointModelRZ, forwardKinematics, neutral
|
||||||
|
import gepetto.corbaserver
|
||||||
|
from display import Display
|
||||||
|
|
||||||
|
class Visual:
|
||||||
|
'''
|
||||||
|
Class representing one 3D mesh of the robot, to be attached to a joint. The class contains:
|
||||||
|
* the name of the 3D objects inside Gepetto viewer.
|
||||||
|
* the ID of the joint in the kinematic tree to which the body is attached.
|
||||||
|
* the placement of the body with respect to the joint frame.
|
||||||
|
This class is only used in the list Robot.visuals (see below).
|
||||||
|
'''
|
||||||
|
def __init__(self,name,jointParent,placement):
|
||||||
|
self.name = name # Name in gepetto viewer
|
||||||
|
self.jointParent = jointParent # ID (int) of the joint
|
||||||
|
self.placement = placement # placement of the body wrt joint, i.e. bodyMjoint
|
||||||
|
def place(self,display,oMjoint):
|
||||||
|
oMbody = oMjoint*self.placement
|
||||||
|
display.place(self.name,oMbody,False)
|
||||||
|
|
||||||
|
class Robot:
|
||||||
|
'''
|
||||||
|
Define a class Robot representing a biped robot
|
||||||
|
The members of the class are:
|
||||||
|
* viewer: a display encapsulating a gepetto viewer client to create 3D
|
||||||
|
objects and place them.
|
||||||
|
* model: the kinematic tree of the robot.
|
||||||
|
* data: the temporary variables to be used by the kinematic algorithms.
|
||||||
|
* visuals: the list of all the 'visual' 3D objects to render the robot,
|
||||||
|
each element of the list being an object Visual (see above).
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.viewer = Display()
|
||||||
|
self.visuals = []
|
||||||
|
self.model = Model ()
|
||||||
|
self.createLeggedRobot ()
|
||||||
|
self.data = self.model.createData()
|
||||||
|
self.q0 = neutral (self.model)
|
||||||
|
|
||||||
|
def createLeggedRobot (self,rootId=0, prefix=''):
|
||||||
|
# Write your code here
|
||||||
|
pass
|
||||||
|
|
||||||
|
def display(self,q):
|
||||||
|
forwardKinematics(self.model,self.data,q)
|
||||||
|
for visual in self.visuals:
|
||||||
|
visual.place( self.viewer,self.data.oMi[visual.jointParent] )
|
||||||
|
self.viewer.viewer.gui.refresh()
|
90
Code/robot_arm.py
Normal file
90
Code/robot_arm.py
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
from pinocchio.utils import *
|
||||||
|
from pinocchio.explog import exp,log
|
||||||
|
from numpy.linalg import pinv,norm
|
||||||
|
from pinocchio import forwardKinematics, Inertia, JointModelRX, Model, SE3
|
||||||
|
import gepetto.corbaserver
|
||||||
|
from display import Display
|
||||||
|
import eigenpy
|
||||||
|
eigenpy.switchToNumpyArray()
|
||||||
|
|
||||||
|
class Visual:
|
||||||
|
'''
|
||||||
|
Class representing one 3D mesh of the robot, to be attached to a joint. The class contains:
|
||||||
|
* the name of the 3D objects inside Gepetto viewer.
|
||||||
|
* the ID of the joint in the kinematic tree to which the body is attached.
|
||||||
|
* the placement of the body with respect to the joint frame.
|
||||||
|
This class is only used in the list Robot.visuals (see below).
|
||||||
|
'''
|
||||||
|
def __init__(self,name,jointParent,placement):
|
||||||
|
self.name = name # Name in gepetto viewer
|
||||||
|
self.jointParent = jointParent # ID (int) of the joint
|
||||||
|
self.placement = placement # placement of the body wrt joint, i.e. bodyMjoint
|
||||||
|
def place(self,display,oMjoint):
|
||||||
|
oMbody = oMjoint*self.placement
|
||||||
|
display.place(self.name,oMbody,False)
|
||||||
|
|
||||||
|
class Robot:
|
||||||
|
'''
|
||||||
|
Define a class Robot with 7DOF (shoulder=3 + elbow=1 + wrist=3).
|
||||||
|
The configuration is nq=7. The velocity is the same.
|
||||||
|
The members of the class are:
|
||||||
|
* viewer: a display encapsulating a gepetto viewer client to create 3D objects and place them.
|
||||||
|
* model: the kinematic tree of the robot.
|
||||||
|
* data: the temporary variables to be used by the kinematic algorithms.
|
||||||
|
* visuals: the list of all the 'visual' 3D objects to render the robot, each element of the list being
|
||||||
|
an object Visual (see above).
|
||||||
|
|
||||||
|
See tp1.py for an example of use.
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.viewer = Display()
|
||||||
|
self.visuals = []
|
||||||
|
self.model = Model ()
|
||||||
|
self.createArm3DOF()
|
||||||
|
self.data = self.model.createData()
|
||||||
|
self.q0 = zero(self.model.nq)
|
||||||
|
|
||||||
|
def createArm3DOF(self,rootId=0, prefix='', jointPlacement=SE3.Identity()):
|
||||||
|
color = [red,green,blue,transparency] = [1,1,0.78,1.0]
|
||||||
|
colorred = [1.0,0.0,0.0,1.0]
|
||||||
|
|
||||||
|
jointId = rootId
|
||||||
|
|
||||||
|
jointName = prefix + "shoulder_joint"
|
||||||
|
joint = JointModelRX()
|
||||||
|
jointId = self.model.addJoint(jointId,joint,jointPlacement,jointName)
|
||||||
|
self.model.appendBodyToJoint(jointId,Inertia.Random(),SE3.Identity())
|
||||||
|
self.viewer.viewer.gui.addSphere('world/' + prefix + 'shoulder', 0.3,colorred)
|
||||||
|
self.visuals.append( Visual('world/' + prefix + 'shoulder',jointId,SE3.Identity()) )
|
||||||
|
self.viewer.viewer.gui.addBox('world/' + prefix + 'upperarm', .1,.1,.5,color)
|
||||||
|
self.visuals.append( Visual('world/' + prefix + 'upperarm',jointId,SE3(eye(3),np.array([0., 0., .5]))))
|
||||||
|
|
||||||
|
jointName = prefix + "elbow_joint"
|
||||||
|
jointPlacement = SE3(eye(3),np.array( [0, 0, 1.0] ))
|
||||||
|
joint = JointModelRX()
|
||||||
|
jointId = self.model.addJoint(jointId,joint,jointPlacement,jointName)
|
||||||
|
self.model.appendBodyToJoint(jointId,Inertia.Random(),SE3.Identity())
|
||||||
|
self.viewer.viewer.gui.addSphere('world/' + prefix + 'elbow', 0.3,colorred)
|
||||||
|
self.visuals.append( Visual('world/' + prefix + 'elbow',jointId,SE3.Identity()) )
|
||||||
|
self.viewer.viewer.gui.addBox('world/' + prefix + 'lowerarm', .1,.1,.5,color)
|
||||||
|
self.visuals.append( Visual('world/' + prefix + 'lowerarm',jointId,SE3(eye(3),np.array([0., 0., .5]))))
|
||||||
|
|
||||||
|
jointName = prefix + "wrist_joint"
|
||||||
|
jointPlacement = SE3(eye(3),np.array( [0, 0, 1.0] ))
|
||||||
|
joint = JointModelRX()
|
||||||
|
jointId = self.model.addJoint(jointId,joint,jointPlacement,jointName)
|
||||||
|
self.model.appendBodyToJoint(jointId,Inertia.Random(),SE3.Identity())
|
||||||
|
self.viewer.viewer.gui.addSphere('world/' + prefix + 'wrist', 0.3,colorred)
|
||||||
|
self.visuals.append( Visual('world/' + prefix + 'wrist',jointId,SE3.Identity()) )
|
||||||
|
self.viewer.viewer.gui.addBox('world/' + prefix + 'hand', .1,.1,.25,color)
|
||||||
|
self.visuals.append( Visual('world/' + prefix + 'hand',jointId,SE3(eye(3),np.array([0., 0., .25]))))
|
||||||
|
|
||||||
|
|
||||||
|
def display(self,q):
|
||||||
|
forwardKinematics(self.model,self.data,q)
|
||||||
|
for visual in self.visuals:
|
||||||
|
visual.place( self.viewer,self.data.oMi[visual.jointParent] )
|
||||||
|
self.viewer.viewer.gui.refresh()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue