equation.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // Copyright 2016 The G3N Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // Package equation implements SPOOK equations based on
  5. // the 2007 PhD thesis of Claude Lacoursière titled
  6. // "Ghosts and Machines: Regularized Variational Methods for
  7. // Interactive Simulations of Multibodies with Dry Frictional Contacts"
  8. package equation
  9. import (
  10. "github.com/g3n/engine/math32"
  11. )
  12. // IBody is the interface of all body types.
  13. type IBody interface {
  14. Index() int
  15. Position() math32.Vector3
  16. Velocity() math32.Vector3
  17. AngularVelocity() math32.Vector3
  18. Force() math32.Vector3
  19. Torque() math32.Vector3
  20. InvMassSolve() float32
  21. InvInertiaWorldSolve() *math32.Matrix3
  22. }
  23. // Equation is a SPOOK constraint equation.
  24. type Equation struct {
  25. id int
  26. minForce float32 // Minimum (read: negative max) force to be applied by the constraint.
  27. maxForce float32 // Maximum (read: positive max) force to be applied by the constraint.
  28. bA IBody // Body "i"
  29. bB IBody // Body "j"
  30. a float32 // SPOOK parameter
  31. b float32 // SPOOK parameter
  32. eps float32 // SPOOK parameter
  33. jeA JacobianElement
  34. jeB JacobianElement
  35. enabled bool
  36. multiplier float32 // A number, proportional to the force added to the bodies.
  37. }
  38. // NewEquation creates and returns a pointer to a new Equation object.
  39. func NewEquation(bi, bj IBody, minForce, maxForce float32) *Equation {
  40. e := new(Equation)
  41. e.initialize(bi, bj, minForce, maxForce)
  42. return e
  43. }
  44. func (e *Equation) initialize(bi, bj IBody, minForce, maxForce float32) {
  45. //e.id = Equation.id++
  46. e.minForce = minForce //-1e6
  47. e.maxForce = maxForce //1e6
  48. e.bA = bi
  49. e.bB = bj
  50. e.a = 0
  51. e.b = 0
  52. e.eps = 0
  53. e.enabled = true
  54. e.multiplier = 0
  55. // Set typical spook params
  56. e.SetSpookParams(1e7, 4, 1/60)
  57. }
  58. func (e *Equation) BodyA() IBody {
  59. return e.bA
  60. }
  61. func (e *Equation) BodyB() IBody {
  62. return e.bB
  63. }
  64. func (e *Equation) JeA() JacobianElement {
  65. return e.jeA
  66. }
  67. func (e *Equation) JeB() JacobianElement {
  68. return e.jeB
  69. }
  70. // SetMinForce sets the minimum force to be applied by the constraint.
  71. func (e *Equation) SetMinForce(minForce float32) {
  72. e.minForce = minForce
  73. }
  74. // MinForce returns the minimum force to be applied by the constraint.
  75. func (e *Equation) MinForce() float32 {
  76. return e.minForce
  77. }
  78. // SetMaxForce sets the maximum force to be applied by the constraint.
  79. func (e *Equation) SetMaxForce(maxForce float32) {
  80. e.maxForce = maxForce
  81. }
  82. // MaxForce returns the maximum force to be applied by the constraint.
  83. func (e *Equation) MaxForce() float32 {
  84. return e.maxForce
  85. }
  86. // TODO
  87. func (e *Equation) Eps() float32 {
  88. return e.eps
  89. }
  90. // SetMultiplier sets the multiplier.
  91. func (e *Equation) SetMultiplier(multiplier float32) {
  92. e.multiplier = multiplier
  93. }
  94. // MaxForce returns the multiplier.
  95. func (e *Equation) Multiplier() float32 {
  96. return e.multiplier
  97. }
  98. // SetEnable sets the enabled flag of the equation.
  99. func (e *Equation) SetEnabled(state bool) {
  100. e.enabled = state
  101. }
  102. // Enabled returns the enabled flag of the equation.
  103. func (e *Equation) Enabled() bool {
  104. return e.enabled
  105. }
  106. // SetSpookParams recalculates a, b, eps.
  107. func (e *Equation) SetSpookParams(stiffness, relaxation float32, timeStep float32) {
  108. e.a = 4.0 / (timeStep * (1 + 4*relaxation))
  109. e.b = (4.0 * relaxation) / (1 + 4*relaxation)
  110. e.eps = 4.0 / (timeStep * timeStep * stiffness * (1 + 4*relaxation))
  111. }
  112. // ComputeB computes the RHS of the SPOOK equation.
  113. func (e *Equation) ComputeB(h float32) float32 {
  114. GW := e.ComputeGW()
  115. Gq := e.ComputeGq()
  116. GiMf := e.ComputeGiMf()
  117. return -Gq*e.a - GW*e.b - GiMf*h
  118. }
  119. // ComputeGq computes G*q, where q are the generalized body coordinates.
  120. func (e *Equation) ComputeGq() float32 {
  121. xi := e.bA.Position()
  122. xj := e.bB.Position()
  123. spatA := e.jeA.Spatial()
  124. spatB := e.jeB.Spatial()
  125. return (&spatA).Dot(&xi) + (&spatB).Dot(&xj)
  126. }
  127. // ComputeGW computes G*W, where W are the body velocities.
  128. func (e *Equation) ComputeGW() float32 {
  129. vA := e.bA.Velocity()
  130. vB := e.bB.Velocity()
  131. wA := e.bA.AngularVelocity()
  132. wB := e.bB.AngularVelocity()
  133. return e.jeA.MultiplyVectors(&vA, &wA) + e.jeB.MultiplyVectors(&vB, &wB)
  134. }
  135. // ComputeGiMf computes G*inv(M)*f, where M is the mass matrix with diagonal blocks for each body, and f are the forces on the bodies.
  136. func (e *Equation) ComputeGiMf() float32 {
  137. forceA := e.bA.Force()
  138. forceB := e.bB.Force()
  139. iMfA := forceA.MultiplyScalar(e.bA.InvMassSolve())
  140. iMfB := forceB.MultiplyScalar(e.bB.InvMassSolve())
  141. torqueA := e.bA.Torque()
  142. torqueB := e.bB.Torque()
  143. invIiTaui := torqueA.ApplyMatrix3(e.bA.InvInertiaWorldSolve())
  144. invIjTauj := torqueB.ApplyMatrix3(e.bB.InvInertiaWorldSolve())
  145. return e.jeA.MultiplyVectors(iMfA, invIiTaui) + e.jeB.MultiplyVectors(iMfB, invIjTauj)
  146. }
  147. // ComputeGiMGt computes G*inv(M)*G'.
  148. func (e *Equation) ComputeGiMGt() float32 {
  149. rotA := e.jeA.Rotational()
  150. rotB := e.jeB.Rotational()
  151. rotAcopy := e.jeA.Rotational()
  152. rotBcopy := e.jeB.Rotational()
  153. result := e.bA.InvMassSolve() + e.bB.InvMassSolve()
  154. result += rotA.ApplyMatrix3(e.bA.InvInertiaWorldSolve()).Dot(&rotAcopy)
  155. result += rotB.ApplyMatrix3(e.bB.InvInertiaWorldSolve()).Dot(&rotBcopy)
  156. return result
  157. }
  158. // ComputeC computes the denominator part of the SPOOK equation: C = G*inv(M)*G' + eps.
  159. func (e *Equation) ComputeC() float32 {
  160. return e.ComputeGiMGt() + e.eps
  161. }