rigid.scm 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;;; Chapter 2
  21. ;;; Generalized coordinates to angular velocities.
  22. (define (m:antisymmetric? A)
  23. (m:zero? ((m:elementwise careful-simplify)
  24. (matrix+matrix (transpose A) A))))
  25. (define (antisymmetric->column-matrix A)
  26. (assert (m:antisymmetric? A))
  27. (column-matrix (matrix-ref A 2 1)
  28. (matrix-ref A 0 2)
  29. (matrix-ref A 1 0)))
  30. (define (3vector-components->antisymmetric v)
  31. (matrix-by-rows
  32. (list 0 (- (ref v 2)) (ref v 1))
  33. (list (ref v 2) 0 (- (ref v 0)))
  34. (list (- (ref v 1)) (ref v 0) 0)))
  35. (define* ((M-of-q->omega-of-t M-of-q) q)
  36. (lambda (t)
  37. (define M-on-path (compose M-of-q q))
  38. (define (omega-cross t)
  39. (* ((D M-on-path) t)
  40. (transpose (M-on-path t))))
  41. (antisymmetric->column-matrix (omega-cross t))))
  42. (define* ((M-of-q->omega-body-of-t M-of-q) q)
  43. (lambda (t)
  44. ;; FBE
  45. (* (transpose (M-of-q ;(q t)
  46. (g:apply q (list t))
  47. ))
  48. (((M-of-q->omega-of-t M-of-q) q) t))))
  49. (define (M->omega M-of-q)
  50. (Gamma-bar (M-of-q->omega-of-t M-of-q)))
  51. (define (M->omega-body M-of-q)
  52. (Gamma-bar (M-of-q->omega-body-of-t M-of-q)))
  53. ;;; Assuming omega-body is on principal axes,
  54. ;;; and A, B, C are the principal moments.
  55. ;;; Angular velocity to kinetic energy and angular momenta
  56. (define* ((T-body A B C) omega-body)
  57. (* 1/2
  58. (+ (* A (square (ref omega-body 0)))
  59. (* B (square (ref omega-body 1)))
  60. (* C (square (ref omega-body 2))))))
  61. #|
  62. (define ((L-body A B C) omega-body)
  63. (column-matrix (* A (ref omega-body 0))
  64. (* B (ref omega-body 1))
  65. (* C (ref omega-body 2))))
  66. |#
  67. (define* ((L-body A B C) omega-body)
  68. (down (* A (ref omega-body 0))
  69. (* B (ref omega-body 1))
  70. (* C (ref omega-body 2))))
  71. (define* ((L-space M) A B C)
  72. (lambda (omega-body)
  73. (* ((L-body A B C) omega-body)
  74. (transpose M))))
  75. ;;; Euler Angles
  76. (define (Euler->M angles)
  77. (let ((theta (ref angles 0))
  78. (phi (ref angles 1))
  79. (psi (ref angles 2)))
  80. (* (rotate-z-matrix phi)
  81. (* (rotate-x-matrix theta)
  82. (rotate-z-matrix psi)))))
  83. (define* ((Euler->omega angles-path) t)
  84. (define (M-on-path t)
  85. (Euler->M (angles-path t)))
  86. (define (w-cross t)
  87. (* ((D M-on-path) t)
  88. (transpose (M-on-path t))))
  89. (antisymmetric->column-matrix (w-cross t)))
  90. (define* ((Euler->omega-body angles-path) t)
  91. (* (transpose (Euler->M (angles-path t)))
  92. ((Euler->omega angles-path) t)))
  93. #|
  94. (show-expression
  95. ((Euler->omega-body
  96. (up (literal-function 'theta)
  97. (literal-function 'phi)
  98. (literal-function 'psi)))
  99. 't))
  100. (matrix-by-rows
  101. (list (+ (* (sin (theta t)) (sin (psi t)) ((D phi) t))
  102. (* ((D theta) t) (cos (psi t)))))
  103. (list (+ (* (sin (theta t)) (cos (psi t)) ((D phi) t))
  104. (* -1 ((D theta) t) (sin (psi t)))))
  105. (list (+ (* (cos (theta t)) ((D phi) t))
  106. ((D psi) t))))
  107. |#
  108. #|
  109. (show-expression
  110. (((M-of-q->omega-body-of-t Euler->M)
  111. (up (literal-function 'theta)
  112. (literal-function 'phi)
  113. (literal-function 'psi)))
  114. 't))
  115. (matrix-by-rows
  116. (list (+ (* (sin (theta t)) (sin (psi t)) ((D phi) t))
  117. (* ((D theta) t) (cos (psi t)))))
  118. (list (+ (* (sin (theta t)) (cos (psi t)) ((D phi) t))
  119. (* -1 ((D theta) t) (sin (psi t)))))
  120. (list (+ (* (cos (theta t)) ((D phi) t))
  121. ((D psi) t))))
  122. (show-expression
  123. ((M->omega-body Euler->M)
  124. (up 't
  125. (up 'theta 'phi 'psi)
  126. (up 'thetadot 'phidot 'psidot))))
  127. (matrix-by-rows
  128. (list (+ (* phidot (sin psi) (sin theta)) (* thetadot (cos psi))))
  129. (list (+ (* phidot (cos psi) (sin theta)) (* -1 thetadot (sin psi))))
  130. (list (+ (* phidot (cos theta)) psidot)))
  131. |#
  132. ;;; Assuming Euler angles rotate principal axes from reference
  133. ;;; orientation.
  134. #|
  135. (define (Euler-state->omega-body local)
  136. (let ((q (coordinate local))
  137. (qdot (velocity local)))
  138. (let ((theta (ref q 0))
  139. (psi (ref q 2))
  140. (thetadot (ref qdot 0))
  141. (phidot (ref qdot 1))
  142. (psidot (ref qdot 2)))
  143. (let ((omega-a (+ (* thetadot (cos psi))
  144. (* phidot (sin theta) (sin psi))))
  145. (omega-b (+ (* -1 thetadot (sin psi))
  146. (* phidot (sin theta) (cos psi))))
  147. (omega-c (+ (* phidot (cos theta)) psidot)))
  148. (column-matrix omega-a omega-b omega-c)))))
  149. |#
  150. ;;; Although this just appears to summarize (M->omega-body Euler->M)
  151. ;;; it is actually essential to prevent intermediate expression
  152. ;;; explosion.
  153. (define (Euler-state->omega-body local)
  154. (let ((q (coordinate local))
  155. (qdot (velocity local)))
  156. (let ((theta (ref q 0))
  157. (psi (ref q 2))
  158. (thetadot (ref qdot 0))
  159. (phidot (ref qdot 1))
  160. (psidot (ref qdot 2)))
  161. (let ((omega-a (+ (* thetadot (cos psi))
  162. (* phidot (sin theta) (sin psi))))
  163. (omega-b (+ (* -1 thetadot (sin psi))
  164. (* phidot (sin theta) (cos psi))))
  165. (omega-c (+ (* phidot (cos theta)) psidot)))
  166. (up omega-a omega-b omega-c)))))
  167. (define* ((T-body-Euler A B C) local)
  168. ((T-body A B C)
  169. (Euler-state->omega-body local)))
  170. (define T-rigid-body T-body-Euler)
  171. (define* ((L-body-Euler A B C) local)
  172. ((L-body A B C)
  173. (Euler-state->omega-body local)))
  174. (define Euler-state->L-body L-body-Euler)
  175. #| Wrong up/down
  176. (define ((Euler-state->L-space A B C) local)
  177. (let ((angles (coordinate local)))
  178. (* (Euler->M angles)
  179. ((Euler-state->L-body A B C) local))))
  180. |#
  181. #|
  182. (define ((Euler-state->L-space A B C) local)
  183. (let ((angles (coordinate local)))
  184. (((L-space (Euler->M angles)) A B C)
  185. (Euler-state->omega-body local))))
  186. |#
  187. (define* ((L-space-Euler A B C) local)
  188. (let ((angles (coordinate local)))
  189. (* ((L-body-Euler A B C) local)
  190. (transpose (Euler->M angles)))))
  191. (define Euler-state->L-space L-space-Euler)
  192. #|
  193. (define an-Euler-state
  194. (up 't
  195. (up 'theta 'phi 'psi)
  196. (up 'thetadot 'phidot 'psidot)))
  197. (show-expression
  198. (ref
  199. (((partial 2) (T-body-Euler 'A 'B 'C))
  200. an-Euler-state)
  201. 1))
  202. (+ (* A phidot (expt (sin psi) 2) (expt (sin theta) 2))
  203. (* B phidot (expt (cos psi) 2) (expt (sin theta) 2))
  204. (* A thetadot (cos psi) (sin psi) (sin theta))
  205. (* -1 B thetadot (cos psi) (sin psi) (sin theta))
  206. (* C phidot (expt (cos theta) 2))
  207. (* C psidot (cos theta)))
  208. (print-expression
  209. (- (ref ((L-space-Euler 'A 'B 'C) an-Euler-state) 2) ;$L_z$
  210. (ref (((partial 2) (T-body-Euler 'A 'B 'C)) an-Euler-state) 1) ;$p_\phi$
  211. ))
  212. 0
  213. (print-expression
  214. (determinant
  215. (((compose (partial 2) (partial 2))
  216. (T-body-Euler 'A 'B 'C))
  217. an-Euler-state)))
  218. (* A B C (expt (sin theta) 2))
  219. |#
  220. (define (relative-error value reference-value)
  221. (if (zero? reference-value)
  222. (error "Zero reference value -- RELATIVE-ERROR")
  223. (/ (- value reference-value) reference-value)))
  224. #|
  225. (define (rigid-sysder A B C)
  226. (Lagrangian->state-derivative (T-body-Euler A B C)))
  227. (define ((monitor-errors win A B C L0 E0) state)
  228. (let ((t (time state))
  229. (L ((L-space-Euler A B C) state))
  230. (E ((T-body-Euler A B C) state)))
  231. (plot-point win t (relative-error (ref L 0) (ref L0 0)))
  232. (plot-point win t (relative-error (ref L 1) (ref L0 1)))
  233. (plot-point win t (relative-error (ref L 2) (ref L0 2)))
  234. (plot-point win t (relative-error E E0))))
  235. ;;; rkqc4
  236. ;;;(set! *ode-integration-method* 'qcrk4)
  237. ;;;(define win (frame 0. 100. -1.e-12 1.e-12))
  238. ;;; bulirsch-stoer
  239. (set! *ode-integration-method* 'bulirsch-stoer)
  240. (define win (frame 0. 100. -2.e-13 2.e-13))
  241. (let ((A 1.) (B (sqrt 2.)) (C 2.)
  242. (state0 (up 0.0
  243. (up 1. 0. 0.)
  244. (up 0.1 0.1 0.1))))
  245. (let ((L0 ((L-space-Euler A B C) state0))
  246. (E0 ((T-body-Euler A B C) state0)))
  247. ((evolve rigid-sysder A B C)
  248. state0
  249. (monitor-errors win A B C L0 E0)
  250. 0.1
  251. 100.0
  252. 1.0e-12)))
  253. #|
  254. (up 99.99999999999864
  255. (up .6319896958334494 1.3610271540875034 17.437900484737938)
  256. (up -.12343716197181527 .09016109524808046 .07567921658605782))
  257. |#
  258. (graphics-clear win)
  259. (graphics-close win)
  260. |#
  261. #|
  262. (show-expression
  263. ((T-body-Euler 'A 'A 'C)
  264. (up 't
  265. (up 'theta 'phi 'psi)
  266. (up 'thetadot 'phidot 'psidot))))
  267. (+ (* 1/2 A (expt phidot 2) (expt (sin theta) 2))
  268. (* 1/2 C (expt phidot 2) (expt (cos theta) 2))
  269. (* C phidot psidot (cos theta))
  270. (* 1/2 A (expt thetadot 2))
  271. (* 1/2 C (expt psidot 2)))
  272. ;;; Transformation of A(v):
  273. ;;; M^T A(Mv) M = A(v) for arbitrary v orthogonal M
  274. (print-expression
  275. (let ((Euler (up 'theta 'phi 'psi))
  276. (v (up 'x 'y 'z)))
  277. (let ((M (Euler->M Euler)))
  278. (- (* (3vector-components->antisymmetric (* M v))
  279. M)
  280. (* M
  281. (3vector-components->antisymmetric v))))))
  282. (matrix-by-rows (list 0 0 0) (list 0 0 0) (list 0 0 0))
  283. |#
  284. #|
  285. ;;; Configuration equations for Euler's equations with Euler angles
  286. (print-expression
  287. (let ((Euler (up (literal-function 'theta)
  288. (literal-function 'phi)
  289. (literal-function 'psi))))
  290. (antisymmetric->column-matrix
  291. (* (transpose ((Euler->M Euler) 't))
  292. ((D (Euler->M Euler)) 't)))))
  293. (matrix-by-rows
  294. (list
  295. (+ (* ((D phi) t) (sin (psi t)) (sin (theta t)))
  296. (* ((D theta) t) (cos (psi t)))))
  297. (list
  298. (+ (* ((D phi) t) (sin (theta t)) (cos (psi t)))
  299. (* -1 (sin (psi t)) ((D theta) t))))
  300. (list (+ (* (cos (theta t)) ((D phi) t)) ((D psi) t))))
  301. |#
  302. #|
  303. (define ((L-axisymmetric-top A C gMR) local)
  304. (let ((q (coordinate local))
  305. (qdot (velocity local)))
  306. (let ((theta (ref q 0))
  307. (thetadot (ref qdot 0))
  308. (phidot (ref qdot 1))
  309. (psidot (ref qdot 2)))
  310. (+ (* 1/2 A
  311. (+ (square thetadot)
  312. (square (* phidot (sin theta)))))
  313. (* 1/2 C
  314. (square (+ psidot (* phidot (cos theta)))))
  315. (* -1 gMR (cos theta))))))
  316. (define ((V_eff p A C gMR) theta)
  317. (+ (/ (square p) (* 2 C))
  318. (* (/ (square p) (* 2 A))
  319. (square (tan (/ theta 2))))
  320. (* gMR (cos theta))))
  321. ;;; Critical value of bifurcation when D^2 V_eff (0) = 0
  322. (print-expression
  323. (((square derivative) (V_eff 'p_c 'A 'C 'gMR)) 0))
  324. (+ (* -1 gMR) (/ (* 1/4 (expt p_c 2)) A))
  325. ;;; critical angular speed in RPM is:
  326. (* (/ 60 2pi) (/ 7.734804457773965e-3 6.6e-5))
  327. ;Value: 1119.1203302763215
  328. |#
  329. ;;; Quaternion representation
  330. (define (quaternion-state->omega-body s)
  331. (let ((q (coordinates s)) (qdot (velocities s)))
  332. (let* ((m^2 (dot-product q q)))
  333. (let ((omega^a
  334. (/ (* 2 (dot-product q (* q:i qdot))) m^2))
  335. (omega^b
  336. (/ (* 2 (dot-product q (* q:j qdot))) m^2))
  337. (omega^c
  338. (/ (* 2 (dot-product q (* q:k qdot))) m^2)))
  339. (up omega^a omega^b omega^c)))))
  340. (define (quaternion-state->omega-space s)
  341. (define q:a
  342. (matrix-by-rows (list 0 +1 0 0)
  343. (list -1 0 0 0)
  344. (list 0 0 0 +1)
  345. (list 0 0 -1 0)))
  346. (define q:b
  347. (matrix-by-rows (list 0 0 +1 0)
  348. (list 0 0 0 -1)
  349. (list -1 0 0 0)
  350. (list 0 +1 0 0)))
  351. (define q:c
  352. (matrix-by-rows (list 0 0 0 +1)
  353. (list 0 0 +1 0)
  354. (list 0 -1 0 0)
  355. (list -1 0 0 0)))
  356. (let ((q (coordinates s))
  357. (qdot (velocities s)))
  358. (let ((Q (up->column-matrix q))
  359. (QdotT (m:transpose (up->column-matrix qdot))))
  360. (let ((m^2 (ref (* (m:transpose Q) Q) 0 0)))
  361. (let ((omega^x (/ (ref (* -2 QdotT q:a Q) 0 0) m^2))
  362. (omega^y (/ (ref (* -2 QdotT q:b Q) 0 0) m^2))
  363. (omega^z (/ (ref (* -2 QdotT q:c Q) 0 0) m^2)))
  364. (up omega^x omega^y omega^z))))))
  365. (define* ((qw-state->L-body A B C) qw-state)
  366. ((L-body A B C) (ref qw-state 2)))
  367. (define* ((qw-state->L-space A B C) qw-state)
  368. (let ((q (coordinates qw-state)))
  369. (let ((Lbody ((qw-state->L-body A B C) qw-state))
  370. (M (quaternion->rotation-matrix (make-quaternion q))))
  371. (* Lbody (transpose M)))))
  372. (define* ((T-quaternion-state A B C) s)
  373. (let ((q (coordinates s))
  374. (qdot (velocities s)))
  375. (let ((Q (up->column-matrix q))
  376. (Qdot (up->column-matrix qdot)))
  377. (let ((m^2 (ref (* (m:transpose Q) Q) 0 0)))
  378. (let ((x (/ (* q:i Qdot) m^2))
  379. (y (/ (* q:j Qdot) m^2))
  380. (z (/ (* q:k Qdot) m^2))
  381. (M (* Q (m:transpose Q))))
  382. (* 2
  383. (+ (* A (ref (* (m:transpose x) M x) 0 0))
  384. (* B (ref (* (m:transpose y) M y) 0 0))
  385. (* C (ref (* (m:transpose z) M z) 0 0)))))))))
  386. #|
  387. (define (qw-sysder A B C)
  388. (let ((B-C/A (/ (- B C) A))
  389. (C-A/B (/ (- C A) B))
  390. (A-B/C (/ (- A B) C)))
  391. (define (the-deriv qw-state)
  392. (let ((t (time qw-state))
  393. (q (coordinates qw-state))
  394. (omega-body (ref qw-state 2)))
  395. (let ((omega^a (ref omega-body 0))
  396. (omega^b (ref omega-body 1))
  397. (omega^c (ref omega-body 2)))
  398. (let ((tdot 1)
  399. (qdot ;driven quaternion
  400. (* -1/2
  401. (+ (* omega^a q:i)
  402. (* omega^b q:j)
  403. (* omega^c q:k))
  404. q))
  405. (omegadot ;Euler's equations
  406. (up (* B-C/A omega^b omega^c)
  407. (* C-A/B omega^c omega^a)
  408. (* A-B/C omega^a omega^b))))
  409. (up tdot qdot omegadot)))))
  410. the-deriv))
  411. (define ((monitor-errors win A B C L0 E0) qw-state)
  412. (let ((t (time qw-state))
  413. (L ((qw-state->L-space A B C) qw-state))
  414. (E ((T-body A B C) (ref qw-state 2))))
  415. (plot-point win t (relative-error (ref L 0) (ref L0 0)))
  416. (plot-point win t (relative-error (ref L 1) (ref L0 1)))
  417. (plot-point win t (relative-error (ref L 2) (ref L0 2)))
  418. (plot-point win t (relative-error E E0))
  419. qw-state))
  420. (define win (frame 0. 100. -1.e-13 1.e-13))
  421. (let* ((A 1.) (B (sqrt 2.)) (C 2.) ; moments of inertia
  422. (Euler-state (up 0.0 ; initial state
  423. (up 1. 0. 0.)
  424. (up 0.1 0.1 0.1)))
  425. (M (Euler->M (coordinates Euler-state)))
  426. (q (quaternion->vector (rotation-matrix->quaternion M)))
  427. (qw-state0
  428. (up (time Euler-state)
  429. q
  430. (Euler-state->omega-body Euler-state))))
  431. (let ((L0 ((qw-state->L-space A B C) qw-state0))
  432. (E0 ((T-body A B C) (ref qw-state0 2))))
  433. ((evolve qw-sysder A B C)
  434. qw-state0
  435. (monitor-errors win A B C L0 E0)
  436. 0.1 ; step between plotted points
  437. 100.0 ; final time
  438. 1.0e-12)))
  439. |#