(*By Nasser M. Abbasi. 6/28/2014*)
Manipulate[
(*by Nasser M. Abbasi, 6/28/148*)
tick;
Module[{mass = m*h*Pi r^2, eq1, eq2, eq3, r2, angle, t, to, Ix, Iy, Iz, thetax, thetay, thetaz, sol, g, debug = False, lengthOfw},
Iz = (1/2) mass r^2;
Iy = (1/4) mass r^2 + 1/12 mass h^2;
Ix = Iy;
If[state == "RESET",
currentThetax = 0;
currentThetay = 0;
currentThetaz = 0;
Which[
spin == "X-axes", currentThetaDotx = initialSpinRate*2*Pi/60; currentThetaDoty = 0; currentThetaDotz = 0,
spin == "Y-axes", currentThetaDoty = initialSpinRate*2*Pi/60; currentThetaDotx = 0; currentThetaDotz = 0,
spin == "Z-axes", currentThetaDotz = initialSpinRate*2*Pi/60; currentThetaDoty = 0; currentThetaDotx = 0
]
];
(*Euler equations for 3D, zero torque*)
eq1 = Ix *thetax''[t] + (Iz - Iy)*thetay'[t] thetaz'[t] == 0;
eq2 = Iy *thetay''[t] + (Ix - Iz)*thetaz'[t] thetax'[t] == 0;
eq3 = Iz *thetaz''[t] + (Iy - Ix)*thetay'[t] thetax'[t] == 0;
sol = First@NDSolve[{eq1, eq2, eq3,
thetax[0] == currentThetax,
thetay[0] == currentThetay,
thetaz[0] == currentThetaz,
thetax'[0] == currentThetaDotx,
thetay'[0] == currentThetaDoty,
thetaz'[0] == currentThetaDotz}, {thetax, thetay, thetaz, thetax', thetay', thetaz'}, {t, 0, delT}];
thetax = thetax /. sol;
thetay = thetay /. sol;
thetaz = thetaz /. sol;
lengthOfw = Norm[{currentThetaDotx, currentThetaDoty, currentThetaDotz}];
If[lengthOfw <= $MachineEpsilon, lengthOfw = 1];
r2 = Which[
spin == "X-axes",
angle = (Dot[{1, 0, 0}, {currentThetaDotx, currentThetaDoty, currentThetaDotz}])/lengthOfw;
to = {angle, 0, 0};
r2 = lengthOfw*Sin[ArcCos[ angle]],
spin == "Y-axes",
angle = (Dot[{0, 1, 0}, {currentThetaDotx, currentThetaDoty, currentThetaDotz}])/lengthOfw;
to = {0, angle, 0};
r2 = lengthOfw*Sin[ArcCos[ angle]],
spin == "Z-axes",
angle = (Dot[{0, 0, 1}, {currentThetaDotx, currentThetaDoty, currentThetaDotz}])/lengthOfw;
to = {0, 0, angle};
r2 = lengthOfw*Sin[ArcCos[ angle]]
];
g = Grid[{
{Grid[{
{"time (sec)", "Ix", "Iy", "Iz", "body cone radius"},
{padIt2[currentTime, {5, 2}],
padIt2[Ix, {4, 3}],
padIt2[Iy, {4, 3}],
padIt2[Iz, {4, 3}],
padIt2[r, {3, 2}]
}
}, Alignment -> Center, Frame -> All, Spacings -> {.5, .7}]
}
,
{Grid[{
{"\[Theta]x(deg)", "\[Theta]y(deg)", "\[Theta]z(deg)", "\[Theta]x'(rpm)", "\[Theta]'y(rpm)", "\[Theta]'z(rpm)"},
{
padIt2[N@Mod[currentThetax*180/Pi, 360], {4, 1}],
padIt2[N@Mod[currentThetay*180/Pi, 360], {4, 1}],
padIt2[N@Mod[currentThetaz*180/Pi, 360], {4, 1}],
padIt1[N[currentThetaDotx/(2*Pi)] *60, {4, 2}],(*RPM*)
padIt1[N[currentThetaDoty/(2*Pi)]*60, {4, 2}],
padIt1[N[currentThetaDotz/(2*Pi) ]*60, {4, 2}]
}
}, Alignment -> Center, Frame -> All, Spacings -> {.5, .7}
]
},
{Framed@
Graphics3D[
Rotate[GraphicsGroup[Rotate[GraphicsGroup[Rotate[GraphicsGroup
[{
If[showAxes,
{
{Red, Arrowheads[Medium], Arrow[{{0, 0, 0}, {.7, 0, 0}}]},
Inset[Graphics[
Text[Style["x", Red, 14]]
], {0.75, 0, 0}],
{Red, Arrowheads[Medium], Arrow[{{0, 0, 0}, {0, .7, 0}}]},
Inset[Graphics[
Text[Style["y", Red, 14]]
], {0, 0.75, 0}],
{Red, Arrowheads[Medium], Arrow[{{0, 0, 0}, {0, 0, .7}}]},
Inset[Graphics[
Text[Style["z", Red, 14]]
], {0, 0, 0.75}]
}
],
{Opacity[op], Cylinder[{{0, 0, -h/2}, {0, 0, h/2}}, r]},
Sphere[{0, 0, 0}, .02],
If[showW,
{Blue, Arrow[{{0, 0, 0}, {currentThetaDotx, currentThetaDoty, currentThetaDotz}/lengthOfw}]}
],
If[showCone,
{EdgeForm[Red], Opacity[.1], Cone[{to, {0, 0, 0}}, r2]}
]
}], thetax[0], {1, 0, 0}
]
], thetay[0], {0, 1, 0}]
], thetaz[0], {0, 0, 1}
],
Axes -> False, AxesLabel -> {"x", "y", "z"}, PlotRange -> {{-1.1, 1.1}, {-1.1, 1.1}, {-1.1, 1.1}},
SphericalRegion -> True, Boxed -> False, ImagePadding -> 2, ImageSize -> 350
]
}
}
];
currentThetax = thetax[delT];
currentThetay = thetay[delT];
currentThetaz = thetaz[delT];
currentThetaDotx = (thetax' /. sol)[delT];
currentThetaDoty = (thetay' /. sol)[delT];
currentThetaDotz = (thetaz' /. sol)[delT];
If[debug, Print["currentThetax=", currentThetax]];
If[debug, Print["currentThetay=", currentThetay]];
If[debug, Print["currentThetaz=", currentThetaz]];
Which[state == "RUN",
currentTime += delT;
If[currentTime >= 1000, currentTime = 0];
tick = Not[tick]
];
If[Abs[currentThetaDotx] > 10 || Abs[currentThetaDoty] > 10 || Abs[currentThetaDotz] > 10,
state = "STOP"
];
g
],
Grid[{
{
Grid[{
{"radius", Manipulator[Dynamic[r, {r = #, tick = Not[tick]} &], {.1, .5, .1}, ImageSize -> Small], Dynamic[padIt2[r, {2, 1}]]},
{"height", Manipulator[Dynamic[h, {h = #, tick = Not[tick]} &], {.1, 1, .1}, ImageSize -> Small], Dynamic[padIt2[h, {2, 1}]]},
{"density", Manipulator[Dynamic[m, {m = #, tick = Not[tick]} &], {.1, 50, .1}, ImageSize -> Small], Dynamic[padIt2[m, {3, 1}]]}
}, Frame -> True, FrameStyle -> Gray
]
},
(*
{
Row[{"Initial angular positions"}]
},
{
Grid[{
{"\[Theta]x(0)",Manipulator[Dynamic[\[Theta]x,{\[Theta]x=#;currentThetax=\[Theta]x*Pi/180;tick=Not[tick]}&],{-15,15,1},
ImageSize\[Rule]Small],Dynamic[padIt1[\[Theta]x,2]]},
{"\[Theta]y(0)",Manipulator[Dynamic[\[Theta]y,{\[Theta]y=#;currentThetay=\[Theta]y*Pi/180;tick=Not[tick]}&],{-15,15,1},
ImageSize\[Rule]Small],Dynamic[padIt1[\[Theta]y,2]]},
{"\[Theta]z(0)",Manipulator[Dynamic[\[Theta]z,{\[Theta]z=#;currentThetaz=\[Theta]z*Pi/180;tick=Not[tick]}&],{-15,15,1},
ImageSize\[Rule]Small],Dynamic[padIt1[\[Theta]z,2]]}
},Frame\[Rule]True]
},
*)
{
Grid[{
{Style["select spin axes", 12],
PopupMenu[Dynamic[spin, {spin = #;
Which[
spin == "X-axes", currentThetaDotx = initialSpinRate*2*Pi/60; currentThetaDoty = 0; currentThetaDotz = 0;
currentThetax = 0; currentThetay = 0; currentThetaz = 0,
spin == "Y-axes", currentThetaDoty = initialSpinRate*2*Pi/60; currentThetaDotx = 0; currentThetaDotz = 0;
currentThetax = 0; currentThetay = 0; currentThetaz = 0,
spin == "Z-axes", currentThetaDotz = initialSpinRate*2*Pi/60; currentThetaDotx = 0; currentThetaDoty = 0;
currentThetax = 0; currentThetay = 0; currentThetaz = 0
];
tick = Not[tick]} &], {"X-axes", "Y-axes", "Z-axes"},
ImageSize -> All]
},
{Style["Initial spin rate (RPM)", 10], SpanFromLeft},
{Manipulator[Dynamic[initialSpinRate, (initialSpinRate = #;
Which[
spin == "X-axes", currentThetaDotx = initialSpinRate*2*Pi/60; currentThetaDoty = 0; currentThetaDotz = 0,
spin == "Y-axes", currentThetaDoty = initialSpinRate*2*Pi/60; currentThetaDotx = 0; currentThetaDotz = 0,
spin == "Z-axes", currentThetaDotz = initialSpinRate*2*Pi/60; currentThetaDoty = 0; currentThetaDotx = 0
];
tick = Not[tick]) &], {-10, 10, .1}, ImageSize -> Small
],
Dynamic[padIt1[N@initialSpinRate, {4, 2}]]
}
}, Frame -> True, FrameStyle -> Gray
]
},
{
Grid[{
{ Button[Text@Style["run", 12], {state = "RUN"; tick = Not[tick]}, ImageSize -> {40, 40}],
Button[Text@Style["step", 12], {state = "STEP"; tick = Not[tick]}, ImageSize -> {40, 40}],
Button[Text@Style["stop", 12], {state = "STOP"; tick = Not[tick]}, ImageSize -> {40, 40}],
Button[Text@Style["reset", 12], {state = "RESET"; currentThetax = 0; currentThetay = 0; currentThetaz = 0;
currentThetaDotx = 0; currentThetaDoty = 0; currentThetaDotz = 0; op = 1; h = .5; r = .5; m = 1; spin = "Z-axes";
initialSpinRate = 10; delT = 0.1; currentTime = 0; tick = Not[tick]}, ImageSize -> {40, 40}](*fix*)
}
}, Spacings -> {.2, 0}, Frame -> True, FrameStyle -> Gray
]
},
{
Grid[{
{
Button[Text@Style["perturbe", Bold], {
Which[
spin == "X-axes", currentThetaDoty = (0.02*currentThetaDotx); currentThetaDotz = (0.02*currentThetaDotx),
spin == "Y-axes", currentThetaDotx = (0.02*currentThetaDoty); currentThetaDotz = (0.02*currentThetaDoty),
spin == "Z-axes", currentThetaDoty = (0.02*currentThetaDotz); currentThetaDotx = (0.02*currentThetaDotz)
];
tick = Not[tick]}, ImageSize -> {80, 40}]
}
}]
}
,
{Grid[{
{Row[{"opacity", Spacer[3], Manipulator[Dynamic[op, {op = #; tick = Not[tick]} &], {.1, 1, .1}, ImageSize -> Small],
Spacer[3], Dynamic[padIt1[op, {1, 1}]]}]},
{Row[{"slow", Spacer[3], Manipulator[Dynamic[delT, {delT = #; tick = Not[tick]} &], {0.01, 0.2, .01}, ImageSize -> Small],
Spacer[3], "fast"}]},
{Row[{"show Axes", Spacer[3], Checkbox[Dynamic[showAxes, {showAxes = #; tick = Not[tick]} &]]}]},
{Row[{"show angular velocity direction", Spacer[2], Checkbox[Dynamic[showW, {showW = #; tick = Not[tick]} &]]}], SpanFromLeft},
{Row[{"show body cone", Spacer[3], Checkbox[Dynamic[showCone, {showCone = #; tick = Not[tick]} &]]}]}
}, Frame -> True, Alignment -> Left, FrameStyle -> Gray
]
}
}, Frame -> False, Alignment -> Center, FrameStyle -> Gray
],
{{tick, False}, None},
{{state, "RESET"}, None},
{{currentTime, 0}, None},
{{delT, 0.1}, None},
{{op, 1}, None},
{{spin, "Z-axes"}, None},
{{initialSpinRate, 10}, None},
{{showAxes, True}, None},
{{showCone, True}, None},
(*{{\[Theta]x,0},None},
{{\[Theta]y,0},None},
{{\[Theta]z,0},None},
*)
{{r, .5}, None},
{{h, .5}, None},
{{m, 1}, None},
{{showW, True}, None},
{{currentThetax, 0}, None},
{{currentThetay, 0}, None},
{{currentThetaz, 0}, None},
{{currentThetaDotx, 0}, None},
{{currentThetaDoty, 0}, None},
{{currentThetaDotz, 0}, None},
{{currentThetaDotDotx, 0}, None},
{{currentThetaDotDoty, 0}, None},
{{currentThetaDotDotz, 0}, None},
TrackedSymbols :> {tick},
ControlPlacement -> Left, Alignment -> Center, ImageMargins -> 0, FrameMargins -> 0,
Initialization :>
(
integerStrictPositive = (IntegerQ[#] && # > 0 &);
integerPositive = (IntegerQ[#] && # >= 0 &);
numericStrictPositive = (Element[#, Reals] && # > 0 &);
numericPositive = (Element[#, Reals] && # >= 0 &);
numericStrictNegative = (Element[#, Reals] && # < 0 &);
numericNegative = (Element[#, Reals] && # <= 0 &);
bool = (Element[#, Booleans] &);
numeric = (Element[#, Reals] &);
integer = (Element[#, Integers] &);
(*--------------------------------------------*)
padIt1[v_?numeric, f_List] := AccountingForm[v,
f, NumberSigns -> {"-", "+"}, NumberPadding -> {"0", "0"}, SignPadding -> True];
(*--------------------------------------------*)
padIt1[v_?numeric, f_Integer] := AccountingForm[Chop[v],
f, NumberSigns -> {"-", "+"}, NumberPadding -> {"0", "0"}, SignPadding -> True];
(*--------------------------------------------*)
padIt2[v_?numeric, f_List] := AccountingForm[v,
f, NumberSigns -> {"", ""}, NumberPadding -> {"0", "0"}, SignPadding -> True];
(*--------------------------------------------*)
padIt2[v_?numeric, f_Integer] := AccountingForm[Chop[v],
f, NumberSigns -> {"", ""}, NumberPadding -> {"0", "0"}, SignPadding -> True];
(*--------------------------------------------*)
getIx[m_, w_, h_, d_] := 1/12 m (h^2 + d^2);
getIy[m_, w_, h_, d_] := 1/12 m (h^2 + w^2);
getIz[m_, w_, h_, d_] := 1/12 m (w^2 + d^2)
)
]