Skip to content

Commit ca55aca

Browse files
committed
Merge branch 'main' of https://github.com/dojo-sim/Dojo.jl into main
2 parents 811d0aa + fa22624 commit ca55aca

File tree

10 files changed

+197
-111
lines changed

10 files changed

+197
-111
lines changed

docs/src/assets/logo.png

27.1 KB
Loading

docs/src/assets/tippetop_real.gif

1.6 MB
Loading

docs/src/define_mechanism.md

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,102 @@
1-
# Defining a Mechanism
1+
# Defining a Mechanism
2+
Here, we describe how to define your own dynamical system of [`Mechanism`](@ref). After it has been defined, it will be extremely easy to simulate it, control it, perform trajectory optimization on it, or even policy optimization.
3+
4+
We're going to build a tippe top,
5+
6+
7+
```@raw html
8+
<img src="./assets/tippetop_real.gif" width="300"/>
9+
```
10+
11+
```@raw html
12+
<img src="./../../examples/animations/tippetop.gif" width="300"/>
13+
```
14+
15+
### Build Mechanism
16+
17+
To do this, we need to define two methods. The first one is named `get_...` where `...` is the name of the mechanism. So here we define `get_tippetop`. This function return a [`Mechanism`](@ref) and takes as input a variety of parameters like the simulation time step, gravity etc. You can add as many parameters you want. This example is typical of what you will find in Dojo.
18+
19+
To build the mechanism corresponding to the tippe top, we decompose it into two spherical bodies. Each body has its own spherical contact constraint with the floor. The joint between the two bodies is a `fixed_joint` and the joint between the main body and the [`Origin`](@ref) of the frame is a floating joint.
20+
21+
```julia
22+
function get_tippetop(;
23+
timestep=0.01,
24+
gravity=[0.0; 0.0; -9.81],
25+
friction_coefficient=0.4,
26+
contact_type=:nonlinear,
27+
T=Float64)
28+
29+
# define origin
30+
origin = Origin{T}(name=:origin)
31+
# define the two bodies which will form the tippe top once assembled
32+
radius = 0.5
33+
mass = 1.0
34+
α = 0.2
35+
bodies = [
36+
Sphere(radius, mass, name=:sphere1, color=gray_light),
37+
Sphere(radius*α, mass*α^3, name=:sphere2, color=gray_light)]
38+
# modify inertia of the first body to ensure we obtain the desired behavior
39+
bodies[1].inertia = Diagonal([1.9, 2.1, 2.0])
40+
41+
# define the joints, the 1st joint is between Origin and :sphere1
42+
# the 2nd joint is between :sphere1 and :sphere2
43+
joints = [
44+
JointConstraint(Floating(origin, bodies[1]),
45+
name=:floating_joint),
46+
JointConstraint(Fixed(bodies[1], bodies[2],
47+
parent_vertex=[0,0,radius],
48+
child_vertex=zeros(3)),
49+
name = :fixed_joint)]
50+
51+
# define the two spherical contacts, each contact is attached to a body.
52+
contact_point = [0.0, 0.0, 0.0] # both contact spheres are located at the center of the bodies they are attached to.
53+
normal = [0.0, 0.0, 1.0] # the normal of the contact is always pointing in the upright direction because the floor is flat.
54+
# we specify the type of contact (impact, linear, nonlinear), the coefficient of friction, the radius of the contact sphere, etc.
55+
contacts = [
56+
contact_constraint(get_body(mechanism, :sphere1), normal,
57+
friction_coefficient=friction_coefficient,
58+
contact_point=contact_point, offset=[0.0, 0.0, radius],
59+
contact_type=contact_type),
60+
contact_constraint(get_body(mechanism, :sphere2), normal,
61+
friction_coefficient=friction_coefficient,
62+
contact_point=contact_point,
63+
offset=[0.0, 0.0, radius * α],
64+
contact_type=contact_type)
65+
]
66+
67+
# we build the mechanism by combining together the the origin, the bodies, the joints, and the contacts.
68+
mechanism = Mechanism(origin, bodies, joints, contacts,
69+
gravity=gravity,
70+
timestep=timestep)
71+
72+
# we make sure that the mechanism is never initialized with its contact spheres below the ground.
73+
set_minimal_coordinates!(mechanism, get_joint(mechanism, :floating_joint), [0.0; 0.0; radius; zeros(3)])
74+
return mechanism
75+
end
76+
```
77+
78+
### Initialize Mechanism
79+
The second method that we need to define is `initialize_...` where `...` is the name of the mechanism. So here we define `initialize_tippetop`. This function initialize the dynamical system to a certain state. This means that we set the position orientation, linear and angular velocity of each body in the mechanism.
80+
81+
82+
```julia
83+
function initialize_tippetop!(mechanism::Mechanism{T};
84+
x=zeros(3),
85+
θ=zeros(3),
86+
v=zeros(3),
87+
ω=zeros(3)) where T
88+
89+
# we retrieve the joints from the mechanism by their names
90+
floating_joint = get_joint(mechanism, :floating_joint)
91+
fixed_joint = get_joint(mechanism, :fixed_joint)
92+
radius = fixed_joint.translational.vertices[1][3]
93+
94+
# we set all the bodies' velocities to zeros
95+
zero_velocity!(mechanism)
96+
# we set to minimal coordinates of the floating joint
97+
set_minimal_coordinates_velocities!(mechanism, floating_joint, xmin=[x; θ; v; ω])
98+
# we set to minimal coordinates of the fixed joint (this joint has zero minimal coordinate).
99+
set_minimal_coordinates_velocities!(mechanism, fixed_joint)
100+
return nothing
101+
end
102+
```

environments/snake/methods/initialize.jl

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,39 @@
1-
function get_snake(;
2-
timestep=0.01,
3-
gravity=[0.0; 0.0; -9.81],
4-
friction_coefficient=0.8,
1+
function get_snake(;
2+
timestep=0.01,
3+
gravity=[0.0; 0.0; -9.81],
4+
friction_coefficient=0.8,
55
contact=true,
6-
contact_type=:nonlinear,
7-
spring=0.0,
8-
damper=0.0,
6+
contact_type=:nonlinear,
7+
spring=0.0,
8+
damper=0.0,
99
num_bodies=2,
10-
joint_type=:Spherical,
11-
height=1.0,
10+
joint_type=:Spherical,
11+
length=1.0,
1212
radius=0.05,
1313
T=Float64)
1414

1515
# Parameters
16-
ex = [1.0; 0.0; 0.0]
17-
ey = [0.0; 1.0; 0.0]
18-
ez = [0.0; 0.0; 1.0]
16+
ex = [1.0; 0.0; 0.0]
17+
ey = [0.0; 1.0; 0.0]
18+
ez = [0.0; 0.0; 1.0]
1919

20-
vert11 = [0.0; 0.0; height / 2.0]
20+
vert11 = [0.0; 0.0; length / 2.0]
2121
vert12 = -vert11
2222

2323
# Links
2424
origin = Origin{T}()
25-
bodies = [Box(3 * radius, 2 * radius, height, height, color=RGBA(1.0, 0.0, 0.0)) for i = 1:num_bodies]
25+
bodies = [Box(3 * radius, 2 * radius, length, length, color=RGBA(0.9, 0.9, 0.9)) for i = 1:num_bodies]
2626

2727
# Constraints
28-
jointb1 = JointConstraint(Floating(origin, bodies[1],
29-
spring=0.0,
28+
jointb1 = JointConstraint(Floating(origin, bodies[1],
29+
spring=0.0,
3030
damper=0.0))
3131

3232
if num_bodies > 1
33-
joints = [JointConstraint(Prototype(joint_type, bodies[i - 1], bodies[i], ex;
34-
parent_vertex=vert12,
35-
child_vertex=vert11,
36-
spring=spring,
33+
joints = [JointConstraint(Prototype(joint_type, bodies[i - 1], bodies[i], ex;
34+
parent_vertex=vert12,
35+
child_vertex=vert11,
36+
spring=spring,
3737
damper=damper)) for i = 2:num_bodies]
3838
joints = [jointb1; joints]
3939
else
@@ -45,35 +45,35 @@ function get_snake(;
4545
normal = [[0.0; 0.0; 1.0] for i = 1:n]
4646
friction_coefficient = friction_coefficient * ones(n)
4747

48-
contacts1 = contact_constraint(bodies, normal,
49-
friction_coefficient=friction_coefficient,
50-
contact_points=fill(vert11, n),
48+
contacts1 = contact_constraint(bodies, normal,
49+
friction_coefficient=friction_coefficient,
50+
contact_points=fill(vert11, n),
5151
contact_type=contact_type) # we need to duplicate point for prismatic joint for instance
52-
contacts2 = contact_constraint(bodies, normal,
53-
friction_coefficient=friction_coefficient,
54-
contact_points=fill(vert12, n),
52+
contacts2 = contact_constraint(bodies, normal,
53+
friction_coefficient=friction_coefficient,
54+
contact_points=fill(vert12, n),
5555
contact_type=contact_type)
56-
mech = Mechanism(origin, bodies, joints, [contacts1; contacts2],
57-
gravity=gravity,
58-
timestep=timestep,
59-
spring=spring,
56+
mech = Mechanism(origin, bodies, joints, [contacts1; contacts2],
57+
gravity=gravity,
58+
timestep=timestep,
59+
spring=spring,
6060
damper=damper)
6161
else
62-
mech = Mechanism(origin, bodies, joints,
63-
gravity=gravity,
64-
timestep=timestep,
65-
spring=spring,
62+
mech = Mechanism(origin, bodies, joints,
63+
gravity=gravity,
64+
timestep=timestep,
65+
spring=spring,
6666
damper=damper)
6767
end
6868
return mech
6969
end
7070

71-
function initialize_snake!(mechanism::Mechanism{T};
71+
function initialize_snake!(mechanism::Mechanism{T};
7272
base_position=[0.0, -0.5, 0.0],
7373
base_orientation=UnitQuaternion(RotX(0.6 * π)),
74-
base_linear_velocity=zeros(3),
74+
base_linear_velocity=zeros(3),
7575
base_angular_velocity=zeros(3),
76-
relative_linear_velocity=zeros(3),
76+
relative_linear_velocity=zeros(3),
7777
relative_angular_velocity=zeros(3)) where T
7878

7979
pbody = mechanism.bodies[1]
@@ -82,22 +82,22 @@ function initialize_snake!(mechanism::Mechanism{T};
8282
vert12 = -vert11
8383

8484
# set position and velocities
85-
set_maximal_configurations!(mechanism.origin, pbody,
86-
child_vertex=base_position,
85+
set_maximal_configurations!(mechanism.origin, pbody,
86+
child_vertex=base_position,
8787
Δq=base_orientation)
88-
set_maximal_velocities!(pbody,
89-
v=base_linear_velocity,
88+
set_maximal_velocities!(pbody,
89+
v=base_linear_velocity,
9090
ω=base_angular_velocity)
9191

9292
previd = pbody.id
9393
for body in mechanism.bodies[2:end]
94-
set_maximal_configurations!(get_body(mechanism, previd), body,
95-
parent_vertex=vert12,
94+
set_maximal_configurations!(get_body(mechanism, previd), body,
95+
parent_vertex=vert12,
9696
child_vertex=vert11)
97-
set_maximal_velocities!(get_body(mechanism, previd), body,
98-
parent_vertex=vert12,
97+
set_maximal_velocities!(get_body(mechanism, previd), body,
98+
parent_vertex=vert12,
9999
child_vertex=vert11,
100-
Δv=relative_linear_velocity,
100+
Δv=relative_linear_velocity,
101101
Δω=relative_angular_velocity)
102102
previd = body.id
103103
end
Lines changed: 32 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,68 @@
1-
function get_tippetop(;
2-
timestep=0.01,
3-
gravity=[0.0; 0.0; -9.81],
4-
friction_coefficient=0.8,
5-
contact=true,
1+
function get_tippetop(;
2+
timestep=0.01,
3+
gravity=[0.0; 0.0; -9.81],
4+
friction_coefficient=0.4,
5+
contact=true,
66
contact_type=:nonlinear,
77
T=Float64)
88

99
origin = Origin{T}(name=:origin)
1010
radius = 0.5
1111
mass = 1.0
1212
α = 0.2
13-
bodies = [Sphere(radius, mass, name=:sphere1, color=cyan), Sphere(radius*α, mass*α, name=:sphere2, color=cyan)]
14-
joints = [JointConstraint(Floating(origin, bodies[1]),
13+
bodies = [
14+
Sphere(radius, mass, name=:sphere1, color=gray_light),
15+
Sphere(radius*α, mass*α^3, name=:sphere2, color=gray_light)]
16+
17+
joints = [
18+
JointConstraint(Floating(origin, bodies[1]),
1519
name=:floating_joint),
16-
JointConstraint(Fixed(bodies[1], bodies[2],
17-
parent_vertex=[0,0,radius],
18-
child_vertex=zeros(3)), name = :fixed_joint),]
20+
JointConstraint(Fixed(bodies[1], bodies[2],
21+
parent_vertex=[0,0,radius],
22+
child_vertex=zeros(3)),
23+
name = :fixed_joint)]
1924
mechanism = Mechanism(origin, bodies, joints,
20-
timestep=timestep,
25+
timestep=timestep,
2126
gravity=gravity)
2227

2328
# modify inertias
2429
mechanism.bodies[1].inertia = Diagonal([1.9, 2.1, 2.0])
2530

2631
if contact
27-
contact = [0.0, 0.0, 0.0]
32+
contact_point = [0.0, 0.0, 0.0]
2833
normal = [0.0, 0.0, 1.0]
2934
contacts = [
30-
contact_constraint(get_body(mechanism, :sphere1), normal,
31-
friction_coefficient=friction_coefficient,
32-
contact_point=contact, offset=[0.0, 0.0, radius],
35+
contact_constraint(get_body(mechanism, :sphere1), normal,
36+
friction_coefficient=friction_coefficient,
37+
contact_point=contact_point, offset=[0.0, 0.0, radius],
3338
contact_type=contact_type),
34-
contact_constraint(get_body(mechanism, :sphere2), normal,
35-
friction_coefficient=friction_coefficient,
36-
contact_point=contact,
37-
offset=[0.0, 0.0, radius * α],
39+
contact_constraint(get_body(mechanism, :sphere2), normal,
40+
friction_coefficient=friction_coefficient,
41+
contact_point=contact_point,
42+
offset=[0.0, 0.0, radius * α],
3843
contact_type=contact_type)
3944
]
4045
set_minimal_coordinates!(mechanism, get_joint(mechanism, :floating_joint), [0.0; 0.0; radius; zeros(3)])
4146
mechanism = Mechanism(origin, bodies, joints, contacts,
42-
gravity=gravity,
47+
gravity=gravity,
4348
timestep=timestep)
4449
end
4550

4651
return mechanism
4752
end
4853

49-
function initialize_tippetop!(mechanism::Mechanism{T};
54+
function initialize_tippetop!(mechanism::Mechanism{T};
5055
x=zeros(3),
51-
q=one(UnitQuaternion),
56+
θ=zeros(3),
5257
v=zeros(3),
5358
ω=zeros(3)) where T
5459

55-
joint2 = get_joint(mechanism, :fixed_joint)
56-
radius = joint2.constraints[1].vertices[1][3]
57-
origin = mechanism.origin
58-
pbody = get_body(mech, :sphere1)
59-
cbody = get_body(mech, :sphere2)
60+
floating_joint = get_joint(mechanism, :floating_joint)
61+
fixed_joint = get_joint(mechanism, :fixed_joint)
62+
radius = fixed_joint.translational.vertices[1][3]
6063

6164
zero_velocity!(mechanism)
62-
63-
set_maximal_configurations!(origin, pbody;
64-
parent_vertex=[0.0; 0.0; radius],
65-
child_vertex=[0.0; 0.0; 0.0],
66-
Δx=x,
67-
Δq=q)
68-
set_maximal_configurations!(pbody, cbody;
69-
parent_vertex=[0.0; 0.0; radius],
70-
child_vertex=[0.0; 0.0; 0.0],
71-
Δx=[0.0; 0.0; 0.0],
72-
Δq=one(UnitQuaternion))
73-
set_maximal_velocities!(origin, pbody;
74-
parent_vertex=[0.0; 0.0; radius],
75-
child_vertex=[0.0; 0.0; 0.0],
76-
Δv=v,
77-
Δω=ω)
78-
set_maximal_velocities!(pbody, cbody;
79-
parent_vertex=[0.0; 0.0; radius],
80-
child_vertex=[0.0; 0.0; 0.0],
81-
Δv=[0.0; 0.0; 0.0],
82-
Δω=[0.0; 0.0; 0.0])
65+
set_minimal_coordinates_velocities!(mechanism, floating_joint, xmin=[x; θ; v; ω])
66+
set_minimal_coordinates_velocities!(mechanism, fixed_joint)
8367
return nothing
8468
end

examples/animations/tippetop.gif

4.05 MB
Loading

examples/animations/tippetop.mp4

133 KB
Binary file not shown.

0 commit comments

Comments
 (0)