exercise.dart 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import 'package:body_detection/models/pose_landmark_type.dart';
  2. import '../../../navigation/utils/geometry_utils.dart';
  3. import '../widgets/pose_detector.dart';
  4. enum AuthorizedTypeIndex {
  5. nose,
  6. leftShoulder,
  7. rightShoulder,
  8. leftElbow,
  9. rightElbow,
  10. leftWrist,
  11. rightWrist,
  12. leftHip,
  13. rightHip,
  14. leftKnee,
  15. rightKnee,
  16. leftAnkle,
  17. rightAnkle,
  18. }
  19. class Exercise {
  20. final int reps;
  21. final int series;
  22. final Criteria startMovement;
  23. final Criteria endMovement;
  24. const Exercise({
  25. required this.reps,
  26. required this.series,
  27. required this.startMovement,
  28. required this.endMovement,
  29. });
  30. bool isAtStartMovement(MeanFilteredData meanFilteredData) {
  31. return startMovement.isAtPosition(meanFilteredData);
  32. }
  33. bool isAtEndMovement(MeanFilteredData meanFilteredData) {
  34. return endMovement.isAtPosition(meanFilteredData);
  35. }
  36. static const authorizedType = [
  37. PoseLandmarkType.nose,
  38. PoseLandmarkType.leftShoulder,
  39. PoseLandmarkType.rightShoulder,
  40. PoseLandmarkType.leftElbow,
  41. PoseLandmarkType.rightElbow,
  42. PoseLandmarkType.leftWrist,
  43. PoseLandmarkType.rightWrist,
  44. PoseLandmarkType.leftHip,
  45. PoseLandmarkType.rightHip,
  46. PoseLandmarkType.leftKnee,
  47. PoseLandmarkType.rightKnee,
  48. PoseLandmarkType.leftAnkle,
  49. PoseLandmarkType.rightAnkle,
  50. ];
  51. }
  52. abstract class Criteria {
  53. bool isAtPosition(MeanFilteredData meanFilteredData);
  54. }
  55. class CriteriaDistance implements Criteria {
  56. final AuthorizedTypeIndex jointStart;
  57. final AuthorizedTypeIndex jointEnd;
  58. final int axis;
  59. final int threshold;
  60. const CriteriaDistance({
  61. required this.jointStart,
  62. required this.jointEnd,
  63. required this.axis,
  64. required this.threshold,
  65. });
  66. @override
  67. bool isAtPosition(MeanFilteredData meanFilteredData) {
  68. final start = meanFilteredData[jointStart.index][axis];
  69. final end = meanFilteredData[jointEnd.index][axis];
  70. final distance = (start - end).abs();
  71. return distance < threshold;
  72. }
  73. }
  74. class CriteriaAngle implements Criteria {
  75. final AuthorizedTypeIndex jointStart;
  76. final AuthorizedTypeIndex jointCenter;
  77. final AuthorizedTypeIndex jointEnd;
  78. final int threshold;
  79. const CriteriaAngle({
  80. required this.jointStart,
  81. required this.jointCenter,
  82. required this.jointEnd,
  83. required this.threshold,
  84. });
  85. @override
  86. bool isAtPosition(MeanFilteredData meanFilteredData) {
  87. final start = Point3D(
  88. x: meanFilteredData[jointStart.index][0],
  89. y: meanFilteredData[jointStart.index][1],
  90. z: meanFilteredData[jointStart.index][2]);
  91. final center = Point3D(
  92. x: meanFilteredData[jointCenter.index][0],
  93. y: meanFilteredData[jointCenter.index][1],
  94. z: meanFilteredData[jointCenter.index][2]);
  95. final end = Point3D(
  96. x: meanFilteredData[jointEnd.index][0],
  97. y: meanFilteredData[jointEnd.index][1],
  98. z: meanFilteredData[jointEnd.index][2]);
  99. final angle = DistanceUtils.angleBetweenThreePoints(start, center, end).round();
  100. return angle > threshold;
  101. }
  102. }