| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- import 'package:body_detection/models/pose_landmark_type.dart';
- import '../../../navigation/utils/geometry_utils.dart';
- import '../widgets/pose_detector.dart';
- enum AuthorizedTypeIndex {
- nose,
- leftShoulder,
- rightShoulder,
- leftElbow,
- rightElbow,
- leftWrist,
- rightWrist,
- leftHip,
- rightHip,
- leftKnee,
- rightKnee,
- leftAnkle,
- rightAnkle,
- }
- AuthorizedTypeIndex typeIndexFromString(String typeIndex) {
- switch (typeIndex) {
- case "nose":
- return AuthorizedTypeIndex.nose;
- case "leftShoulder":
- return AuthorizedTypeIndex.leftShoulder;
- case "rightShoulder":
- return AuthorizedTypeIndex.rightShoulder;
- case "leftElbow":
- return AuthorizedTypeIndex.leftElbow;
- case "rightElbow":
- return AuthorizedTypeIndex.rightElbow;
- case "leftWrist":
- return AuthorizedTypeIndex.leftWrist;
- case "rightWrist":
- return AuthorizedTypeIndex.rightWrist;
- case "leftHip":
- return AuthorizedTypeIndex.leftHip;
- case "rightHip":
- return AuthorizedTypeIndex.rightHip;
- case "leftKnee":
- return AuthorizedTypeIndex.leftKnee;
- case "rightKnee":
- return AuthorizedTypeIndex.rightKnee;
- case "leftAnkle":
- return AuthorizedTypeIndex.leftAnkle;
- case "rightAnkle":
- return AuthorizedTypeIndex.rightAnkle;
- default:
- throw const FormatException("Incorrect type name");
- }
- }
- enum Comparator {
- greater,
- lesser,
- }
- Comparator comparatorFromString(String comparator) {
- switch (comparator) {
- case "greater":
- return Comparator.greater;
- case "lesser":
- return Comparator.lesser;
- default:
- throw const FormatException("Incorrect comparator name");
- }
- }
- class Exercise {
- final int repetitions;
- final int sets;
- final Criteria? startMovement;
- final Criteria? endMovement;
- final String description;
- final String name;
- final int difficulty;
- final String id;
- late final List<PoseLandmarkType> jointsOnScreen;
- Exercise({
- required this.repetitions,
- required this.sets,
- required this.startMovement,
- required this.endMovement,
- required this.description,
- required this.name,
- required this.difficulty,
- required this.id,
- required List<AuthorizedTypeIndex> jointsOnScreen,
- }) {
- this.jointsOnScreen = jointsOnScreen.map((joint) => authorizedType[joint.index]).toList();
- }
- bool isAtStartMovement(MeanFilteredData meanFilteredData) {
- final start = startMovement;
- if (start != null) {
- return start.isAtPosition(meanFilteredData);
- }
- return false;
- }
- bool isAtEndMovement(MeanFilteredData meanFilteredData) {
- final end = endMovement;
- if (end != null) {
- return end.isAtPosition(meanFilteredData);
- }
- return false;
- }
- Map<String, dynamic> toMap() {
- return {
- "repetitions": repetitions,
- "sets": sets,
- "start_movement": startMovement?.toMap(),
- "end_movement": endMovement?.toMap(),
- "description": description,
- "name": name,
- "difficulty": difficulty,
- "joints_on_screen": jointsOnScreen.map((j) => j.name).toList(),
- };
- }
- factory Exercise.fromMap(String id, Map<String, dynamic> map) {
- return Exercise(
- repetitions: map["repetitions"],
- sets: map["sets"],
- startMovement: map.containsKey("start_movement") ? Criteria.fromMap(map["start_movement"]) : null,
- endMovement: map.containsKey("end_movement") ? Criteria.fromMap(map["end_movement"]) : null,
- description: map["description"],
- name: map["name"],
- difficulty: map["difficulty"],
- id: id,
- jointsOnScreen: map.containsKey("joints_on_screen") ? List<String>.from(map["joints_on_screen"]).map((e) => typeIndexFromString(e)).toList() : [],
- );
- }
- static const authorizedType = [
- PoseLandmarkType.nose,
- PoseLandmarkType.leftShoulder,
- PoseLandmarkType.rightShoulder,
- PoseLandmarkType.leftElbow,
- PoseLandmarkType.rightElbow,
- PoseLandmarkType.leftWrist,
- PoseLandmarkType.rightWrist,
- PoseLandmarkType.leftHip,
- PoseLandmarkType.rightHip,
- PoseLandmarkType.leftKnee,
- PoseLandmarkType.rightKnee,
- PoseLandmarkType.leftAnkle,
- PoseLandmarkType.rightAnkle,
- ];
- }
- abstract class Criteria {
- bool isAtPosition(MeanFilteredData meanFilteredData);
- Map<String, dynamic> toMap();
- static Criteria fromMap(Map<String, dynamic> map) {
- switch (map["type"]) {
- case "distance":
- return CriteriaDistance.fromMap(map);
- case "angle":
- return CriteriaAngle.fromMap(map);
- default:
- throw FormatException("Type should be distance or angle but is ${map['type']}");
- }
- }
- }
- class CriteriaDistance implements Criteria {
- final AuthorizedTypeIndex jointStart;
- final AuthorizedTypeIndex jointEnd;
- final int axis;
- final num threshold;
- final Comparator comparator;
- const CriteriaDistance({
- required this.jointStart,
- required this.jointEnd,
- required this.axis,
- required this.threshold,
- required this.comparator,
- });
- @override
- bool isAtPosition(MeanFilteredData meanFilteredData) {
- final start = meanFilteredData[jointStart.index][axis];
- final end = meanFilteredData[jointEnd.index][axis];
- final distance = (start - end).abs();
- return _compare(distance, threshold);
- }
- bool _compare(num distance, num threshold) {
- if (comparator == Comparator.greater) {
- return distance > threshold;
- } else {
- return distance < threshold;
- }
- }
- @override
- Map<String, dynamic> toMap() {
- return {
- "joint_start": jointStart.name,
- "joint_end": jointEnd.name,
- "threshold": threshold,
- "comparator": comparator.name,
- "type": "distance",
- };
- }
- factory CriteriaDistance.fromMap(Map<String, dynamic> map) {
- return CriteriaDistance(
- jointStart: typeIndexFromString(map["joint_start"]),
- jointEnd: typeIndexFromString(map["joint_end"]),
- axis: map["axis"],
- threshold: map["threshold"],
- comparator: comparatorFromString(map["comparator"]),
- );
- }
- }
- class CriteriaAngle implements Criteria {
- final AuthorizedTypeIndex jointStart;
- final AuthorizedTypeIndex jointCenter;
- final AuthorizedTypeIndex jointEnd;
- final num threshold;
- final Comparator comparator;
- const CriteriaAngle({
- required this.jointStart,
- required this.jointCenter,
- required this.jointEnd,
- required this.threshold,
- required this.comparator,
- });
- @override
- bool isAtPosition(MeanFilteredData meanFilteredData) {
- final start = Point3D(
- x: meanFilteredData[jointStart.index][0],
- y: meanFilteredData[jointStart.index][1],
- z: meanFilteredData[jointStart.index][2]);
- final center = Point3D(
- x: meanFilteredData[jointCenter.index][0],
- y: meanFilteredData[jointCenter.index][1],
- z: meanFilteredData[jointCenter.index][2]);
- final end = Point3D(
- x: meanFilteredData[jointEnd.index][0],
- y: meanFilteredData[jointEnd.index][1],
- z: meanFilteredData[jointEnd.index][2]);
- final angle = DistanceUtils.angleBetweenThreePoints(start, center, end).round();
- return _compare(angle, threshold);
- }
- bool _compare(num angle, num threshold) {
- if (comparator == Comparator.greater) {
- return angle > threshold;
- } else {
- return angle < threshold;
- }
- }
- @override
- Map<String, dynamic> toMap() {
- return {
- "joint_start": jointStart.name,
- "joint_center": jointCenter.name,
- "joint_end": jointEnd.name,
- "threshold": threshold,
- "comparator": comparator.name,
- "type": "angle",
- };
- }
- factory CriteriaAngle.fromMap(Map<String, dynamic> map) {
- return CriteriaAngle(
- jointStart: typeIndexFromString(map["joint_start"]),
- jointCenter: typeIndexFromString(map["joint_center"]),
- jointEnd: typeIndexFromString(map["joint_end"]),
- threshold: map["threshold"],
- comparator: comparatorFromString(map["comparator"]),
- );
- }
- }
|