A real-time robot motion control framework with built-in liveliness
Project description
LivelyTK v0.10.0 (beta)
NOTE: Since LivelyTK is still in beta, the design is subject to change and should not be considered final!
About
LivelyTK Package
The LivelyTK framework provides a highly configurable toolkit for commanding robots in mixed modalities while incorporating liveliness motions. It is adapted from RelaxedIK framework, and compatible with Python and Javascript/Node.
To configure a robot, the easiest method is to use the LivelyStudio interface in the lively_tk_ros repository, which is a wizard for configuring the robot.
Configuring
Configuring of LivelyTK is centered on the Solver class, which you can instantiate in the following ways:
python
from lively_tk import Solver, PositionMatchObjective, OrientationMatchObjective, SmoothnessMacroObjective, CollisionAvoidanceObjective, State, Transform, ScalarRange, BoxShape
solver = Solver(
urdf='<?xml version="1.0" ?><robot name="panda">...</robot>', # Full urdf as a string
objectives=[
PositionMatchObjective(name="EE Position",link="panda_hand",weight=50),
OrientationMatchObjective(name="EE Rotation",link="panda_hand",weight=25),
SmoothnessMacroObjective(name="General Smoothness",weight=10),
CollisionAvoidanceObjective(name="Collision Avoidance",weight=10)
...
],
root_bounds=[
ScalarRange(value=0.0,delta=0.0),ScalarRange(value=0.0,delta=0.0),ScalarRange(value=0.0,delta=0.0), # Translational
ScalarRange(value=0.0,delta=0.0),ScalarRange(value=0.0,delta=0.0),ScalarRange(value=0.0,delta=0.0) # Rotational
],
shapes=[
BoxShape(name="Table",frame="world",physical=True,x=2,y=1,z=1.2,local_transform=Transform.isometry())
],
initial_state=State(origin=Transform.identity(),joints={"panda_joint1":0.0,"panda_joint2":0.0,...}), # Optional
only_core=False, # Only use this flag if you are not using liveliness objectives and want a slight speed-up.
max_retries=1, # Number of times the solution is attempted (default 1)
max_iterations=150 # Number of iterations per try (default 150)
)
javascript
import {
Solver, PositionMatchObjective, OrientationMatchObjective,
SmoothnessMacroObjective, CollisionAvoidanceObjective,
State, Transform, ScalarRange, BoxShape} from "@people_and_robots/lively_tk";
let solver = new Solver(
'<?xml version="1.0" ?><robot name="panda">...</robot>', // Full urdf as a string
[
{type:'PositionMatch',name:"EE Position",link:"panda_hand",weight:50},
{type:'OrientationMatch',name:"EE Rotation",link:"panda_hand",weight:25},
{type:'SmoothnessMacro',name:"General Smoothness",weight:10},
{type:'CollisionAvoidance',name:"Collision Avoidance",weight:10}
...
],
[
{value:0.0,delta:0.0},{value:0.0,delta:0.0},{value:0.0,delta:0.0}, // Translational
{value:0.0,delta:0.0},{value:0.0,delta:0.0},{value:0.0,delta:0.0} // Rotational
],
[
{type:'Box',name="Table",frame:"world",physical:True,x:2,y:1,z:1.2,localTransform:{translation:[0,0,0],rotation:[1,0,0,0]}}
],
{origin:{translation:[0,0,0],rotation:[1,0,0,0]},joints:{panda_joint1:0.0,panda_joint2:0.0,...}}, // Optional
false, // Only use this flag if you are not using liveliness objectives and want a slight speed-up.
1, // Number of times the solution is attempted (default 1)
150 // Number of iterations per try (default 150)
)
Resetting
In both the Javascript and Python interfaces, the Solver
class has a reset
method that allows the user to reset the state of the solver given some new objective weights and a new robot state. In this case, the robot state only needs to supply the joints
and origin
field, as shown in the initialization example.
python
solver.reset(state=State(origin=Transform.identity(),joints={"panda_joint1":0.0,"panda_joint2":0.0,...}),weights=[50.0,30.0,20.0,10.0])
javascript
solver.reset(
{origin:{translation:[0,0,0],rotation:[1,0,0,0]},joints:{panda_joint1:0.0,panda_joint2:0.0,...}}, // New starting state
[50.0,30.0,20.0,10.0] // New starting weights
)
Solving
The Solver
class has a solve
method that represents the core functionality of the LivelyTK interface. At a high level, it accepts the following fields:
goals
: A list of goal-type objects.weights
: A list of floats, order corresponding to the order of the objectives.time
: (float) The current time. If no liveliness objectives are used, this has no effect.shapes
: A list of shape objects.
The solve
method returns a fully-filled State
object
Goals
There are a variety of different "goal" types that can be provided. Think of these as settings that you would like to achieve (e.g. a PositionMatch objective accepts a Translation
goal).
Translation
The translation goal is used by the PositionMatch
, PositionMirroring
, and OriginPositionMatch
objectives.
python
goal = Translation(x:1.0,y:0.0,z:0.5)
javascript
let goal = {Translation:[1.0,0.0,0.5]}
Rotation
The rotation goal is used by the OrientationMatch
, OrientationMirroring
, and OriginOrientationMatch
objectives.
python
goal = Rotation(w:0.707,x:0.0,y:0.0,z:0.707)
javascript
let goal = {Rotation:[0.707,0.0,0.0,0.707]}
Scalar
The scalar goal is used by the JointMatch
, JointMirroring
, DistanceMatch
, JointLiveliness
, and RelativeMotionLiveliness
objectives.
python
goal = 0.5
javascript
let goal = {Scalar:0.5}
Size
The size goal is used by the PositionLiveliness
, OrientationLiveliness
, OriginPositionLiveliness
, and OriginOrientationLiveliness
objectives.
python
goal = Size(x:1.0,y:0.1,z:0.5)
javascript
let goal = {Size:[1.0,0.1,0.5]}
Ellipse
The ellipse goal is used by the PositionBounding
objective.
python
goal = Ellipse(
translation=Translation(x:1.0,y:0.0,z:0.4),
rotation=Rotation(w:0.707,x:0.0,y:0.0,z:0.707),
size=Size(x:0.1,y:0.1,z:0.2)
)
javascript
let goal = {Ellipse: {
pose: {translation: [1.0,0.0,0.4], rotation: [0.707,0.0,0.0,0.707]},
size: [0.1,0.1,0.2]
}
RotationRange
The rotation range goal is used by the RotationBounding
objective.
python
goal = RotationRange(
rotation=Rotation(w:0.707,x:0.0,y:0.0,z:0.707),
delta=0.4
)
javascript
let goal = {RotationRange: {
rotation: [0.707,0.0,0.0,0.707],
delta:0.4
}
ScalarRange
The scalar range goal is used by the JointBounding
objective.
python
goal = ScalarRange(value=0.0,delta=0.4)
javascript
let goal = {ScalarRange: {value:0.0,delta:0.4}
Shapes
There are 4 different Shape classes: Box, Sphere, Capsule, and Cylinder. The name
field is entirely for your own usage, and the frame
field indicates what robot link the shape is attached to (by default "world"). The physical
field indicates whether the shape presents a collision, and should be factored into collision avoidance. Otherwise, the shape is simply tracked in the state if close enough.
Box
python
shape = BoxShape(
name="camera attachment",
frame='panda_hand',
physical=True,
x=0.5,y=0.5,z=0.2,
local_transform=Transform.identity())
javascript
let shape = {
type:'Box',
name:'camera attachment',
frame: 'panda_hand',
physical: true,
x:0.5,y:0.5,z:0.2,
local_transform: {translation:[0.0,0.0,0.0],rotation:[1.0,0.0,0.0,0.0]}
}
Sphere
python
shape = SphereShape(
name="bouncy ball",
frame='world',
physical=True,
radius=0.1,
local_transform=Transform.identity())
javascript
let shape = {
type:'Sphere',
name:'bouncy ball',
frame: 'world',
physical: true,
radius:0.1,
local_transform: {translation:[0.0,0.0,0.0],rotation:[1.0,0.0,0.0,0.0]}
}
Capsule
python
shape = CapsuleShape(
name="pill",
frame='world',
physical=True,
length=0.2,
radius=0.1,
local_transform=Transform.identity())
javascript
let shape = {
type:'Capsule',
name:'pill',
frame: 'world',
physical: true,
length:0.2,
radius:0.1,
local_transform: {translation:[0.0,0.0,0.0],rotation:[1.0,0.0,0.0,0.0]}
}
Cylinder
python
shape = CylinderShape(
name="zone",
frame='world',
physical=False,
length=0.2,
radius=0.1,
local_transform=Transform.identity())
javascript
let shape = {
type:'Cylinder',
name:'zone',
frame: 'world',
physical: false,
length:0.2,
radius:0.1,
local_transform: {translation:[0.0,0.0,0.0],rotation:[1.0,0.0,0.0,0.0]}
}
State
The State
object is the response back after calling solve
. It contains the state of the robot in terms of joint and frames, as well as some diagnostic information regarding proximity of various shapes and the center-of-mass of the robot.
Origin
The transform of the root of the robot. This is useful if the root node is movable. Exported as a Transform class (python) or object containing translation
and rotation
fields (javascript).
Joints
A lookup table of the joint values for each movable joint. Exported as a dictionary (python) or object (javascript).
Frames
A lookup table of the positions/orientations for each link. Exported as a dictionary (python) or object (javascript) of transform objects keyed by the link name.
Proximity
A list of all shapes that are currently tracked and that reach close enough proximity to potentially factor into collision detection. Exported as a ProximityInfo class (python) or object (javascript) with the following attributes:
-
shape1
(string
) The name of the first shape (note, if the robot is initialized with this shape, and it is attached to a robot link, the name is the link it is attached to.) -
shape2
(string
) The name of the second shape (note, if the robot is initialized with this shape, and it is attached to a robot link, the name is the link it is attached to.) -
distance
(float
/number
/None
/null
) The distance recorded between the two shapes. May possibly beNone
ornull
if not tracked, and is zero if the shapes are intersecting. -
points
(None
/set of two points
) The closest points on two different shapes that are used determined whether these two shapes are close though to cause a collision based on the distance between the points on these two shapes.points
will beNone
anddistance
will be0.0
if two shapes areinteresecting
and colliding.points
will return aset of two points
anddistance
will be greater than0.0
but smaller than1.0
if two shapes are close enough(smaller than 1.0) to potentially cause a collision but not yet colliding. Any distance between two points bigger than1.0
are not considered for collision detection. -
physical
(bool
) True if both shapes are physical, otherwise False. -
If the distance between points on two different shapes is
0.0
, two shapes areintersecting
with each other. -
If the distance between points on two different shapes is bigger than
0.0
but smaller than1.0
, two shapes arewith in margin
with each other.
Center of Mass
A translation (vector) indicating the current center of mass of the robot.
Contributing
Python Instructions
To build, download and cd
to this directory. Then run:
# If you just want to install:
python3 setup.py install
# Or if you are developing:
python3 setup.py develop
# If you are developing and need to rebuild:
python3 setup.py clean && python3 setup.py develop
You will need this installed to use the ROS2 LivelyIK Package.
Javascript Instructions
To build, download and cd
to this directory. Then run:
# Build the javascript bundle
wasm-pack build --scope people_and_robots --target web -- --features jsbindings
# Pack
wasm-pack pack
# Publish
wasm-pack publish --access=public
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Hashes for lively_tk-0.10.0-cp39-cp39-macosx_11_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 01c09824baf47abe316b68b6aae45a10790e41c12a5989c39929da55b674e34b |
|
MD5 | 95059a1350c60510e1ca625d91e0de28 |
|
BLAKE2b-256 | 1a946b19f649d52c0648ef29edd5bae0719b632c5d104000c9d95017593f6d25 |
Hashes for lively_tk-0.10.0-cp38-cp38-macosx_11_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 182349bb94bec4f25d8d74a9438298233f91b5d8d0608f86bae7fe32dee89290 |
|
MD5 | 808ed4cd1aaa9719c303786be384cc17 |
|
BLAKE2b-256 | 4216915160c9593d570a3820f83d6e14c7b369fb3656151e47b0738da7a2a762 |
Hashes for lively_tk-0.10.0-cp37-cp37m-macosx_11_0_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6cdf9f15c685d7243310b85aa087530f7b2ba8b66fee468da8184152dca69d9a |
|
MD5 | 1af72f7ab6e747f09cc46ff747668157 |
|
BLAKE2b-256 | f9936d6ec238220d57bdb86c1cd6bd813746ab764827570d85d54b368bfc89d1 |