Skip to content

Commit 958d7ae

Browse files
committed
add 3d model with standard wheels
1 parent dee2ed3 commit 958d7ae

1 file changed

Lines changed: 137 additions & 26 deletions

File tree

src/segway_3d.jl

Lines changed: 137 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,171 @@
11
using ModelingToolkit
22
using Multibody
33
import ModelingToolkit: t_nounits as t, D_nounits as D
4+
import ModelingToolkitStandardLibrary.Mechanical.Rotational
45
using OrdinaryDiffEq
56

6-
# A 3D model of a segway using RollingWheelSet
7+
# A 3D model of a segway using RollingWheelSet (does not allow tilting of body)
78

8-
@component function DyadBot3D(; name)
9+
# @component function DyadBot3D(; name)
10+
# pars = @parameters begin
11+
# wheel_radius = 0.04
12+
# body_mass = 0.1
13+
# body_height = 0.1
14+
# body_width = 0.13
15+
# body_depth = 0.07
16+
# end
17+
18+
# systems = @named begin
19+
# world = World()
20+
# wheels = RollingWheelSet(
21+
# radius = wheel_radius,
22+
# m_wheel = 0.05, # mass of one wheel
23+
# I_axis = 5e-5, # moment of inertia of one wheel around the rotation axis
24+
# I_long = 1e-5,
25+
# track = body_width, # distance between wheels
26+
# )
27+
# body = BodyShape(
28+
# m = body_mass,
29+
# I_22 = 0.01*0.03^2, # Inertia around vertical axis, a very rough approximation
30+
# I_11 = 0.01*0.05^2, # Total guesses
31+
# I_33 = 0.01*0.05^2,
32+
# r = [0.0, body_height, 0.0], # Vector from `frame_a` to `frame_b` (head) resolved in `frame_a`
33+
# height = body_depth, # we use the word "height" for the length of r
34+
# width = body_width,
35+
# )
36+
# end
37+
38+
# eqs = [
39+
# connect(wheels.frame_middle, body_offset.frame_a)
40+
# connect(body_offset.frame_b, body.frame_a)
41+
# ]
42+
43+
# System(eqs, t, [], pars; systems, name)
44+
# end
45+
46+
47+
# @named model = DyadBot3D()
48+
# model = complete(model)
49+
50+
# ssys = structural_simplify(multibody(model))
51+
52+
# prob = ODEProblem(ssys, [], (0.0, 5.0))
53+
54+
# sol = solve(prob, Rodas5P())
55+
56+
# ##
57+
# import GLMakie
58+
59+
60+
##
61+
62+
# ==============================================================================
63+
# DyadBot3DWheels - 3D segway using individual RollingWheel components
64+
# This allows the body to tilt forward/backward (unlike RollingWheelSet which
65+
# keeps wheels vertical)
66+
# ==============================================================================
67+
68+
@component function DyadBot3DWheels(; name)
69+
body_height = 0.1#, [description = "Height of body above wheel axle"]
70+
track = 0.13#, [description = "Distance between wheels"]
971
pars = @parameters begin
1072
wheel_radius = 0.04
1173
body_mass = 0.1
12-
body_height = 0.1
13-
body_width = 0.13
14-
body_depth = 0.07
74+
wheel_mass = 0.05
75+
wheel_I_axis = 5e-5
76+
wheel_I_long = 1e-5
77+
d_wheel = 0.1, [description = "Wheel rotational damping coefficient"]
1578
end
1679

1780
systems = @named begin
1881
world = World()
19-
wheels = RollingWheelSet(
82+
83+
# Two individual rolling wheels (allows tilting)
84+
wheel_left = SlippingWheel(
2085
radius = wheel_radius,
21-
m_wheel = 0.05, # mass of one wheel
22-
I_axis = 5e-5, # moment of inertia of one wheel around the rotation axis
23-
I_long = 1e-5,
24-
track = body_width, # distance between wheels
86+
m = wheel_mass,
87+
I_axis = wheel_I_axis,
88+
I_long = wheel_I_long,
89+
state = false,
2590
)
91+
wheel_right = SlippingWheel(
92+
radius = wheel_radius,
93+
m = wheel_mass,
94+
I_axis = wheel_I_axis,
95+
I_long = wheel_I_long,
96+
# iscut = true, # Avoid over-constraining
97+
state = true,
98+
)
99+
100+
# Revolute joints for wheel spin
101+
revolute_left = Revolute(n = [0, 0, 1], axisflange = true, phi0=0, w0=0)
102+
revolute_right = Revolute(n = [0, 0, 1], axisflange = true, phi0=0, w0=0)
103+
104+
# Axis connecting wheels
105+
rod_left = FixedTranslation(r = [0, 0, track/2])
106+
rod_right = FixedTranslation(r = [0, 0, -track/2])
107+
108+
# Axis body (small mass at center)
109+
axis_body = Body(m = 0.01, r_cm = [0, 0, 0])
110+
111+
# Main body extending upward
26112
body = BodyShape(
27113
m = body_mass,
28-
I_22 = 0.01*0.03^2, # Inertia around vertical axis, a very rough approximation
29-
I_11 = 0.01*0.05^2, # Total guesses
30-
I_33 = 0.01*0.05^2,
31-
r = [0.0, body_height, 0.0], # Vector from `frame_a` to `frame_b` (head) resolved in `frame_a`
32-
height = body_depth, # we use the word "height" for the length of r
33-
width = body_width,
34-
)
114+
I_22 = 0.01*0.03^2,
115+
I_11 = 0.01*0.05^2,
116+
I_33 = 0.01*0.05^2,
117+
r = [0, body_height, 0],
118+
)
119+
120+
# Rotational damping for wheel joints
121+
damper_left = Rotational.Damper(d = d_wheel)
122+
damper_right = Rotational.Damper(d = d_wheel)
35123
end
36124

37125
eqs = [
38-
connect(wheels.frame_middle, body_offset.frame_a)
39-
connect(body_offset.frame_b, body.frame_a)
126+
# Connect wheels to revolute joints
127+
connect(wheel_left.frame_a, revolute_left.frame_b)
128+
connect(wheel_right.frame_a, revolute_right.frame_b)
129+
130+
# Connect revolute joints to axis via rods
131+
connect(revolute_left.frame_a, rod_left.frame_b)
132+
connect(revolute_right.frame_a, rod_right.frame_b)
133+
134+
# Connect rods to axis center
135+
connect(rod_left.frame_a, axis_body.frame_a)
136+
connect(rod_right.frame_a, axis_body.frame_a)
137+
138+
# Connect body to axis center
139+
connect(axis_body.frame_a, body.frame_a)
140+
141+
# Connect dampers to wheel revolute joints
142+
connect(damper_left.flange_a, revolute_left.axis)
143+
connect(damper_left.flange_b, revolute_left.support)
144+
connect(damper_right.flange_a, revolute_right.axis)
145+
connect(damper_right.flange_b, revolute_right.support)
40146
]
41147

42148
System(eqs, t, [], pars; systems, name)
43149
end
44150

151+
##
45152

46-
@named model = DyadBot3D()
47-
model = complete(model)
153+
@named model_wheels = DyadBot3DWheels()
154+
model_wheels = complete(model_wheels)
48155

49-
ssys = structural_simplify(multibody(model))
156+
linsys = (; allow_symbolic = false, inline_linear_sccs = true, analytical_linear_scc_limit = 5, reassemble_alg = StructuralTransformations.DefaultReassembleAlgorithm(; inline_linear_sccs = true, analytical_linear_scc_limit = 5))
157+
ssys = structural_simplify(multibody(model_wheels); linsys...)
50158

51-
prob = ODEProblem(ssys, [], (0.0, 5.0))
52159

53-
sol = solve(prob, Rodas5P())
160+
x0 = [
161+
# collect(ssys.axis_body.Q̂) .=> [1, 0, 0, 0];
162+
]
54163

55-
##
56-
import GLMakie
164+
guesses = unknowns(ssys) .=> 0.0
165+
166+
prob = ODEProblem(ssys, x0, (0.0, 5.0); guesses)
57167

168+
sol_wheels = solve(prob, Rodas5P())
58169

59170
##
60171

0 commit comments

Comments
 (0)