react-native-nitro-pose-exercises 1.1.14 → 1.1.15
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.
- package/android/src/main/java/com/margelo/nitro/nitroposeexercises/NitroPoseExercises.kt +127 -97
- package/ios/NitroPoseExercises.swift +61 -49
- package/lib/module/NitroPoseExercises.nitro.js.map +1 -1
- package/lib/typescript/src/NitroPoseExercises.nitro.d.ts +1 -1
- package/lib/typescript/src/NitroPoseExercises.nitro.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridNitroPoseExercisesSpec.cpp +3 -5
- package/nitrogen/generated/android/c++/JHybridNitroPoseExercisesSpec.hpp +1 -1
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroposeexercises/HybridNitroPoseExercisesSpec.kt +1 -2
- package/nitrogen/generated/ios/NitroPoseExercises-Swift-Cxx-Umbrella.hpp +0 -1
- package/nitrogen/generated/ios/c++/HybridNitroPoseExercisesSpecSwift.hpp +2 -6
- package/nitrogen/generated/ios/swift/HybridNitroPoseExercisesSpec.swift +1 -1
- package/nitrogen/generated/ios/swift/HybridNitroPoseExercisesSpec_cxx.swift +6 -2
- package/nitrogen/generated/shared/c++/HybridNitroPoseExercisesSpec.hpp +1 -2
- package/package.json +1 -1
- package/src/NitroPoseExercises.nitro.ts +10 -7
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
package com.margelo.nitro.nitroposeexercises
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import com.margelo.nitro.camera.HybridFrameSpec
|
|
4
|
+
import com.margelo.nitro.camera.public.NativeFrame
|
|
5
|
+
import com.google.android.gms.tasks.Tasks
|
|
6
|
+
import java.util.concurrent.TimeUnit
|
|
7
|
+
|
|
8
|
+
// import android.graphics.Matrix
|
|
4
9
|
import androidx.annotation.Keep
|
|
5
10
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
6
11
|
import com.google.mlkit.vision.pose.PoseDetection
|
|
@@ -14,15 +19,13 @@ import kotlin.math.max
|
|
|
14
19
|
import kotlin.math.min
|
|
15
20
|
import kotlin.math.sqrt
|
|
16
21
|
|
|
17
|
-
import android.media.Image
|
|
18
|
-
import android.graphics.Bitmap
|
|
22
|
+
// import android.media.Image
|
|
23
|
+
// import android.graphics.Bitmap
|
|
19
24
|
import com.google.mlkit.vision.common.InputImage
|
|
20
|
-
import com.margelo.nitro.core.ArrayBuffer
|
|
21
|
-
import java.nio.ByteBuffer
|
|
25
|
+
// import com.margelo.nitro.core.ArrayBuffer
|
|
26
|
+
// import java.nio.ByteBuffer
|
|
22
27
|
|
|
23
|
-
import java.nio.ByteOrder
|
|
24
|
-
|
|
25
|
-
import com.margelo.nitro.camera.HybridFrameSpec
|
|
28
|
+
// import java.nio.ByteOrder
|
|
26
29
|
|
|
27
30
|
@Keep
|
|
28
31
|
@DoNotStrip
|
|
@@ -211,92 +214,86 @@ override fun isReady(): Boolean {
|
|
|
211
214
|
// Frame Processing (ML Kit — async with cached results)
|
|
212
215
|
// ═══════════════════════════════════════════════════════════
|
|
213
216
|
|
|
217
|
+
// Reusable scratch — allocated once, never GC'd per frame
|
|
218
|
+
@Volatile private var lastProcessTime: Long = 0L
|
|
219
|
+
private val minIntervalMs: Long = 66L // ~15fps cap; bump down to 33 for ~30fps
|
|
214
220
|
|
|
221
|
+
// Time-based throttle — more reliable than frame-count under variable FPS
|
|
222
|
+
@Volatile private var lastProcessTime: Long = 0L
|
|
223
|
+
private val minIntervalMs: Long = 66L // ~15fps; lower to 33 for ~30fps once release build is fast enough
|
|
215
224
|
|
|
216
|
-
override fun processFrameAndroid(
|
|
225
|
+
override fun processFrameAndroid(frame: HybridFrameSpec) {
|
|
217
226
|
if (_status != SessionStatus.ACTIVE && _status != SessionStatus.COUNTDOWN) return
|
|
218
227
|
if (!isInitialized || poseDetector == null) return
|
|
219
228
|
|
|
220
|
-
|
|
221
|
-
if (
|
|
229
|
+
val now = System.currentTimeMillis()
|
|
230
|
+
if (now - lastProcessTime < minIntervalMs) return
|
|
231
|
+
lastProcessTime = now
|
|
222
232
|
|
|
223
|
-
val
|
|
224
|
-
val
|
|
225
|
-
val
|
|
233
|
+
val nativeFrame = frame as? NativeFrame ?: return
|
|
234
|
+
val imageProxy = nativeFrame.image ?: return
|
|
235
|
+
val mediaImage = imageProxy.image ?: return
|
|
226
236
|
|
|
227
237
|
try {
|
|
228
|
-
val
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
val
|
|
233
|
-
val
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
238
|
+
val rotation = imageProxy.imageInfo.rotationDegrees
|
|
239
|
+
val inputImage = InputImage.fromMediaImage(mediaImage, rotation)
|
|
240
|
+
|
|
241
|
+
val rotated = rotation == 90 || rotation == 270
|
|
242
|
+
val imageWidth = (if (rotated) mediaImage.height else mediaImage.width).toDouble()
|
|
243
|
+
val imageHeight = (if (rotated) mediaImage.width else mediaImage.height).toDouble()
|
|
244
|
+
|
|
245
|
+
// SYNC inference — the frame's underlying ImageProxy is only valid until
|
|
246
|
+
// VisionCamera disposes the frame after this method returns. Tasks.await
|
|
247
|
+
// blocks the worklet thread which is exactly what we want here.
|
|
248
|
+
val pose = try {
|
|
249
|
+
Tasks.await(poseDetector!!.process(inputImage), 200, TimeUnit.MILLISECONDS)
|
|
250
|
+
} catch (e: Exception) {
|
|
251
|
+
// Timeout or failure — skip this frame quietly
|
|
252
|
+
null
|
|
242
253
|
}
|
|
243
|
-
rgba.rewind()
|
|
244
|
-
|
|
245
|
-
val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
|
|
246
|
-
bitmap.copyPixelsFromBuffer(rgba)
|
|
247
254
|
|
|
248
|
-
|
|
255
|
+
if (pose == null) return
|
|
249
256
|
|
|
250
|
-
val
|
|
251
|
-
val imageWidth = (if (rotated) h else w).toDouble()
|
|
252
|
-
val imageHeight = (if (rotated) w else h).toDouble()
|
|
257
|
+
val poseLandmarks = pose.allPoseLandmarks
|
|
253
258
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (poseWasLost) {
|
|
260
|
-
poseWasLost = false
|
|
261
|
-
onPoseRegained?.invoke()
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
val landmarkArray = Array(34) { Landmark(x = 0.0, y = 0.0, z = 0.0, visibility = 0.0) }
|
|
265
|
-
|
|
266
|
-
for (poseLandmark in poseLandmarks) {
|
|
267
|
-
val mediaPipeIndex = mlKitToMediaPipeMap[poseLandmark.landmarkType] ?: continue
|
|
268
|
-
if (mediaPipeIndex >= 34) continue
|
|
259
|
+
if (poseLandmarks.isNotEmpty()) {
|
|
260
|
+
if (poseWasLost) {
|
|
261
|
+
poseWasLost = false
|
|
262
|
+
onPoseRegained?.invoke()
|
|
263
|
+
}
|
|
269
264
|
|
|
270
|
-
|
|
271
|
-
x = (poseLandmark.position3D.x / imageWidth).coerceIn(0.0, 1.0),
|
|
272
|
-
y = (poseLandmark.position3D.y / imageHeight).coerceIn(0.0, 1.0),
|
|
273
|
-
z = poseLandmark.position3D.z.toDouble(),
|
|
274
|
-
visibility = poseLandmark.inFrameLikelihood.toDouble()
|
|
275
|
-
)
|
|
276
|
-
}
|
|
265
|
+
val landmarkArray = Array(34) { Landmark(x = 0.0, y = 0.0, z = 0.0, visibility = 0.0) }
|
|
277
266
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
267
|
+
for (poseLandmark in poseLandmarks) {
|
|
268
|
+
val mediaPipeIndex = mlKitToMediaPipeMap[poseLandmark.landmarkType] ?: continue
|
|
269
|
+
if (mediaPipeIndex >= 34) continue
|
|
282
270
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
}
|
|
271
|
+
landmarkArray[mediaPipeIndex] = Landmark(
|
|
272
|
+
x = (poseLandmark.position3D.x / imageWidth).coerceIn(0.0, 1.0),
|
|
273
|
+
y = (poseLandmark.position3D.y / imageHeight).coerceIn(0.0, 1.0),
|
|
274
|
+
z = poseLandmark.position3D.z.toDouble(),
|
|
275
|
+
visibility = poseLandmark.inFrameLikelihood.toDouble()
|
|
276
|
+
)
|
|
290
277
|
}
|
|
291
|
-
|
|
292
|
-
|
|
278
|
+
|
|
279
|
+
synchronized(landmarkLock) {
|
|
280
|
+
cachedLandmarks = landmarkArray
|
|
281
|
+
_landmarks = landmarkArray
|
|
293
282
|
}
|
|
294
|
-
|
|
295
|
-
|
|
283
|
+
|
|
284
|
+
processExerciseLogic()
|
|
285
|
+
} else {
|
|
286
|
+
if (!poseWasLost) {
|
|
287
|
+
poseWasLost = true
|
|
288
|
+
onPoseLost?.invoke()
|
|
296
289
|
}
|
|
290
|
+
}
|
|
297
291
|
} catch (e: Exception) {
|
|
298
292
|
println("[PoseExercise] processFrameAndroid error: ${e.message}")
|
|
299
293
|
}
|
|
294
|
+
// NOTE: we do NOT close the ImageProxy ourselves.
|
|
295
|
+
// VisionCamera owns the frame lifecycle and will release it when
|
|
296
|
+
// frame.dispose() runs in the JS worklet after we return.
|
|
300
297
|
}
|
|
301
298
|
|
|
302
299
|
override fun processFrameIOS(frame: HybridFrameSpec) {
|
|
@@ -639,54 +636,87 @@ private fun isPostureValid(family: PostureFamily, threshold: Double): Boolean {
|
|
|
639
636
|
val lk = _landmarks[25]; val rk = _landmarks[26]
|
|
640
637
|
val la = _landmarks[27]; val ra = _landmarks[28]
|
|
641
638
|
|
|
642
|
-
//
|
|
643
|
-
val
|
|
644
|
-
|
|
645
|
-
if (!torsoVisible) return false
|
|
646
|
-
|
|
647
|
-
val shoulderY = (ls.y + rs.y) / 2
|
|
648
|
-
val hipY = (lh.y + rh.y) / 2
|
|
649
|
-
val shoulderX = (ls.x + rs.x) / 2
|
|
650
|
-
val hipX = (lh.x + rh.x) / 2
|
|
639
|
+
// Shoulders mandatory; everything below is optional for close-range framing
|
|
640
|
+
val shouldersVisible = ls.visibility > threshold && rs.visibility > threshold
|
|
641
|
+
if (!shouldersVisible) return false
|
|
651
642
|
|
|
643
|
+
val hipsVisible = lh.visibility > threshold && rh.visibility > threshold
|
|
652
644
|
val kneesVisible = lk.visibility > threshold && rk.visibility > threshold
|
|
653
645
|
val anklesVisible = la.visibility > threshold && ra.visibility > threshold
|
|
646
|
+
|
|
647
|
+
val shoulderY = (ls.y + rs.y) / 2
|
|
648
|
+
val shoulderX = (ls.x + rs.x) / 2
|
|
649
|
+
val hipY = if (hipsVisible) (lh.y + rh.y) / 2 else shoulderY
|
|
650
|
+
val hipX = if (hipsVisible) (lh.x + rh.x) / 2 else shoulderX
|
|
654
651
|
val kneeY = if (kneesVisible) (lk.y + rk.y) / 2 else hipY
|
|
655
652
|
val ankleY = if (anklesVisible) (la.y + ra.y) / 2 else kneeY
|
|
656
653
|
|
|
654
|
+
// Mirror-invariant — works for front and back camera identically
|
|
655
|
+
val shoulderWidth = kotlin.math.abs(ls.x - rs.x)
|
|
656
|
+
|
|
657
657
|
return when (family) {
|
|
658
658
|
PostureFamily.HORIZONTALPRONE, PostureFamily.SUPINE -> {
|
|
659
|
+
if (!hipsVisible) return false
|
|
660
|
+
|
|
661
|
+
// Case A: side view — shoulders/hips/(ankles) in a horizontal band
|
|
659
662
|
val ys = if (anklesVisible)
|
|
660
663
|
listOf(shoulderY, hipY, ankleY)
|
|
661
664
|
else
|
|
662
665
|
listOf(shoulderY, hipY)
|
|
663
|
-
(ys.max() - ys.min()) < 0.25
|
|
666
|
+
if ((ys.max() - ys.min()) < 0.25) return true
|
|
667
|
+
|
|
668
|
+
// Case B: front-facing prone (pushup head-on) — large y-spread,
|
|
669
|
+
// fall back to upper-body geometry
|
|
670
|
+
val le = _landmarks[13]; val re = _landmarks[14]
|
|
671
|
+
val lw = _landmarks[15]; val rw = _landmarks[16]
|
|
672
|
+
val upperBodyVisible = le.visibility > threshold && re.visibility > threshold &&
|
|
673
|
+
lw.visibility > threshold && rw.visibility > threshold
|
|
674
|
+
if (!upperBodyVisible) return false
|
|
675
|
+
|
|
676
|
+
val wristY = (lw.y + rw.y) / 2
|
|
677
|
+
wristY > shoulderY + 0.03 && shoulderWidth > 0.10
|
|
664
678
|
}
|
|
679
|
+
|
|
665
680
|
PostureFamily.STANDINGUPRIGHT -> {
|
|
666
|
-
if (
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
681
|
+
if (hipsVisible) {
|
|
682
|
+
if (kneesVisible) {
|
|
683
|
+
shoulderY < hipY - 0.05 &&
|
|
684
|
+
hipY < kneeY + 0.05 &&
|
|
685
|
+
(if (anklesVisible) kneeY < ankleY else true)
|
|
686
|
+
} else {
|
|
687
|
+
shoulderY < hipY - 0.05
|
|
688
|
+
}
|
|
670
689
|
} else {
|
|
671
|
-
|
|
690
|
+
// Hips cropped (close-range front-facing) — accept based on shoulder span
|
|
691
|
+
shoulderWidth > 0.08
|
|
672
692
|
}
|
|
673
693
|
}
|
|
694
|
+
|
|
674
695
|
PostureFamily.SEATED -> {
|
|
675
|
-
|
|
676
|
-
shoulderY < hipY - 0.05 && kotlin.math.abs(hipY - kneeY) < 0.20
|
|
677
|
-
|
|
678
|
-
|
|
696
|
+
when {
|
|
697
|
+
hipsVisible && kneesVisible -> shoulderY < hipY - 0.05 && kotlin.math.abs(hipY - kneeY) < 0.20
|
|
698
|
+
hipsVisible -> shoulderY < hipY - 0.05
|
|
699
|
+
else -> shoulderWidth > 0.08
|
|
679
700
|
}
|
|
680
701
|
}
|
|
702
|
+
|
|
681
703
|
PostureFamily.SIDEPLANK -> {
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
704
|
+
if (!hipsVisible) false
|
|
705
|
+
else {
|
|
706
|
+
val ySpread = kotlin.math.abs(shoulderY - hipY)
|
|
707
|
+
val shoulderHipDx = kotlin.math.abs(shoulderX - hipX)
|
|
708
|
+
ySpread < 0.20 && shoulderHipDx < 0.15
|
|
709
|
+
}
|
|
685
710
|
}
|
|
711
|
+
|
|
686
712
|
PostureFamily.INVERTED -> {
|
|
687
|
-
if (!anklesVisible) false
|
|
713
|
+
if (!hipsVisible || !anklesVisible) false
|
|
688
714
|
else hipY < shoulderY && hipY < ankleY
|
|
689
715
|
}
|
|
716
|
+
|
|
690
717
|
PostureFamily.NONE -> true
|
|
691
718
|
}
|
|
692
|
-
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
|
|
722
|
+
}
|
|
@@ -261,7 +261,8 @@ func processFrameIOS(frame: any HybridFrameSpec) throws {
|
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
func processFrameAndroid(buffer: ArrayBuffer, width: Double, height: Double, rotation: Double) {
|
|
264
|
+
// func processFrameAndroid(buffer: ArrayBuffer, width: Double, height: Double, rotation: Double) {
|
|
265
|
+
func processFrameAndroid(frame: any HybridFrameSpec) {
|
|
265
266
|
// no-op on iOS
|
|
266
267
|
}
|
|
267
268
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -354,74 +355,85 @@ private func isPostureValid(family: PostureFamily, threshold: Double) -> Bool {
|
|
|
354
355
|
let lk = _landmarks[25], rk = _landmarks[26]
|
|
355
356
|
let la = _landmarks[27], ra = _landmarks[28]
|
|
356
357
|
|
|
357
|
-
//
|
|
358
|
-
let
|
|
359
|
-
|
|
360
|
-
guard torsoVisible else { return false }
|
|
361
|
-
|
|
362
|
-
let shoulderY = (ls.y + rs.y) / 2
|
|
363
|
-
let hipY = (lh.y + rh.y) / 2
|
|
364
|
-
let shoulderX = (ls.x + rs.x) / 2
|
|
365
|
-
let hipX = (lh.x + rh.x) / 2
|
|
358
|
+
// Shoulders are mandatory; hips/knees/ankles are optional for close-range framing
|
|
359
|
+
let shouldersVisible = ls.visibility > threshold && rs.visibility > threshold
|
|
360
|
+
guard shouldersVisible else { return false }
|
|
366
361
|
|
|
362
|
+
let hipsVisible = lh.visibility > threshold && rh.visibility > threshold
|
|
367
363
|
let kneesVisible = lk.visibility > threshold && rk.visibility > threshold
|
|
368
364
|
let anklesVisible = la.visibility > threshold && ra.visibility > threshold
|
|
365
|
+
|
|
366
|
+
let shoulderY = (ls.y + rs.y) / 2
|
|
367
|
+
let shoulderX = (ls.x + rs.x) / 2
|
|
368
|
+
let hipY = hipsVisible ? (lh.y + rh.y) / 2 : shoulderY
|
|
369
|
+
let hipX = hipsVisible ? (lh.x + rh.x) / 2 : shoulderX
|
|
369
370
|
let kneeY = kneesVisible ? (lk.y + rk.y) / 2 : hipY
|
|
370
371
|
let ankleY = anklesVisible ? (la.y + ra.y) / 2 : kneeY
|
|
371
372
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
let ys: [Double] = anklesVisible
|
|
376
|
-
? [shoulderY, hipY, ankleY]
|
|
377
|
-
: [shoulderY, hipY]
|
|
378
|
-
let ySpread = (ys.max() ?? 0) - (ys.min() ?? 0)
|
|
379
|
-
if ySpread < 0.25 {
|
|
380
|
-
return true
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Case B: front-facing — body extends away from camera along Z.
|
|
384
|
-
// Y-spread is large (head close, feet far), so check upper-body geometry.
|
|
385
|
-
let le = _landmarks[13], re = _landmarks[14]
|
|
386
|
-
let lw = _landmarks[15], rw = _landmarks[16]
|
|
387
|
-
let upperBodyVisible = le.visibility > threshold && re.visibility > threshold
|
|
388
|
-
&& lw.visibility > threshold && rw.visibility > threshold
|
|
389
|
-
guard upperBodyVisible else { return false }
|
|
373
|
+
// Shoulder width is camera-mirror invariant: |x1 - x2| is the same
|
|
374
|
+
// whether the front camera mirror has been applied or not.
|
|
375
|
+
let shoulderWidth = (ls.x - rs.x).magnitude
|
|
390
376
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
377
|
+
switch family {
|
|
378
|
+
case .horizontalprone, .supine:
|
|
379
|
+
// Need hips to make any meaningful judgment for prone/supine
|
|
380
|
+
guard hipsVisible else { return false }
|
|
381
|
+
|
|
382
|
+
// Case A: side view — shoulders, hips, ankles in a horizontal band
|
|
383
|
+
let ys: [Double] = anklesVisible
|
|
384
|
+
? [shoulderY, hipY, ankleY]
|
|
385
|
+
: [shoulderY, hipY]
|
|
386
|
+
let ySpread = (ys.max() ?? 0) - (ys.min() ?? 0)
|
|
387
|
+
if ySpread < 0.25 {
|
|
388
|
+
return true
|
|
389
|
+
}
|
|
395
390
|
|
|
396
|
-
|
|
391
|
+
// Case B: front-facing prone (e.g. pushup viewed head-on) — body extends
|
|
392
|
+
// away along Z, so y-spread is large. Fall back to upper-body geometry.
|
|
393
|
+
let le = _landmarks[13], re = _landmarks[14]
|
|
394
|
+
let lw = _landmarks[15], rw = _landmarks[16]
|
|
395
|
+
let upperBodyVisible = le.visibility > threshold && re.visibility > threshold
|
|
396
|
+
&& lw.visibility > threshold && rw.visibility > threshold
|
|
397
|
+
guard upperBodyVisible else { return false }
|
|
398
|
+
|
|
399
|
+
let wristY = (lw.y + rw.y) / 2
|
|
400
|
+
guard wristY > shoulderY + 0.03 else { return false }
|
|
401
|
+
guard shoulderWidth > 0.10 else { return false }
|
|
402
|
+
return true
|
|
397
403
|
|
|
398
404
|
case .standingupright:
|
|
399
|
-
//
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
405
|
+
// Front-facing standing: user often crops hips/knees at close range.
|
|
406
|
+
// Use a tiered check based on what's visible.
|
|
407
|
+
if hipsVisible {
|
|
408
|
+
if kneesVisible {
|
|
409
|
+
return shoulderY < hipY - 0.05
|
|
410
|
+
&& hipY < kneeY + 0.05
|
|
411
|
+
&& (anklesVisible ? kneeY < ankleY : true)
|
|
412
|
+
}
|
|
413
|
+
return shoulderY < hipY - 0.05
|
|
406
414
|
}
|
|
415
|
+
// Hips off-frame — accept if shoulders form a reasonable horizontal span,
|
|
416
|
+
// which means the person is upright and facing (or backing) the camera.
|
|
417
|
+
return shoulderWidth > 0.08
|
|
407
418
|
|
|
408
419
|
case .seated:
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
420
|
+
if hipsVisible && kneesVisible {
|
|
421
|
+
return shoulderY < hipY - 0.05 && (hipY - kneeY).magnitude < 0.20
|
|
422
|
+
}
|
|
423
|
+
if hipsVisible {
|
|
413
424
|
return shoulderY < hipY - 0.05
|
|
414
425
|
}
|
|
426
|
+
// Seated with hips out of frame is rare; fall back to upright shoulder span
|
|
427
|
+
return shoulderWidth > 0.08
|
|
415
428
|
|
|
416
429
|
case .sideplank:
|
|
417
|
-
|
|
418
|
-
let ySpread =
|
|
419
|
-
let shoulderHipDx =
|
|
430
|
+
guard hipsVisible else { return false }
|
|
431
|
+
let ySpread = (shoulderY - hipY).magnitude
|
|
432
|
+
let shoulderHipDx = (shoulderX - hipX).magnitude
|
|
420
433
|
return ySpread < 0.20 && shoulderHipDx < 0.15
|
|
421
434
|
|
|
422
435
|
case .inverted:
|
|
423
|
-
|
|
424
|
-
guard anklesVisible else { return false }
|
|
436
|
+
guard hipsVisible, anklesVisible else { return false }
|
|
425
437
|
return hipY < shoulderY && hipY < ankleY
|
|
426
438
|
|
|
427
439
|
case .none:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NitroModules","nitroPoseExercises","createHybridObject"],"sourceRoot":"../../src","sources":["NitroPoseExercises.nitro.ts"],"mappings":";;AAAA,SAA4BA,YAAY,QAAQ,4BAA4B;;AAI5E;;AAqBA;;AASA;;AAsCA;;AAmCA;;
|
|
1
|
+
{"version":3,"names":["NitroModules","nitroPoseExercises","createHybridObject"],"sourceRoot":"../../src","sources":["NitroPoseExercises.nitro.ts"],"mappings":";;AAAA,SAA4BA,YAAY,QAAQ,4BAA4B;;AAI5E;;AAqBA;;AASA;;AAsCA;;AAmCA;;AAuDA,MAAMC,kBAAkB,GACtBD,YAAY,CAACE,kBAAkB,CAAqB,cAAc,CAAC;AAErE,SAASD,kBAAkB","ignoreList":[]}
|
|
@@ -81,7 +81,7 @@ interface NitroPoseExercises extends HybridObject<{
|
|
|
81
81
|
loadExercise(config: ExerciseConfig): void;
|
|
82
82
|
readonly status: SessionStatus;
|
|
83
83
|
processFrameIOS(frame: Frame): void;
|
|
84
|
-
processFrameAndroid(
|
|
84
|
+
processFrameAndroid(frame: Frame): void;
|
|
85
85
|
onRepComplete: ((data: RepData) => void) | undefined;
|
|
86
86
|
onPhaseChange: ((phase: ExercisePhase) => void) | undefined;
|
|
87
87
|
onFormFeedback: ((feedback: FormFeedback) => void) | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NitroPoseExercises.nitro.d.ts","sourceRoot":"","sources":["../../../src/NitroPoseExercises.nitro.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"NitroPoseExercises.nitro.d.ts","sourceRoot":"","sources":["../../../src/NitroPoseExercises.nitro.ts"],"names":[],"mappings":"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"}
|
|
@@ -91,8 +91,6 @@ namespace margelo::nitro::camera { class HybridFrameSpec; }
|
|
|
91
91
|
#include <memory>
|
|
92
92
|
#include <VisionCamera/HybridFrameSpec.hpp>
|
|
93
93
|
#include <VisionCamera/JHybridFrameSpec.hpp>
|
|
94
|
-
#include <NitroModules/ArrayBuffer.hpp>
|
|
95
|
-
#include <NitroModules/JArrayBuffer.hpp>
|
|
96
94
|
|
|
97
95
|
namespace margelo::nitro::nitroposeexercises {
|
|
98
96
|
|
|
@@ -335,9 +333,9 @@ namespace margelo::nitro::nitroposeexercises {
|
|
|
335
333
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<margelo::nitro::camera::JHybridFrameSpec::JavaPart> /* frame */)>("processFrameIOS");
|
|
336
334
|
method(_javaPart, std::dynamic_pointer_cast<margelo::nitro::camera::JHybridFrameSpec>(frame)->getJavaPart());
|
|
337
335
|
}
|
|
338
|
-
void JHybridNitroPoseExercisesSpec::processFrameAndroid(const std::shared_ptr<
|
|
339
|
-
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<
|
|
340
|
-
method(_javaPart,
|
|
336
|
+
void JHybridNitroPoseExercisesSpec::processFrameAndroid(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame) {
|
|
337
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<margelo::nitro::camera::JHybridFrameSpec::JavaPart> /* frame */)>("processFrameAndroid");
|
|
338
|
+
method(_javaPart, std::dynamic_pointer_cast<margelo::nitro::camera::JHybridFrameSpec>(frame)->getJavaPart());
|
|
341
339
|
}
|
|
342
340
|
void JHybridNitroPoseExercisesSpec::startSession(double targetReps, double countdownSeconds) {
|
|
343
341
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(double /* targetReps */, double /* countdownSeconds */)>("startSession");
|
|
@@ -79,7 +79,7 @@ namespace margelo::nitro::nitroposeexercises {
|
|
|
79
79
|
void release() override;
|
|
80
80
|
void loadExercise(const ExerciseConfig& config) override;
|
|
81
81
|
void processFrameIOS(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame) override;
|
|
82
|
-
void processFrameAndroid(const std::shared_ptr<
|
|
82
|
+
void processFrameAndroid(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame) override;
|
|
83
83
|
void startSession(double targetReps, double countdownSeconds) override;
|
|
84
84
|
void pauseSession() override;
|
|
85
85
|
void resumeSession() override;
|
|
@@ -12,7 +12,6 @@ import com.facebook.jni.HybridData
|
|
|
12
12
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
13
13
|
import com.margelo.nitro.core.Promise
|
|
14
14
|
import com.margelo.nitro.camera.HybridFrameSpec
|
|
15
|
-
import com.margelo.nitro.core.ArrayBuffer
|
|
16
15
|
import com.margelo.nitro.core.HybridObject
|
|
17
16
|
|
|
18
17
|
/**
|
|
@@ -189,7 +188,7 @@ abstract class HybridNitroPoseExercisesSpec: HybridObject() {
|
|
|
189
188
|
|
|
190
189
|
@DoNotStrip
|
|
191
190
|
@Keep
|
|
192
|
-
abstract fun processFrameAndroid(
|
|
191
|
+
abstract fun processFrameAndroid(frame: com.margelo.nitro.camera.HybridFrameSpec): Unit
|
|
193
192
|
|
|
194
193
|
@DoNotStrip
|
|
195
194
|
@Keep
|
|
@@ -63,7 +63,6 @@ namespace margelo::nitro::nitroposeexercises { enum class SessionStatus; }
|
|
|
63
63
|
#include "RepData.hpp"
|
|
64
64
|
#include "SessionResult.hpp"
|
|
65
65
|
#include "SessionStatus.hpp"
|
|
66
|
-
#include <NitroModules/ArrayBuffer.hpp>
|
|
67
66
|
#include <NitroModules/Promise.hpp>
|
|
68
67
|
#include <NitroModules/Result.hpp>
|
|
69
68
|
#include <VisionCamera/HybridFrameSpec.hpp>
|
|
@@ -46,8 +46,6 @@ namespace margelo::nitro::nitroposeexercises { enum class PostureFamily; }
|
|
|
46
46
|
namespace margelo::nitro::nitroposeexercises { enum class CameraAngleType; }
|
|
47
47
|
// Forward declaration of `HybridFrameSpec` to properly resolve imports.
|
|
48
48
|
namespace margelo::nitro::camera { class HybridFrameSpec; }
|
|
49
|
-
// Forward declaration of `ArrayBufferHolder` to properly resolve imports.
|
|
50
|
-
namespace NitroModules { class ArrayBufferHolder; }
|
|
51
49
|
|
|
52
50
|
#include "SessionStatus.hpp"
|
|
53
51
|
#include "RepData.hpp"
|
|
@@ -72,8 +70,6 @@ namespace NitroModules { class ArrayBufferHolder; }
|
|
|
72
70
|
#include "CameraAngleType.hpp"
|
|
73
71
|
#include <memory>
|
|
74
72
|
#include <VisionCamera/HybridFrameSpec.hpp>
|
|
75
|
-
#include <NitroModules/ArrayBuffer.hpp>
|
|
76
|
-
#include <NitroModules/ArrayBufferHolder.hpp>
|
|
77
73
|
|
|
78
74
|
#include "NitroPoseExercises-Swift-Cxx-Umbrella.hpp"
|
|
79
75
|
|
|
@@ -228,8 +224,8 @@ namespace margelo::nitro::nitroposeexercises {
|
|
|
228
224
|
std::rethrow_exception(__result.error());
|
|
229
225
|
}
|
|
230
226
|
}
|
|
231
|
-
inline void processFrameAndroid(const std::shared_ptr<
|
|
232
|
-
auto __result = _swiftPart.processFrameAndroid(
|
|
227
|
+
inline void processFrameAndroid(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame) override {
|
|
228
|
+
auto __result = _swiftPart.processFrameAndroid(frame);
|
|
233
229
|
if (__result.hasError()) [[unlikely]] {
|
|
234
230
|
std::rethrow_exception(__result.error());
|
|
235
231
|
}
|
|
@@ -30,7 +30,7 @@ public protocol HybridNitroPoseExercisesSpec_protocol: HybridObject {
|
|
|
30
30
|
func release() throws -> Void
|
|
31
31
|
func loadExercise(config: ExerciseConfig) throws -> Void
|
|
32
32
|
func processFrameIOS(frame: (any HybridFrameSpec)) throws -> Void
|
|
33
|
-
func processFrameAndroid(
|
|
33
|
+
func processFrameAndroid(frame: (any HybridFrameSpec)) throws -> Void
|
|
34
34
|
func startSession(targetReps: Double, countdownSeconds: Double) throws -> Void
|
|
35
35
|
func pauseSession() throws -> Void
|
|
36
36
|
func resumeSession() throws -> Void
|
|
@@ -502,9 +502,13 @@ open class HybridNitroPoseExercisesSpec_cxx {
|
|
|
502
502
|
}
|
|
503
503
|
|
|
504
504
|
@inline(__always)
|
|
505
|
-
public final func processFrameAndroid(
|
|
505
|
+
public final func processFrameAndroid(frame: bridge.std__shared_ptr_margelo__nitro__camera__HybridFrameSpec_) -> bridge.Result_void_ {
|
|
506
506
|
do {
|
|
507
|
-
try self.__implementation.processFrameAndroid(
|
|
507
|
+
try self.__implementation.processFrameAndroid(frame: { () -> any HybridFrameSpec in
|
|
508
|
+
let __unsafePointer = bridge.get_std__shared_ptr_margelo__nitro__camera__HybridFrameSpec_(frame)
|
|
509
|
+
let __instance = HybridFrameSpec_cxx.fromUnsafe(__unsafePointer)
|
|
510
|
+
return __instance.getHybridFrameSpec()
|
|
511
|
+
}())
|
|
508
512
|
return bridge.create_Result_void_()
|
|
509
513
|
} catch (let __error) {
|
|
510
514
|
let __exceptionPtr = __error.toCpp()
|
|
@@ -47,7 +47,6 @@ namespace margelo::nitro::camera { class HybridFrameSpec; }
|
|
|
47
47
|
#include "ExerciseConfig.hpp"
|
|
48
48
|
#include <memory>
|
|
49
49
|
#include <VisionCamera/HybridFrameSpec.hpp>
|
|
50
|
-
#include <NitroModules/ArrayBuffer.hpp>
|
|
51
50
|
|
|
52
51
|
namespace margelo::nitro::nitroposeexercises {
|
|
53
52
|
|
|
@@ -105,7 +104,7 @@ namespace margelo::nitro::nitroposeexercises {
|
|
|
105
104
|
virtual void release() = 0;
|
|
106
105
|
virtual void loadExercise(const ExerciseConfig& config) = 0;
|
|
107
106
|
virtual void processFrameIOS(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame) = 0;
|
|
108
|
-
virtual void processFrameAndroid(const std::shared_ptr<
|
|
107
|
+
virtual void processFrameAndroid(const std::shared_ptr<margelo::nitro::camera::HybridFrameSpec>& frame) = 0;
|
|
109
108
|
virtual void startSession(double targetReps, double countdownSeconds) = 0;
|
|
110
109
|
virtual void pauseSession() = 0;
|
|
111
110
|
virtual void resumeSession() = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nitro-pose-exercises",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "Real-time on-device exercise tracking for React Native. Rep counting, form validation, and skeleton overlay powered by Apple Vision (iOS) and Google ML Kit (Android) with VisionCamera v5 via Nitro Modules.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -124,13 +124,16 @@ interface NitroPoseExercises extends HybridObject<{
|
|
|
124
124
|
// iOS: zero-copy Vision path
|
|
125
125
|
processFrameIOS(frame: Frame): void;
|
|
126
126
|
|
|
127
|
-
// Android
|
|
128
|
-
processFrameAndroid(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
127
|
+
// Android
|
|
128
|
+
processFrameAndroid(frame: Frame): void;
|
|
129
|
+
|
|
130
|
+
// // Android: pre-resized RGBA buffer from VisionCamera Resizer (Vulkan-accelerated)
|
|
131
|
+
// processFrameAndroid(
|
|
132
|
+
// buffer: ArrayBuffer,
|
|
133
|
+
// width: number,
|
|
134
|
+
// height: number,
|
|
135
|
+
// rotation: number
|
|
136
|
+
// ): void;
|
|
134
137
|
|
|
135
138
|
// Callbacks (set from JS side)
|
|
136
139
|
onRepComplete: ((data: RepData) => void) | undefined;
|