Skip to content

Commit 69114b3

Browse files
committed
Merge branch 'main' of https://github.com/dojo-sim/Dojo.jl into main
2 parents 48cd557 + e261bdb commit 69114b3

File tree

10 files changed

+202
-58
lines changed

10 files changed

+202
-58
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ A differentiable simulator for robotics.
1212
### Atlas drop
1313
<img src="examples/animations/atlas_drop.gif" width="100"/>
1414

15+
### REx Hopper drop
16+
<img src="examples/animations/rexhopper.gif" width="200"/>
17+
1518
### Astronaut
1619
<img src="examples/animations/astronaut.gif" width="200"/>
1720

docs/src/assets/rexhopper.png

192 KB
Loading

docs/src/assets/rexhopper_contact.png

194 KB
Loading

docs/src/define_mechanism.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ The second method that we need to define is `initialize_...` where `...` is the
8181

8282
```julia
8383
function initialize_tippetop!(mechanism::Mechanism{T};
84-
x=zeros(3),
85-
θ=zeros(3),
86-
v=zeros(3),
87-
ω=zeros(3)) where T
84+
body_position=zeros(3),
85+
body_orientation=zeros(3),
86+
body_linear_velocity=zeros(3),
87+
body_angular_velocity=zeros(3)) where T
8888

8989
# we retrieve the joints from the mechanism by their names
9090
floating_joint = get_joint(mechanism, :floating_joint)
@@ -94,7 +94,8 @@ function initialize_tippetop!(mechanism::Mechanism{T};
9494
# we set all the bodies' velocities to zeros
9595
zero_velocity!(mechanism)
9696
# we set to minimal coordinates of the floating joint
97-
set_minimal_coordinates_velocities!(mechanism, floating_joint, xmin=[x; θ; v; ω])
97+
set_minimal_coordinates_velocities!(mechanism, floating_joint,
98+
xmin=[body_position; body_orientation; body_linear_velocity; body_angular_velocity])
9899
# we set to minimal coordinates of the fixed joint (this joint has zero minimal coordinate).
99100
set_minimal_coordinates_velocities!(mechanism, fixed_joint)
100101
return nothing

docs/src/load_mechanism.md

Lines changed: 133 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,133 @@
1-
# Loading Mechanism via URDF
1+
# Loading Mechanism via URDF
2+
Another way to build a mechanism is to directly load it from a URDF file. We illustrate this with the RExLab hopper.
3+
4+
```julia
5+
function get_rexhopper(;
6+
timestep=0.01,
7+
gravity=[0.0; 0.0; -9.81],
8+
friction_coefficient=1.0,
9+
contact_body=true,
10+
limits=true,
11+
model=:rexhopper,
12+
floating=true,
13+
contact_type=:nonlinear,
14+
spring=0.0,
15+
damper=1.0,
16+
T=Float64)
17+
18+
# we define the path of the URDF file
19+
path = joinpath(@__DIR__, "../deps/$(String(model)).urdf")
20+
# we load the URDF file into a Mechanism object
21+
mech = Mechanism(path, floating, T,
22+
gravity=gravity,
23+
timestep=timestep,
24+
spring=spring,
25+
damper=damper)
26+
return mech
27+
end
28+
```
29+
Here, we have created a mechanism, that contains all the bodies and the joint and also the meshes loaded from the path contained in the URDF file. This is the resulting robot;
30+
![rexhopper](./assets/rexhopper.png)
31+
32+
However, we are still missing the joint limits and the contact spheres. The following methods provides an example for adding joint limits and contact spheres. Our goal here was to best approximate the mesh shapes using as few spheres as possible.
33+
Parsing joint limits from the URDF to add them automatically to the mechanism should be easily feasible. That could be a great way to contribute and familiarize yourself with the code!
34+
35+
```julia
36+
function get_rexhopper(;
37+
timestep=0.01,
38+
gravity=[0.0; 0.0; -9.81],
39+
friction_coefficient=1.0,
40+
contact_body=true,
41+
limits=true,
42+
model=:rexhopper,
43+
floating=true,
44+
contact_type=:nonlinear,
45+
spring=0.0,
46+
damper=1.0,
47+
T=Float64)
48+
49+
# we define the path of the URDF file
50+
path = joinpath(@__DIR__, "../deps/$(String(model)).urdf")
51+
# we load the URDF file into a Mechanism object
52+
mech = Mechanism(path, floating, T,
53+
gravity=gravity,
54+
timestep=timestep,
55+
spring=spring,
56+
damper=damper)
57+
58+
# we add joint limits to the mechanism
59+
joints = deepcopy(mech.joints)
60+
if limits
61+
joint1 = get_joint(mech, :joint1)
62+
joint3 = get_joint(mech, :joint3)
63+
joints[joint1.id] = add_limits(mech, joint1,
64+
rot_limits=[SVector{1}(-0.7597), SVector{1}(1.8295)])
65+
joints[joint3.id] = add_limits(mech, joint3,
66+
rot_limits=[SVector{1}(-1.8295), SVector{1}(0.7597)])
67+
mech = Mechanism(Origin{T}(), [mech.bodies...], [joints...],
68+
gravity=gravity,
69+
timestep=timestep,
70+
spring=spring,
71+
damper=damper)
72+
end
73+
74+
# we attach spherical collisions zones to certain bodies
75+
if contact_body
76+
origin = Origin{T}()
77+
bodies = mech.bodies
78+
joints = mech.joints
79+
80+
normal = [0.0; 0.0; 1.0]
81+
contacts = []
82+
83+
link3 = get_body(mech, :link3)
84+
link2 = get_body(mech, :link2)
85+
foot_radius = 0.0203
86+
ankle_radius = 0.025
87+
base_radius = 0.125
88+
p = [0.1685; 0.0025; -0.0055]
89+
o = [0;0; foot_radius]
90+
push!(contacts, contact_constraint(link3, normal,
91+
friction_coefficient=friction_coefficient,
92+
contact_point=p,
93+
offset=o,
94+
contact_type=contact_type,
95+
name=:foot))
96+
p = [-0.10; -0.002; 0.01]
97+
o = [0;0; ankle_radius]
98+
push!(contacts, contact_constraint(link3, normal,
99+
friction_coefficient=friction_coefficient,
100+
contact_point=p,
101+
offset=o,
102+
contact_type=contact_type,
103+
name=:ankle3))
104+
p = [0.24; 0.007; 0.005]
105+
push!(contacts, contact_constraint(link2, normal,
106+
friction_coefficient=friction_coefficient,
107+
contact_point=p,
108+
offset=o,
109+
contact_type=contact_type,
110+
name=:ankle2))
111+
base_link = get_body(mech, :base_link)
112+
p = [0.0; 0.0; 0.0]
113+
o = [0;0; base_radius]
114+
push!(contacts, contact_constraint(base_link, normal,
115+
friction_coefficient=friction_coefficient,
116+
contact_point=p,
117+
offset=o,
118+
contact_type=contact_type,
119+
name=:torso))
120+
121+
set_minimal_coordinates!(mech, get_joint(mech, :auto_generated_floating_joint), [0,0,1.0, 0,0,0])
122+
mech = Mechanism(origin, bodies, joints, [contacts...],
123+
gravity=gravity,
124+
timestep=timestep,
125+
spring=spring,
126+
damper=damper)
127+
end
128+
return mech
129+
end
130+
```
131+
132+
This is the result, we added three spherical contacts to the robot. There is one coverinn the torso one covering the knee and one covering the foot, they are shown in red;
133+
![rexhopper_contact](./assets/rexhopper_contact.png)

environments/rexhopper/methods/initialize.jl

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
function get_rexhopper(;
2-
timestep=0.01,
3-
gravity=[0.0; 0.0; -9.81],
1+
function get_rexhopper(;
2+
timestep=0.01,
3+
gravity=[0.0; 0.0; -9.81],
44
friction_coefficient=1.0,
55
contact_foot=true,
66
contact_body=true,
@@ -13,10 +13,10 @@ function get_rexhopper(;
1313
T=Float64)
1414

1515
path = joinpath(@__DIR__, "../deps/$(String(model)).urdf")
16-
mech = Mechanism(path, floating, T,
17-
gravity=gravity,
18-
timestep=timestep,
19-
spring=spring,
16+
mech = Mechanism(path, floating, T,
17+
gravity=gravity,
18+
timestep=timestep,
19+
spring=spring,
2020
damper=damper)
2121

2222
# joint limits
@@ -25,14 +25,14 @@ function get_rexhopper(;
2525
if limits
2626
joint1 = get_joint(mech, :joint1)
2727
joint3 = get_joint(mech, :joint3)
28-
joints[joint1.id] = add_limits(mech, joint1,
28+
joints[joint1.id] = add_limits(mech, joint1,
2929
rot_limits=[SVector{1}(-0.7597), SVector{1}(1.8295)])
30-
joints[joint3.id] = add_limits(mech, joint3,
30+
joints[joint3.id] = add_limits(mech, joint3,
3131
rot_limits=[SVector{1}(-1.8295), SVector{1}(0.7597)])
32-
mech = Mechanism(Origin{T}(), [mech.bodies...], [joints...],
33-
gravity=gravity,
34-
timestep=timestep,
35-
spring=spring,
32+
mech = Mechanism(Origin{T}(), [mech.bodies...], [joints...],
33+
gravity=gravity,
34+
timestep=timestep,
35+
spring=spring,
3636
damper=damper)
3737
end
3838

@@ -48,54 +48,61 @@ function get_rexhopper(;
4848
link2 = get_body(mech, :link2)
4949
foot_radius = 0.0203
5050
ankle_radius = 0.025
51-
base_radius = 0.125
51+
base_radius = 0.14
5252
p = [0.1685; 0.0025; -0.0055]
5353
o = [0;0; foot_radius]
54-
push!(models, contact_constraint(link3, normal,
54+
push!(models, contact_constraint(link3, normal,
5555
friction_coefficient=friction_coefficient,
56-
contact_point=p,
57-
offset=o,
58-
contact_type=contact_type,
56+
contact_point=p,
57+
offset=o,
58+
contact_type=contact_type,
5959
name=:foot))
6060
p = [-0.10; -0.002; 0.01]
6161
o = [0;0; ankle_radius]
62-
push!(models, contact_constraint(link3, normal,
62+
push!(models, contact_constraint(link3, normal,
6363
friction_coefficient=friction_coefficient,
64-
contact_point=p,
65-
offset=o,
66-
contact_type=contact_type,
64+
contact_point=p,
65+
offset=o,
66+
contact_type=contact_type,
6767
name=:ankle3))
6868
p = [0.24; 0.007; 0.005]
69-
push!(models, contact_constraint(link2, normal,
69+
push!(models, contact_constraint(link2, normal,
7070
friction_coefficient=friction_coefficient,
71-
contact_point=p,
72-
offset=o,
73-
contact_type=contact_type,
71+
contact_point=p,
72+
offset=o,
73+
contact_type=contact_type,
7474
name=:ankle2))
7575
base_link = get_body(mech, :base_link)
76-
p = [0.0; 0.0; 0.0]
76+
pl = [0.0; +0.075; 0.03]
77+
pr = [0.0; -0.075; 0.03]
7778
o = [0;0; base_radius]
78-
push!(models, contact_constraint(base_link, normal,
79+
push!(models, contact_constraint(base_link, normal,
7980
friction_coefficient=friction_coefficient,
80-
contact_point=p,
81-
offset=o,
82-
contact_type=contact_type,
83-
name=:torso))
81+
contact_point=pl,
82+
offset=o,
83+
contact_type=contact_type,
84+
name=:torso_left))
85+
push!(models, contact_constraint(base_link, normal,
86+
friction_coefficient=friction_coefficient,
87+
contact_point=pr,
88+
offset=o,
89+
contact_type=contact_type,
90+
name=:torso_right))
8491

8592
set_minimal_coordinates!(mech, get_joint(mech, :auto_generated_floating_joint), [0,0,1.0, 0,0,0])
86-
mech = Mechanism(origin, bodies, joints, [models...],
87-
gravity=gravity,
88-
timestep=timestep,
89-
spring=spring,
93+
mech = Mechanism(origin, bodies, joints, [models...],
94+
gravity=gravity,
95+
timestep=timestep,
96+
spring=spring,
9097
damper=damper)
9198
end
9299
return mech
93100
end
94101

95-
function initialize_rexhopper!(mechanism::Mechanism{T};
96-
body_position=zeros(3),
97-
body_orientation=zeros(3),
98-
body_linear_velocity=zeros(3),
102+
function initialize_rexhopper!(mechanism::Mechanism{T};
103+
body_position=zeros(3),
104+
body_orientation=zeros(3),
105+
body_linear_velocity=zeros(3),
99106
body_angular_velocity=zeros(3)) where T
100107

101108
zero_velocity!(mechanism)
@@ -104,7 +111,7 @@ function initialize_rexhopper!(mechanism::Mechanism{T};
104111
for joint in mechanism.joints
105112
!(joint.name in (:loop_joint, :floating_joint)) && set_minimal_coordinates!(mechanism, joint, zeros(input_dimension(joint)))
106113
end
107-
114+
108115
set_minimal_coordinates!(mechanism, get_joint(mechanism,
109116
:auto_generated_floating_joint), [body_position; body_orientation])
110117
set_minimal_velocities!(mechanism, get_joint(mechanism,

environments/tippetop/methods/initialize.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,18 @@ function get_tippetop(;
5252
end
5353

5454
function initialize_tippetop!(mechanism::Mechanism{T};
55-
x=zeros(3),
56-
θ=zeros(3),
57-
v=zeros(3),
58-
ω=zeros(3)) where T
55+
body_position=zeros(3),
56+
body_orientation=zeros(3),
57+
body_linear_velocity=zeros(3),
58+
body_angular_velocity=zeros(3)) where T
5959

6060
floating_joint = get_joint(mechanism, :floating_joint)
6161
fixed_joint = get_joint(mechanism, :fixed_joint)
6262
radius = fixed_joint.translational.vertices[1][3]
6363

6464
zero_velocity!(mechanism)
65-
set_minimal_coordinates_velocities!(mechanism, floating_joint, xmin=[x; θ; v; ω])
65+
set_minimal_coordinates_velocities!(mechanism, floating_joint,
66+
xmin=[body_position; body_orientation; body_linear_velocity; body_angular_velocity])
6667
set_minimal_coordinates_velocities!(mechanism, fixed_joint)
6768
return nothing
6869
end

examples/animations/rexhopper.gif

1000 KB
Loading

examples/animations/rexhopper.mp4

266 KB
Binary file not shown.

examples/dev/rexhopper.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using Dojo
22

33
# Open visualizer
4-
vis=visualizer()
4+
vis = Visualizer()
55
open(vis)
66
# render(vis)
77

@@ -11,15 +11,15 @@ include(joinpath(module_dir(), "environments/rexhopper/methods/initialize.jl"))
1111
# Mechanism
1212
mechanism = get_rexhopper(model=:rexhopper_fixed, timestep=0.05, gravity=-9.81,
1313
contact_body=true, friction_coefficient=1.0)
14-
env = get_environment("rexhopper",
15-
timestep=0.05, gravity=-9.81, contact_body=true, friction_coefficient=1.0)
14+
# env = get_environment("rexhopper",
15+
# timestep=0.05, gravity=-9.81, contact_body=true, friction_coefficient=1.0)
1616

1717
# Simulate
18-
initialize!(env.mechanism, :rexhopper, x=[0.0; 0.0; 0.4])
18+
initialize!(mechanism, :rexhopper, body_position=[0.0; 0.0; 0.1], body_orientation=[0.1, 0.9, 0.0])
1919

2020
# Open visualizer
21-
storage = simulate!(mechanism, 2.5, record=true, opts=SolverOptions(undercut=10.0,
21+
storage = simulate!(mechanism, 1.5, record=true, opts=SolverOptions(undercut=10.0,
2222
btol=1.0e-4, rtol=1.0e-4, verbose=false));
2323

2424
# Visualize
25-
visualize(mechanism, storage, vis=vis, show_contact=false);
25+
visualize(mechanism, storage, vis=vis, show_contact=true, build=true);

0 commit comments

Comments
 (0)