react-native-nitro-pose-exercises 1.1.5 → 1.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/README.md +192 -159
  2. package/android/src/main/java/com/margelo/nitro/nitroposeexercises/NitroPoseExercises.kt +121 -4
  3. package/ios/NitroPoseExercises.swift +128 -11
  4. package/lib/module/NitroPoseExercises.nitro.js.map +1 -1
  5. package/lib/module/config/bicep-curl.js +3 -0
  6. package/lib/module/config/bicep-curl.js.map +1 -1
  7. package/lib/module/config/boat-pose.js +44 -0
  8. package/lib/module/config/boat-pose.js.map +1 -0
  9. package/lib/module/config/bow-pose.js +37 -0
  10. package/lib/module/config/bow-pose.js.map +1 -0
  11. package/lib/module/config/bridge-pose.js +37 -0
  12. package/lib/module/config/bridge-pose.js.map +1 -0
  13. package/lib/module/config/calf-raise.js +47 -0
  14. package/lib/module/config/calf-raise.js.map +1 -0
  15. package/lib/module/config/camel-pose.js +37 -0
  16. package/lib/module/config/camel-pose.js.map +1 -0
  17. package/lib/module/config/chair-pose.js +3 -0
  18. package/lib/module/config/chair-pose.js.map +1 -1
  19. package/lib/module/config/childs-pose.js +42 -0
  20. package/lib/module/config/childs-pose.js.map +1 -0
  21. package/lib/module/config/cobra-pose.js +3 -0
  22. package/lib/module/config/cobra-pose.js.map +1 -1
  23. package/lib/module/config/cobra-wings.js +47 -0
  24. package/lib/module/config/cobra-wings.js.map +1 -0
  25. package/lib/module/config/dead-lift.js +54 -0
  26. package/lib/module/config/dead-lift.js.map +1 -0
  27. package/lib/module/config/downward-dog.js +3 -0
  28. package/lib/module/config/downward-dog.js.map +1 -1
  29. package/lib/module/config/extended-side-angle.js +49 -0
  30. package/lib/module/config/extended-side-angle.js.map +1 -0
  31. package/lib/module/config/fish-pose.js +37 -0
  32. package/lib/module/config/fish-pose.js.map +1 -0
  33. package/lib/module/config/front-raise.js +54 -0
  34. package/lib/module/config/front-raise.js.map +1 -0
  35. package/lib/module/config/glute-bridge.js +49 -0
  36. package/lib/module/config/glute-bridge.js.map +1 -0
  37. package/lib/module/config/hip-abduction.js +42 -0
  38. package/lib/module/config/hip-abduction.js.map +1 -0
  39. package/lib/module/config/knee-raise.js +47 -0
  40. package/lib/module/config/knee-raise.js.map +1 -0
  41. package/lib/module/config/lateral-raise.js +54 -0
  42. package/lib/module/config/lateral-raise.js.map +1 -0
  43. package/lib/module/config/leg-raise.js +49 -0
  44. package/lib/module/config/leg-raise.js.map +1 -0
  45. package/lib/module/config/lunge.js +3 -0
  46. package/lib/module/config/lunge.js.map +1 -1
  47. package/lib/module/config/mountain-pose.js +49 -0
  48. package/lib/module/config/mountain-pose.js.map +1 -0
  49. package/lib/module/config/overarm-reach.js +47 -0
  50. package/lib/module/config/overarm-reach.js.map +1 -0
  51. package/lib/module/config/plank.js +3 -0
  52. package/lib/module/config/plank.js.map +1 -1
  53. package/lib/module/config/pull-up.js +47 -0
  54. package/lib/module/config/pull-up.js.map +1 -0
  55. package/lib/module/config/pushup.js +4 -0
  56. package/lib/module/config/pushup.js.map +1 -1
  57. package/lib/module/config/reverse-warrior.js +49 -0
  58. package/lib/module/config/reverse-warrior.js.map +1 -0
  59. package/lib/module/config/shoulder-press.js +3 -0
  60. package/lib/module/config/shoulder-press.js.map +1 -1
  61. package/lib/module/config/side-lung.js +54 -0
  62. package/lib/module/config/side-lung.js.map +1 -0
  63. package/lib/module/config/side-plank.js +37 -0
  64. package/lib/module/config/side-plank.js.map +1 -0
  65. package/lib/module/config/situp.js +3 -0
  66. package/lib/module/config/situp.js.map +1 -1
  67. package/lib/module/config/squat.js +3 -0
  68. package/lib/module/config/squat.js.map +1 -1
  69. package/lib/module/config/sumo-squat.js +54 -0
  70. package/lib/module/config/sumo-squat.js.map +1 -0
  71. package/lib/module/config/tree-pose.js +3 -0
  72. package/lib/module/config/tree-pose.js.map +1 -1
  73. package/lib/module/config/triangle-pose.js +49 -0
  74. package/lib/module/config/triangle-pose.js.map +1 -0
  75. package/lib/module/config/tricep-dip.js +4 -0
  76. package/lib/module/config/tricep-dip.js.map +1 -1
  77. package/lib/module/config/v-up.js +42 -0
  78. package/lib/module/config/v-up.js.map +1 -0
  79. package/lib/module/config/wall-sit.js +3 -0
  80. package/lib/module/config/wall-sit.js.map +1 -1
  81. package/lib/module/config/warrior-i.js +3 -0
  82. package/lib/module/config/warrior-i.js.map +1 -1
  83. package/lib/module/config/warrior-ii.js +3 -0
  84. package/lib/module/config/warrior-ii.js.map +1 -1
  85. package/lib/module/config/warrior-iii.js +61 -0
  86. package/lib/module/config/warrior-iii.js.map +1 -0
  87. package/lib/module/index.js +31 -3
  88. package/lib/module/index.js.map +1 -1
  89. package/lib/typescript/src/NitroPoseExercises.nitro.d.ts +9 -1
  90. package/lib/typescript/src/NitroPoseExercises.nitro.d.ts.map +1 -1
  91. package/lib/typescript/src/config/bicep-curl.d.ts.map +1 -1
  92. package/lib/typescript/src/config/boat-pose.d.ts +3 -0
  93. package/lib/typescript/src/config/boat-pose.d.ts.map +1 -0
  94. package/lib/typescript/src/config/bow-pose.d.ts +3 -0
  95. package/lib/typescript/src/config/bow-pose.d.ts.map +1 -0
  96. package/lib/typescript/src/config/bridge-pose.d.ts +3 -0
  97. package/lib/typescript/src/config/bridge-pose.d.ts.map +1 -0
  98. package/lib/typescript/src/config/calf-raise.d.ts +3 -0
  99. package/lib/typescript/src/config/calf-raise.d.ts.map +1 -0
  100. package/lib/typescript/src/config/camel-pose.d.ts +3 -0
  101. package/lib/typescript/src/config/camel-pose.d.ts.map +1 -0
  102. package/lib/typescript/src/config/chair-pose.d.ts.map +1 -1
  103. package/lib/typescript/src/config/childs-pose.d.ts +3 -0
  104. package/lib/typescript/src/config/childs-pose.d.ts.map +1 -0
  105. package/lib/typescript/src/config/cobra-pose.d.ts.map +1 -1
  106. package/lib/typescript/src/config/cobra-wings.d.ts +3 -0
  107. package/lib/typescript/src/config/cobra-wings.d.ts.map +1 -0
  108. package/lib/typescript/src/config/dead-lift.d.ts +3 -0
  109. package/lib/typescript/src/config/dead-lift.d.ts.map +1 -0
  110. package/lib/typescript/src/config/downward-dog.d.ts.map +1 -1
  111. package/lib/typescript/src/config/extended-side-angle.d.ts +3 -0
  112. package/lib/typescript/src/config/extended-side-angle.d.ts.map +1 -0
  113. package/lib/typescript/src/config/fish-pose.d.ts +3 -0
  114. package/lib/typescript/src/config/fish-pose.d.ts.map +1 -0
  115. package/lib/typescript/src/config/front-raise.d.ts +3 -0
  116. package/lib/typescript/src/config/front-raise.d.ts.map +1 -0
  117. package/lib/typescript/src/config/glute-bridge.d.ts +3 -0
  118. package/lib/typescript/src/config/glute-bridge.d.ts.map +1 -0
  119. package/lib/typescript/src/config/hip-abduction.d.ts +3 -0
  120. package/lib/typescript/src/config/hip-abduction.d.ts.map +1 -0
  121. package/lib/typescript/src/config/knee-raise.d.ts +3 -0
  122. package/lib/typescript/src/config/knee-raise.d.ts.map +1 -0
  123. package/lib/typescript/src/config/lateral-raise.d.ts +3 -0
  124. package/lib/typescript/src/config/lateral-raise.d.ts.map +1 -0
  125. package/lib/typescript/src/config/leg-raise.d.ts +3 -0
  126. package/lib/typescript/src/config/leg-raise.d.ts.map +1 -0
  127. package/lib/typescript/src/config/lunge.d.ts.map +1 -1
  128. package/lib/typescript/src/config/mountain-pose.d.ts +3 -0
  129. package/lib/typescript/src/config/mountain-pose.d.ts.map +1 -0
  130. package/lib/typescript/src/config/overarm-reach.d.ts +3 -0
  131. package/lib/typescript/src/config/overarm-reach.d.ts.map +1 -0
  132. package/lib/typescript/src/config/plank.d.ts.map +1 -1
  133. package/lib/typescript/src/config/pull-up.d.ts +3 -0
  134. package/lib/typescript/src/config/pull-up.d.ts.map +1 -0
  135. package/lib/typescript/src/config/pushup.d.ts.map +1 -1
  136. package/lib/typescript/src/config/reverse-warrior.d.ts +3 -0
  137. package/lib/typescript/src/config/reverse-warrior.d.ts.map +1 -0
  138. package/lib/typescript/src/config/shoulder-press.d.ts.map +1 -1
  139. package/lib/typescript/src/config/side-lung.d.ts +3 -0
  140. package/lib/typescript/src/config/side-lung.d.ts.map +1 -0
  141. package/lib/typescript/src/config/side-plank.d.ts +3 -0
  142. package/lib/typescript/src/config/side-plank.d.ts.map +1 -0
  143. package/lib/typescript/src/config/situp.d.ts.map +1 -1
  144. package/lib/typescript/src/config/squat.d.ts.map +1 -1
  145. package/lib/typescript/src/config/sumo-squat.d.ts +3 -0
  146. package/lib/typescript/src/config/sumo-squat.d.ts.map +1 -0
  147. package/lib/typescript/src/config/tree-pose.d.ts.map +1 -1
  148. package/lib/typescript/src/config/triangle-pose.d.ts +3 -0
  149. package/lib/typescript/src/config/triangle-pose.d.ts.map +1 -0
  150. package/lib/typescript/src/config/tricep-dip.d.ts.map +1 -1
  151. package/lib/typescript/src/config/v-up.d.ts +3 -0
  152. package/lib/typescript/src/config/v-up.d.ts.map +1 -0
  153. package/lib/typescript/src/config/wall-sit.d.ts.map +1 -1
  154. package/lib/typescript/src/config/warrior-i.d.ts.map +1 -1
  155. package/lib/typescript/src/config/warrior-ii.d.ts.map +1 -1
  156. package/lib/typescript/src/config/warrior-iii.d.ts +3 -0
  157. package/lib/typescript/src/config/warrior-iii.d.ts.map +1 -0
  158. package/lib/typescript/src/index.d.ts +26 -0
  159. package/lib/typescript/src/index.d.ts.map +1 -1
  160. package/nitrogen/generated/android/c++/JCameraAngleType.hpp +58 -0
  161. package/nitrogen/generated/android/c++/JExerciseConfig.hpp +19 -3
  162. package/nitrogen/generated/android/c++/JHybridNitroPoseExercisesSpec.cpp +47 -0
  163. package/nitrogen/generated/android/c++/JHybridNitroPoseExercisesSpec.hpp +5 -0
  164. package/nitrogen/generated/android/c++/JPostureFamily.hpp +73 -0
  165. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroposeexercises/CameraAngleType.kt +23 -0
  166. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroposeexercises/ExerciseConfig.kt +19 -4
  167. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroposeexercises/HybridNitroPoseExercisesSpec.kt +32 -0
  168. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroposeexercises/PostureFamily.kt +28 -0
  169. package/nitrogen/generated/ios/NitroPoseExercises-Swift-Cxx-Bridge.hpp +9 -0
  170. package/nitrogen/generated/ios/NitroPoseExercises-Swift-Cxx-Umbrella.hpp +6 -0
  171. package/nitrogen/generated/ios/c++/HybridNitroPoseExercisesSpecSwift.hpp +28 -0
  172. package/nitrogen/generated/ios/swift/CameraAngleType.swift +40 -0
  173. package/nitrogen/generated/ios/swift/ExerciseConfig.swift +17 -2
  174. package/nitrogen/generated/ios/swift/HybridNitroPoseExercisesSpec.swift +3 -0
  175. package/nitrogen/generated/ios/swift/HybridNitroPoseExercisesSpec_cxx.swift +76 -0
  176. package/nitrogen/generated/ios/swift/PostureFamily.swift +60 -0
  177. package/nitrogen/generated/shared/c++/CameraAngleType.hpp +76 -0
  178. package/nitrogen/generated/shared/c++/ExerciseConfig.hpp +20 -2
  179. package/nitrogen/generated/shared/c++/HybridNitroPoseExercisesSpec.cpp +5 -0
  180. package/nitrogen/generated/shared/c++/HybridNitroPoseExercisesSpec.hpp +5 -0
  181. package/nitrogen/generated/shared/c++/PostureFamily.hpp +96 -0
  182. package/package.json +1 -1
  183. package/src/NitroPoseExercises.nitro.ts +19 -0
  184. package/src/config/bicep-curl.ts +3 -0
  185. package/src/config/boat-pose.ts +36 -0
  186. package/src/config/bow-pose.ts +27 -0
  187. package/src/config/bridge-pose.ts +28 -0
  188. package/src/config/calf-raise.ts +30 -0
  189. package/src/config/camel-pose.ts +27 -0
  190. package/src/config/chair-pose.ts +3 -0
  191. package/src/config/childs-pose.ts +26 -0
  192. package/src/config/cobra-pose.ts +3 -0
  193. package/src/config/cobra-wings.ts +29 -0
  194. package/src/config/dead-lift.ts +38 -0
  195. package/src/config/downward-dog.ts +3 -0
  196. package/src/config/extended-side-angle.ts +36 -0
  197. package/src/config/fish-pose.ts +28 -0
  198. package/src/config/front-raise.ts +58 -0
  199. package/src/config/glute-bridge.ts +36 -0
  200. package/src/config/hip-abduction.ts +28 -0
  201. package/src/config/knee-raise.ts +29 -0
  202. package/src/config/lateral-raise.ts +58 -0
  203. package/src/config/leg-raise.ts +36 -0
  204. package/src/config/lunge.ts +3 -0
  205. package/src/config/mountain-pose.ts +36 -0
  206. package/src/config/overarm-reach.ts +49 -0
  207. package/src/config/plank.ts +3 -0
  208. package/src/config/pull-up.ts +30 -0
  209. package/src/config/pushup.ts +3 -0
  210. package/src/config/reverse-warrior.ts +36 -0
  211. package/src/config/shoulder-press.ts +3 -0
  212. package/src/config/side-lung.ts +37 -0
  213. package/src/config/side-plank.ts +28 -0
  214. package/src/config/situp.ts +3 -0
  215. package/src/config/squat.ts +3 -0
  216. package/src/config/sumo-squat.ts +38 -0
  217. package/src/config/tree-pose.ts +3 -0
  218. package/src/config/triangle-pose.ts +37 -0
  219. package/src/config/tricep-dip.ts +3 -0
  220. package/src/config/v-up.ts +29 -0
  221. package/src/config/wall-sit.ts +3 -0
  222. package/src/config/warrior-i.ts +3 -0
  223. package/src/config/warrior-ii.ts +3 -0
  224. package/src/config/warrior-iii.ts +45 -0
  225. package/src/index.tsx +31 -3
@@ -26,6 +26,7 @@ class NitroPoseExercises : HybridNitroPoseExercisesSpec() {
26
26
  private var poseDetector: PoseDetector? = null
27
27
  private var isInitialized = false
28
28
 
29
+
29
30
  // ─── Cached Landmarks (ML Kit is async, we cache last result) ──
30
31
  private var cachedLandmarks: Array<Landmark> = emptyArray()
31
32
  private val landmarkLock = Any()
@@ -115,6 +116,14 @@ class NitroPoseExercises : HybridNitroPoseExercisesSpec() {
115
116
  override var onPoseRegained: (() -> Unit)? = null
116
117
  override var onSessionComplete: ((result: SessionResult) -> Unit)? = null
117
118
 
119
+ override var onPostureLost: (() -> Unit)? = null
120
+ override var onPostureRegained: (() -> Unit)? = null
121
+
122
+ // ─── Posture Gate ──────────────────────────────────────────
123
+ private var consecutivePostureFailures: Int = 0
124
+ private val postureFailureThreshold: Int = 10
125
+ private var postureWasLost = false
126
+
118
127
  // ─── Hold Tracking ──────────────────────────────────────────
119
128
  private var holdStartTime: Long? = null
120
129
 
@@ -143,6 +152,12 @@ class NitroPoseExercises : HybridNitroPoseExercisesSpec() {
143
152
  resetSession()
144
153
  }
145
154
 
155
+ override fun isReady(): Boolean {
156
+ val config = exerciseConfig ?: return false
157
+ if (_landmarks.isEmpty()) return false
158
+ return isPostureValid(config.postureFamily)
159
+ }
160
+
146
161
  // ═══════════════════════════════════════════════════════════
147
162
  // Exercise Setup
148
163
  // ═══════════════════════════════════════════════════════════
@@ -201,7 +216,10 @@ override fun processFrame(frame: HybridFrameSpec) {
201
216
  val nativeBuffer = frame.getNativeBuffer()
202
217
  val bitmap = FrameHelper.hardwareBufferToBitmap(nativeBuffer.pointer) ?: return
203
218
 
204
- val inputImage = InputImage.fromBitmap(bitmap, 0)
219
+
220
+ val rotation = rotationDegreesFromFrame(frame)
221
+ val inputImage = InputImage.fromBitmap(bitmap, rotation)
222
+
205
223
  val imageWidth = bitmap.width.toDouble()
206
224
  val imageHeight = bitmap.height.toDouble()
207
225
 
@@ -270,9 +288,29 @@ override fun processFrame(frame: HybridFrameSpec) {
270
288
  // Exercise Logic Engine
271
289
  // ═══════════════════════════════════════════════════════════
272
290
 
273
- private fun processExerciseLogic() {
274
- val config = exerciseConfig ?: return
275
- if (_landmarks.isEmpty()) return
291
+ private fun processExerciseLogic() {
292
+ val config = exerciseConfig ?: return
293
+ if (_landmarks.isEmpty()) return
294
+
295
+ // Posture gate with hysteresis
296
+ if (!isPostureValid(config.postureFamily)) {
297
+ consecutivePostureFailures++
298
+ if (consecutivePostureFailures >= postureFailureThreshold) {
299
+ if (!postureWasLost) {
300
+ postureWasLost = true
301
+ onPostureLost?.invoke()
302
+ }
303
+ _currentPhase = ExercisePhase.UNKNOWN
304
+ phaseHistory.clear()
305
+ }
306
+ return
307
+ }
308
+
309
+ consecutivePostureFailures = 0
310
+ if (postureWasLost) {
311
+ postureWasLost = false
312
+ onPostureRegained?.invoke()
313
+ }
276
314
 
277
315
  val currentAngles = mutableMapOf<String, Double>()
278
316
  val angleSnapshots = mutableListOf<AngleSnapshot>()
@@ -511,6 +549,83 @@ override fun processFrame(frame: HybridFrameSpec) {
511
549
  onSessionComplete?.invoke(result)
512
550
  }
513
551
 
552
+ // ═══════════════════════════════════════════════════════════
553
+ // Orientation Helpers
554
+ // ═══════════════════════════════════════════════════════════
555
+
556
+ private fun rotationDegreesFromFrame(frame: HybridFrameSpec): Int {
557
+ return when (frame.orientation.name.lowercase()) {
558
+ "up" -> 0
559
+ "right" -> 90
560
+ "down" -> 180
561
+ "left" -> 270
562
+ else -> 0
563
+ }
564
+ }
565
+
566
+ // ═══════════════════════════════════════════════════════════
567
+ // Posture Gates
568
+ // ═══════════════════════════════════════════════════════════
569
+
570
+ private func isPostureValid(_ family: String) -> Bool {
571
+ guard _landmarks.count >= 33 else { return false }
572
+
573
+ let visThreshold = exerciseConfig?.visibilityThreshold ?? 0.3
574
+
575
+ if (_landmarks.size < 33) return false
576
+
577
+ val ls = _landmarks[11]; val rs = _landmarks[12]
578
+ val lh = _landmarks[23]; val rh = _landmarks[24]
579
+ val lk = _landmarks[25]; val rk = _landmarks[26]
580
+ val la = _landmarks[27]; val ra = _landmarks[28]
581
+
582
+ val keyVisible = ls.visibility > 0.3 && rs.visibility > 0.3 &&
583
+ lh.visibility > 0.3 && rh.visibility > 0.3
584
+ if (!keyVisible) return false
585
+
586
+ val shoulderY = (ls.y + rs.y) / 2
587
+ val hipY = (lh.y + rh.y) / 2
588
+ val shoulderX = (ls.x + rs.x) / 2
589
+ val hipX = (lh.x + rh.x) / 2
590
+
591
+ val kneesVisible = lk.visibility > 0.3 && rk.visibility > 0.3
592
+ val anklesVisible = la.visibility > 0.3 && ra.visibility > 0.3
593
+ val kneeY = if (kneesVisible) (lk.y + rk.y) / 2 else hipY
594
+ val ankleY = if (anklesVisible) (la.y + ra.y) / 2 else kneeY
595
+
596
+ return when (family) {
597
+ "horizontalProne" -> {
598
+ val ys = listOf(shoulderY, hipY, ankleY)
599
+ (ys.max() - ys.min()) < 0.25
600
+ }
601
+ "standingUpright" -> {
602
+ if (!kneesVisible) false
603
+ else shoulderY < hipY - 0.08 &&
604
+ hipY < kneeY + 0.05 &&
605
+ (if (anklesVisible) kneeY < ankleY else true)
606
+ }
607
+ "seated" -> {
608
+ if (!kneesVisible) false
609
+ else shoulderY < hipY - 0.05 && kotlin.math.abs(hipY - kneeY) < 0.20
610
+ }
611
+ "supine" -> {
612
+ val ys = listOf(shoulderY, hipY, ankleY)
613
+ (ys.max() - ys.min()) < 0.25
614
+ }
615
+ "sidePlank" -> {
616
+ val ySpread = kotlin.math.abs(shoulderY - hipY)
617
+ val shoulderHipDx = kotlin.math.abs(shoulderX - hipX)
618
+ ySpread < 0.20 && shoulderHipDx < 0.15
619
+ }
620
+ "inverted" -> {
621
+ if (!anklesVisible) false
622
+ else hipY < shoulderY && hipY < ankleY
623
+ }
624
+ "none" -> true
625
+ else -> true
626
+ }
627
+ }
628
+
514
629
  // ═══════════════════════════════════════════════════════════
515
630
  // Countdown
516
631
  // ═══════════════════════════════════════════════════════════
@@ -549,6 +664,8 @@ override fun processFrame(frame: HybridFrameSpec) {
549
664
  targetReps = 0.0
550
665
  countdownSeconds = 0.0
551
666
  frameCount = 0
667
+ consecutivePostureFailures = 0
668
+ postureWasLost = false
552
669
  synchronized(landmarkLock) {
553
670
  cachedLandmarks = emptyArray()
554
671
  }
@@ -70,6 +70,11 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
70
70
  private var allRepDurations: [Double] = []
71
71
  private var allRepFormScores: [Double] = []
72
72
 
73
+ // ─── Posture Gate ──────────────────────────────────────────
74
+ private var consecutivePostureFailures: Int = 0
75
+ private let postureFailureThreshold: Int = 10 // ~1s at 30fps with throttle=3
76
+ private var postureWasLost = false
77
+
73
78
  // ─── Pose Tracking ──────────────────────────────────────────
74
79
  private var poseWasLost = false
75
80
 
@@ -85,6 +90,8 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
85
90
  var onPoseLost: (() -> Void)?
86
91
  var onPoseRegained: (() -> Void)?
87
92
  var onSessionComplete: ((_ result: SessionResult) -> Void)?
93
+ var onPostureLost: (() -> Void)?
94
+ var onPostureRegained: (() -> Void)?
88
95
 
89
96
  // ─── Hold Tracking ──────────────────────────────────────────
90
97
  private var holdStartTime: Date?
@@ -108,6 +115,12 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
108
115
  resetSession()
109
116
  }
110
117
 
118
+ func isReady() throws -> Bool {
119
+ guard let config = exerciseConfig else { return false }
120
+ guard !_landmarks.isEmpty else { return false }
121
+ return isPostureValid(config.postureFamily)
122
+ }
123
+
111
124
  // ═══════════════════════════════════════════════════════════
112
125
  // MARK: - Exercise Setup
113
126
  // ═══════════════════════════════════════════════════════════
@@ -151,12 +164,23 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
151
164
  completeSession()
152
165
  }
153
166
 
167
+ private static func cgOrientation(orientation: CameraOrientation, isMirrored: Bool) -> CGImagePropertyOrientation {
168
+ switch orientation {
169
+ case .up: return isMirrored ? .upMirrored : .up
170
+ case .down: return isMirrored ? .downMirrored : .down
171
+ case .left: return isMirrored ? .leftMirrored : .left
172
+ case .right: return isMirrored ? .rightMirrored : .right
173
+ @unknown default: return .up
174
+ }
175
+ }
176
+
154
177
  // ═══════════════════════════════════════════════════════════
155
178
  // MARK: - Frame Processing (Apple Vision)
156
179
  // ═══════════════════════════════════════════════════════════
157
180
 
158
181
  func processFrame(frame: any HybridFrameSpec) throws {
159
182
  guard _status == .active || _status == .countdown else { return }
183
+
160
184
  guard isInitialized else { return }
161
185
 
162
186
  // Frame throttle
@@ -173,9 +197,11 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
173
197
  // Create Vision request
174
198
  let request = VNDetectHumanBodyPoseRequest()
175
199
 
176
- // Run synchronously on this frame processor thread
177
- let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, options: [:])
200
+ print("[PoseExercise] orientation=\(frame.orientation) isMirrored=\(frame.isMirrored) type=\(type(of: frame.orientation))")
178
201
 
202
+ let cgOrient = Self.cgOrientation(orientation: frame.orientation, isMirrored: frame.isMirrored)
203
+ let handler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: cgOrient, options: [:])
204
+
179
205
  do {
180
206
  try handler.perform([request])
181
207
 
@@ -241,13 +267,37 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
241
267
  // MARK: - Exercise Logic Engine
242
268
  // ═══════════════════════════════════════════════════════════
243
269
 
244
- private func processExerciseLogic() {
245
- guard let config = exerciseConfig else { return }
246
- guard !_landmarks.isEmpty else { return }
270
+ private func processExerciseLogic() {
271
+
272
+ guard let config = exerciseConfig else { return }
273
+ guard !_landmarks.isEmpty else { return }
274
+
275
+ // Posture gate with hysteresis
276
+ if !isPostureValid(family: config.postureFamily, threshold: config.visibilityThreshold) {
277
+ consecutivePostureFailures += 1
278
+ if consecutivePostureFailures >= postureFailureThreshold {
279
+ if !postureWasLost {
280
+ postureWasLost = true
281
+ onPostureLost?()
282
+ }
283
+ _currentPhase = .unknown
284
+ phaseHistory = []
285
+ }
286
+ return
287
+ }
288
+
289
+ consecutivePostureFailures = 0
290
+
291
+ if postureWasLost {
292
+ postureWasLost = false
293
+ onPostureRegained?()
294
+ }
247
295
 
248
296
  var currentAngles: [String: Double] = [:]
249
297
  var angleSnapshots: [AngleSnapshot] = []
250
298
 
299
+ let visThreshold = config.visibilityThreshold
300
+
251
301
  for angleDef in config.angles {
252
302
  let a = Int(angleDef.landmarkA)
253
303
  let b = Int(angleDef.landmarkB)
@@ -255,10 +305,10 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
255
305
 
256
306
  guard a < _landmarks.count, b < _landmarks.count, c < _landmarks.count else { continue }
257
307
 
258
- // Only calculate if all three landmarks have reasonable confidence
259
- guard _landmarks[a].visibility > 0.3,
260
- _landmarks[b].visibility > 0.3,
261
- _landmarks[c].visibility > 0.3 else { continue }
308
+ guard _landmarks[a].visibility > visThreshold,
309
+ _landmarks[b].visibility > visThreshold,
310
+ _landmarks[c].visibility > visThreshold else { continue }
311
+
262
312
 
263
313
  let angle = calculateAngle(
264
314
  pointA: _landmarks[a],
@@ -293,6 +343,71 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
293
343
  }
294
344
  }
295
345
 
346
+ // ═══════════════════════════════════════════════════════════
347
+ // MARK: - Posture Gates
348
+ // ═══════════════════════════════════════════════════════════
349
+
350
+ private func isPostureValid(_ family: String) -> Bool {
351
+ guard _landmarks.count >= 33 else { return false }
352
+
353
+ let ls = _landmarks[11], rs = _landmarks[12]
354
+ let lh = _landmarks[23], rh = _landmarks[24]
355
+ let lk = _landmarks[25], rk = _landmarks[26]
356
+ let la = _landmarks[27], ra = _landmarks[28]
357
+
358
+ let key = [ls, rs, lh, rh]
359
+ guard key.allSatisfy({ $0.visibility > 0.3 }) else { return false }
360
+
361
+ let shoulderY = (ls.y + rs.y) / 2
362
+ let hipY = (lh.y + rh.y) / 2
363
+ let shoulderX = (ls.x + rs.x) / 2
364
+ let hipX = (lh.x + rh.x) / 2
365
+
366
+ let kneesVisible = lk.visibility > 0.3 && rk.visibility > 0.3
367
+ let anklesVisible = la.visibility > 0.3 && ra.visibility > 0.3
368
+ let kneeY = kneesVisible ? (lk.y + rk.y) / 2 : hipY
369
+ let ankleY = anklesVisible ? (la.y + ra.y) / 2 : kneeY
370
+
371
+ switch family {
372
+ case "horizontalProne":
373
+ let ys = [shoulderY, hipY, ankleY]
374
+ let spread = (ys.max() ?? 0) - (ys.min() ?? 0)
375
+ return spread < 0.25
376
+
377
+ case "standingUpright":
378
+ guard kneesVisible else { return false }
379
+ return shoulderY < hipY - 0.08
380
+ && hipY < kneeY + 0.05
381
+ && (anklesVisible ? kneeY < ankleY : true)
382
+
383
+ case "seated":
384
+ guard kneesVisible else { return false }
385
+ return shoulderY < hipY - 0.05
386
+ && abs(hipY - kneeY) < 0.20
387
+
388
+ case "supine":
389
+ let ys = [shoulderY, hipY, ankleY]
390
+ let spread = (ys.max() ?? 0) - (ys.min() ?? 0)
391
+ return spread < 0.25
392
+
393
+ case "sidePlank":
394
+ let ys = [shoulderY, hipY]
395
+ let ySpread = (ys.max() ?? 0) - (ys.min() ?? 0)
396
+ let shoulderHipDx = abs(shoulderX - hipX)
397
+ return ySpread < 0.20 && shoulderHipDx < 0.15
398
+
399
+ case "inverted":
400
+ guard anklesVisible else { return false }
401
+ return hipY < shoulderY && hipY < ankleY
402
+
403
+ case "none":
404
+ return true
405
+
406
+ default:
407
+ return true
408
+ }
409
+ }
410
+
296
411
  // ═══════════════════════════════════════════════════════════
297
412
  // MARK: - Angle Calculation
298
413
  // ═══════════════════════════════════════════════════════════
@@ -547,6 +662,8 @@ class NitroPoseExercises: HybridNitroPoseExercisesSpec {
547
662
  countdownSeconds = 0
548
663
  countdownTimer?.invalidate()
549
664
  countdownTimer = nil
550
- frameCount = 0
665
+ frameCount = 0,
666
+ consecutivePostureFailures = 0
667
+ postureWasLost = false
551
668
  }
552
- }
669
+ }
@@ -1 +1 @@
1
- {"version":3,"names":["NitroModules","nitroPoseExercises","createHybridObject"],"sourceRoot":"../../src","sources":["NitroPoseExercises.nitro.ts"],"mappings":";;AAAA,SAA4BA,YAAY,QAAQ,4BAA4B;;AAI5E;;AAUA;;AASA;;AAmCA;;AAmCA;;AAwCA,MAAMC,kBAAkB,GACtBD,YAAY,CAACE,kBAAkB,CAAqB,cAAc,CAAC;AAErE,SAASD,kBAAkB","ignoreList":[]}
1
+ {"version":3,"names":["NitroModules","nitroPoseExercises","createHybridObject"],"sourceRoot":"../../src","sources":["NitroPoseExercises.nitro.ts"],"mappings":";;AAAA,SAA4BA,YAAY,QAAQ,4BAA4B;;AAI5E;;AAqBA;;AASA;;AAsCA;;AAmCA;;AA4CA,MAAMC,kBAAkB,GACtBD,YAAY,CAACE,kBAAkB,CAAqB,cAAc,CAAC;AAErE,SAASD,kBAAkB","ignoreList":[]}
@@ -7,6 +7,9 @@
7
7
  export const BICEP_CURL_CONFIG = {
8
8
  name: 'Bicep Curl',
9
9
  type: 'rep',
10
+ postureFamily: 'standingUpright',
11
+ visibilityThreshold: 0.2,
12
+ cameraAngle: 'front',
10
13
  angles: [{
11
14
  name: 'leftElbow',
12
15
  landmarkA: 11,
@@ -1 +1 @@
1
- {"version":3,"names":["BICEP_CURL_CONFIG","name","type","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/bicep-curl.ts"],"mappings":";;AAEA;AACA;AACA;;AAEA,OAAO,MAAMA,iBAAiC,GAAG;EAC/CC,IAAI,EAAE,YAAY;EAClBC,IAAI,EAAE,KAAK;EACXC,MAAM,EAAE,CACN;IACEF,IAAI,EAAE,WAAW;IACjBG,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACEL,IAAI,EAAE,YAAY;IAClBG,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACEL,IAAI,EAAE,cAAc;IACpBG,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,CACF;EACDC,MAAM,EAAE,CACN;IACEC,KAAK,EAAE,MAAM;IACbC,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEH,KAAK,EAAE,IAAI;IACXC,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;EACnCC,SAAS,EAAE,CACT;IACEZ,IAAI,EAAE,YAAY;IAClBa,OAAO,EAAE,uCAAuC;IAChDC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,cAAc;IACzBC,QAAQ,EAAE,CAAC;IACXC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEV,IAAI,EAAE,UAAU;IAChBa,OAAO,EAAE,oCAAoC;IAC7CC,QAAQ,EAAE,OAAO;IACjBN,SAAS,EAAE,cAAc;IACzBC,QAAQ,EAAE,CAAC;IACXC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["BICEP_CURL_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/bicep-curl.ts"],"mappings":";;AAEA;AACA;AACA;;AAEA,OAAO,MAAMA,iBAAiC,GAAG;EAC/CC,IAAI,EAAE,YAAY;EAClBC,IAAI,EAAE,KAAK;EACXC,aAAa,EAAE,iBAAiB;EAChCC,mBAAmB,EAAE,GAAG;EACxBC,WAAW,EAAE,OAAO;EACpBC,MAAM,EAAE,CACN;IACEL,IAAI,EAAE,WAAW;IACjBM,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACER,IAAI,EAAE,YAAY;IAClBM,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACER,IAAI,EAAE,cAAc;IACpBM,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,CACF;EACDC,MAAM,EAAE,CACN;IACEC,KAAK,EAAE,MAAM;IACbC,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEH,KAAK,EAAE,IAAI;IACXC,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;EACnCC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,YAAY;IAClBgB,OAAO,EAAE,uCAAuC;IAChDC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,cAAc;IACzBC,QAAQ,EAAE,CAAC;IACXC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEb,IAAI,EAAE,UAAU;IAChBgB,OAAO,EAAE,oCAAoC;IAC7CC,QAAQ,EAAE,OAAO;IACjBN,SAAS,EAAE,cAAc;IACzBC,QAAQ,EAAE,CAAC;IACXC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ export const BOAT_POSE_CONFIG = {
4
+ name: 'Boat Pose (Navasana)',
5
+ type: 'hold',
6
+ postureFamily: 'seated',
7
+ visibilityThreshold: 0.3,
8
+ cameraAngle: 'side',
9
+ angles: [{
10
+ name: 'hipFlexion',
11
+ landmarkA: 11,
12
+ landmarkB: 23,
13
+ landmarkC: 25
14
+ }, {
15
+ name: 'kneeAngle',
16
+ landmarkA: 23,
17
+ landmarkB: 25,
18
+ landmarkC: 27
19
+ }],
20
+ phases: [{
21
+ phase: 'hold',
22
+ angleName: 'hipFlexion',
23
+ minAngle: 60,
24
+ maxAngle: 110
25
+ }],
26
+ repSequence: [],
27
+ formRules: [{
28
+ name: 'backRounding',
29
+ message: "Lengthen your spine — don't round your back",
30
+ severity: 'warning',
31
+ angleName: 'hipFlexion',
32
+ minAngle: 60,
33
+ maxAngle: 110
34
+ }, {
35
+ name: 'legsDropping',
36
+ message: 'Keep your legs lifted',
37
+ severity: 'warning',
38
+ angleName: 'kneeAngle',
39
+ minAngle: 150,
40
+ maxAngle: 180
41
+ }],
42
+ holdDurationMs: 30000
43
+ };
44
+ //# sourceMappingURL=boat-pose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["BOAT_POSE_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/boat-pose.ts"],"mappings":";;AAEA,OAAO,MAAMA,gBAAgC,GAAG;EAC9CC,IAAI,EAAE,sBAAsB;EAC5BC,IAAI,EAAE,MAAM;EACZC,aAAa,EAAE,QAAQ;EACvBC,mBAAmB,EAAE,GAAG;EACxBC,WAAW,EAAE,MAAM;EACnBC,MAAM,EAAE,CACN;IAAEL,IAAI,EAAE,YAAY;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,EACnE;IAAER,IAAI,EAAE,WAAW;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,CACnE;EACDC,MAAM,EAAE,CACN;IAAEC,KAAK,EAAE,MAAM;IAAEC,SAAS,EAAE,YAAY;IAAEC,QAAQ,EAAE,EAAE;IAAEC,QAAQ,EAAE;EAAI,CAAC,CACxE;EACDC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,cAAc;IACpBgB,OAAO,EAAE,6CAA6C;IACtDC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,YAAY;IACvBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEb,IAAI,EAAE,cAAc;IACpBgB,OAAO,EAAE,uBAAuB;IAChCC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ export const BOW_POSE_CONFIG = {
4
+ name: 'Bow Pose (Dhanurasana)',
5
+ type: 'hold',
6
+ postureFamily: 'horizontalProne',
7
+ visibilityThreshold: 0.25,
8
+ cameraAngle: 'side',
9
+ angles: [{
10
+ name: 'kneeAngle',
11
+ landmarkA: 23,
12
+ landmarkB: 25,
13
+ landmarkC: 27
14
+ }, {
15
+ name: 'shoulderExtension',
16
+ landmarkA: 23,
17
+ landmarkB: 11,
18
+ landmarkC: 15
19
+ }],
20
+ phases: [{
21
+ phase: 'hold',
22
+ angleName: 'kneeAngle',
23
+ minAngle: 50,
24
+ maxAngle: 100
25
+ }],
26
+ repSequence: [],
27
+ formRules: [{
28
+ name: 'kneesTooWide',
29
+ message: 'Keep your knees hip-width apart',
30
+ severity: 'warning',
31
+ angleName: 'kneeAngle',
32
+ minAngle: 50,
33
+ maxAngle: 100
34
+ }],
35
+ holdDurationMs: 30000
36
+ };
37
+ //# sourceMappingURL=bow-pose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["BOW_POSE_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/bow-pose.ts"],"mappings":";;AACA,OAAO,MAAMA,eAA+B,GAAG;EAC7CC,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,MAAM;EACZC,aAAa,EAAE,iBAAiB;EAChCC,mBAAmB,EAAE,IAAI;EACzBC,WAAW,EAAE,MAAM;EACnBC,MAAM,EAAE,CACN;IAAEL,IAAI,EAAE,WAAW;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,EAClE;IAAER,IAAI,EAAE,mBAAmB;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,CAC3E;EACDC,MAAM,EAAE,CACN;IAAEC,KAAK,EAAE,MAAM;IAAEC,SAAS,EAAE,WAAW;IAAEC,QAAQ,EAAE,EAAE;IAAEC,QAAQ,EAAE;EAAI,CAAC,CACvE;EACDC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,cAAc;IACpBgB,OAAO,EAAE,iCAAiC;IAC1CC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ export const BRIDGE_POSE_CONFIG = {
4
+ name: 'Bridge Pose (Setu Bandhasana)',
5
+ type: 'hold',
6
+ postureFamily: 'supine',
7
+ visibilityThreshold: 0.3,
8
+ cameraAngle: 'side',
9
+ angles: [{
10
+ name: 'hipExtension',
11
+ landmarkA: 11,
12
+ landmarkB: 23,
13
+ landmarkC: 25
14
+ }, {
15
+ name: 'kneeAngle',
16
+ landmarkA: 23,
17
+ landmarkB: 25,
18
+ landmarkC: 27
19
+ }],
20
+ phases: [{
21
+ phase: 'hold',
22
+ angleName: 'kneeAngle',
23
+ minAngle: 80,
24
+ maxAngle: 110
25
+ }],
26
+ repSequence: [],
27
+ formRules: [{
28
+ name: 'hipsLow',
29
+ message: 'Push your hips up higher',
30
+ severity: 'warning',
31
+ angleName: 'hipExtension',
32
+ minAngle: 140,
33
+ maxAngle: 180
34
+ }],
35
+ holdDurationMs: 30000
36
+ };
37
+ //# sourceMappingURL=bridge-pose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["BRIDGE_POSE_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/bridge-pose.ts"],"mappings":";;AAEA,OAAO,MAAMA,kBAAkC,GAAG;EAChDC,IAAI,EAAE,+BAA+B;EACrCC,IAAI,EAAE,MAAM;EACZC,aAAa,EAAE,QAAQ;EACvBC,mBAAmB,EAAE,GAAG;EACxBC,WAAW,EAAE,MAAM;EACnBC,MAAM,EAAE,CACN;IAAEL,IAAI,EAAE,cAAc;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,EACrE;IAAER,IAAI,EAAE,WAAW;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,CACnE;EACDC,MAAM,EAAE,CACN;IAAEC,KAAK,EAAE,MAAM;IAAEC,SAAS,EAAE,WAAW;IAAEC,QAAQ,EAAE,EAAE;IAAEC,QAAQ,EAAE;EAAI,CAAC,CACvE;EACDC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,SAAS;IACfgB,OAAO,EAAE,0BAA0B;IACnCC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,cAAc;IACzBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ export const CALF_RAISE_CONFIG = {
4
+ name: 'Calf Raise',
5
+ type: 'rep',
6
+ postureFamily: 'standingUpright',
7
+ visibilityThreshold: 0.2,
8
+ cameraAngle: 'front',
9
+ angles: [{
10
+ name: 'leftAnkle',
11
+ landmarkA: 25,
12
+ landmarkB: 27,
13
+ landmarkC: 31
14
+ }, {
15
+ name: 'rightAnkle',
16
+ landmarkA: 26,
17
+ landmarkB: 28,
18
+ landmarkC: 32
19
+ }, {
20
+ name: 'leftKnee',
21
+ landmarkA: 23,
22
+ landmarkB: 25,
23
+ landmarkC: 27
24
+ }],
25
+ phases: [{
26
+ phase: 'down',
27
+ angleName: 'leftAnkle',
28
+ minAngle: 70,
29
+ maxAngle: 95
30
+ }, {
31
+ phase: 'up',
32
+ angleName: 'leftAnkle',
33
+ minAngle: 110,
34
+ maxAngle: 150
35
+ }],
36
+ repSequence: ['down', 'up', 'down'],
37
+ formRules: [{
38
+ name: 'kneesBending',
39
+ message: 'Keep your legs straight',
40
+ severity: 'warning',
41
+ angleName: 'leftKnee',
42
+ minAngle: 165,
43
+ maxAngle: 180
44
+ }],
45
+ holdDurationMs: 0
46
+ };
47
+ //# sourceMappingURL=calf-raise.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["CALF_RAISE_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/calf-raise.ts"],"mappings":";;AAEA,OAAO,MAAMA,iBAAiC,GAAG;EAC/CC,IAAI,EAAE,YAAY;EAClBC,IAAI,EAAE,KAAK;EACXC,aAAa,EAAE,iBAAiB;EAChCC,mBAAmB,EAAE,GAAG;EACxBC,WAAW,EAAE,OAAO;EACpBC,MAAM,EAAE,CACN;IAAEL,IAAI,EAAE,WAAW;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,EAClE;IAAER,IAAI,EAAE,YAAY;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,EACnE;IAAER,IAAI,EAAE,UAAU;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,CAClE;EACDC,MAAM,EAAE,CACN;IAAEC,KAAK,EAAE,MAAM;IAAEC,SAAS,EAAE,WAAW;IAAEC,QAAQ,EAAE,EAAE;IAAEC,QAAQ,EAAE;EAAG,CAAC,EACrE;IAAEH,KAAK,EAAE,IAAI;IAAEC,SAAS,EAAE,WAAW;IAAEC,QAAQ,EAAE,GAAG;IAAEC,QAAQ,EAAE;EAAI,CAAC,CACtE;EACDC,WAAW,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;EACnCC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,cAAc;IACpBgB,OAAO,EAAE,yBAAyB;IAClCC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,UAAU;IACrBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ export const CAMEL_POSE_CONFIG = {
4
+ name: 'Camel Pose (Ustrasana)',
5
+ type: 'hold',
6
+ postureFamily: 'seated',
7
+ visibilityThreshold: 0.3,
8
+ cameraAngle: 'side',
9
+ angles: [{
10
+ name: 'hipExtension',
11
+ landmarkA: 11,
12
+ landmarkB: 23,
13
+ landmarkC: 25
14
+ }, {
15
+ name: 'kneeAngle',
16
+ landmarkA: 23,
17
+ landmarkB: 25,
18
+ landmarkC: 27
19
+ }],
20
+ phases: [{
21
+ phase: 'hold',
22
+ angleName: 'hipExtension',
23
+ minAngle: 120,
24
+ maxAngle: 165
25
+ }],
26
+ repSequence: [],
27
+ formRules: [{
28
+ name: 'kneesTooWide',
29
+ message: 'Keep knees hip-width apart',
30
+ severity: 'warning',
31
+ angleName: 'kneeAngle',
32
+ minAngle: 80,
33
+ maxAngle: 100
34
+ }],
35
+ holdDurationMs: 30000
36
+ };
37
+ //# sourceMappingURL=camel-pose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["CAMEL_POSE_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/camel-pose.ts"],"mappings":";;AACA,OAAO,MAAMA,iBAAiC,GAAG;EAC/CC,IAAI,EAAE,wBAAwB;EAC9BC,IAAI,EAAE,MAAM;EACZC,aAAa,EAAE,QAAQ;EACvBC,mBAAmB,EAAE,GAAG;EACxBC,WAAW,EAAE,MAAM;EACnBC,MAAM,EAAE,CACN;IAAEL,IAAI,EAAE,cAAc;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,EACrE;IAAER,IAAI,EAAE,WAAW;IAAEM,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE,EAAE;IAAEC,SAAS,EAAE;EAAG,CAAC,CACnE;EACDC,MAAM,EAAE,CACN;IAAEC,KAAK,EAAE,MAAM;IAAEC,SAAS,EAAE,cAAc;IAAEC,QAAQ,EAAE,GAAG;IAAEC,QAAQ,EAAE;EAAI,CAAC,CAC3E;EACDC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,cAAc;IACpBgB,OAAO,EAAE,4BAA4B;IACrCC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,WAAW;IACtBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE;AAClB,CAAC","ignoreList":[]}
@@ -8,6 +8,9 @@
8
8
  export const CHAIR_POSE_CONFIG = {
9
9
  name: 'Chair Pose (Utkatasana)',
10
10
  type: 'hold',
11
+ postureFamily: 'standingUpright',
12
+ visibilityThreshold: 0.4,
13
+ cameraAngle: 'side',
11
14
  angles: [{
12
15
  name: 'leftKnee',
13
16
  landmarkA: 23,
@@ -1 +1 @@
1
- {"version":3,"names":["CHAIR_POSE_CONFIG","name","type","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/chair-pose.ts"],"mappings":";;AAEA;AACA;AACA;AACA;;AAEA,OAAO,MAAMA,iBAAiC,GAAG;EAC/CC,IAAI,EAAE,yBAAyB;EAC/BC,IAAI,EAAE,MAAM;EACZC,MAAM,EAAE,CACN;IACEF,IAAI,EAAE,UAAU;IAChBG,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACEL,IAAI,EAAE,SAAS;IACfG,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACEL,IAAI,EAAE,SAAS;IACfG,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,CACF;EACDC,MAAM,EAAE,CACN;IACEC,KAAK,EAAE,MAAM;IACbC,SAAS,EAAE,UAAU;IACrBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,CACT;IACEZ,IAAI,EAAE,kBAAkB;IACxBa,OAAO,EAAE,mCAAmC;IAC5CC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,UAAU;IACrBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEV,IAAI,EAAE,gBAAgB;IACtBa,OAAO,EAAE,qDAAqD;IAC9DC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,SAAS;IACpBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEV,IAAI,EAAE,WAAW;IACjBa,OAAO,EAAE,6BAA6B;IACtCC,QAAQ,EAAE,MAAM;IAChBN,SAAS,EAAE,SAAS;IACpBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE,KAAK,CAAE;AACzB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["CHAIR_POSE_CONFIG","name","type","postureFamily","visibilityThreshold","cameraAngle","angles","landmarkA","landmarkB","landmarkC","phases","phase","angleName","minAngle","maxAngle","repSequence","formRules","message","severity","holdDurationMs"],"sourceRoot":"../../../src","sources":["config/chair-pose.ts"],"mappings":";;AAEA;AACA;AACA;AACA;;AAEA,OAAO,MAAMA,iBAAiC,GAAG;EAC/CC,IAAI,EAAE,yBAAyB;EAC/BC,IAAI,EAAE,MAAM;EACZC,aAAa,EAAE,iBAAiB;EAChCC,mBAAmB,EAAE,GAAG;EACxBC,WAAW,EAAE,MAAM;EACnBC,MAAM,EAAE,CACN;IACEL,IAAI,EAAE,UAAU;IAChBM,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACER,IAAI,EAAE,SAAS;IACfM,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,EACD;IACER,IAAI,EAAE,SAAS;IACfM,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE;IAAE;IACfC,SAAS,EAAE,EAAE,CAAE;EACjB,CAAC,CACF;EACDC,MAAM,EAAE,CACN;IACEC,KAAK,EAAE,MAAM;IACbC,SAAS,EAAE,UAAU;IACrBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,CACT;IACEf,IAAI,EAAE,kBAAkB;IACxBgB,OAAO,EAAE,mCAAmC;IAC5CC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,UAAU;IACrBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEb,IAAI,EAAE,gBAAgB;IACtBgB,OAAO,EAAE,qDAAqD;IAC9DC,QAAQ,EAAE,SAAS;IACnBN,SAAS,EAAE,SAAS;IACpBC,QAAQ,EAAE,EAAE;IACZC,QAAQ,EAAE;EACZ,CAAC,EACD;IACEb,IAAI,EAAE,WAAW;IACjBgB,OAAO,EAAE,6BAA6B;IACtCC,QAAQ,EAAE,MAAM;IAChBN,SAAS,EAAE,SAAS;IACpBC,QAAQ,EAAE,GAAG;IACbC,QAAQ,EAAE;EACZ,CAAC,CACF;EACDK,cAAc,EAAE,KAAK,CAAE;AACzB,CAAC","ignoreList":[]}