diff --git a/dart/biomechanics/SubjectOnDisk.cpp b/dart/biomechanics/SubjectOnDisk.cpp index 3388b83d9..cfc6829c5 100644 --- a/dart/biomechanics/SubjectOnDisk.cpp +++ b/dart/biomechanics/SubjectOnDisk.cpp @@ -181,6 +181,84 @@ MissingGRFReason missingGRFReasonFromProto(proto::MissingGRFReason reason) return notMissingGRF; } +BasicTrialType basicTrialTypeFromProto(proto::BasicTrialType type) +{ + switch (type) + { + case proto::BasicTrialType::treadmill: + return treadmill; + case proto::BasicTrialType::overground: + return overground; + case proto::BasicTrialType::staticTrial: + return staticTrial; + case proto::BasicTrialType::other: + return other; + case proto::BasicTrialType_INT_MIN_SENTINEL_DO_NOT_USE_: + return other; + break; + case proto::BasicTrialType_INT_MAX_SENTINEL_DO_NOT_USE_: + return other; + break; + } + return other; +} + +proto::BasicTrialType basicTrialTypeToProto(BasicTrialType type) +{ + switch (type) + { + case treadmill: + return proto::BasicTrialType::treadmill; + case overground: + return proto::BasicTrialType::overground; + case staticTrial: + return proto::BasicTrialType::staticTrial; + case other: + return proto::BasicTrialType::other; + } + return proto::BasicTrialType::other; +} + +DetectedTrialFeature detectedTrialFeatureFromProto( + proto::DetectedTrialFeature feature) +{ + switch (feature) + { + case proto::DetectedTrialFeature::walking: + return walking; + case proto::DetectedTrialFeature::running: + return running; + case proto::DetectedTrialFeature::unevenTerrain: + return unevenTerrain; + case proto::DetectedTrialFeature::flatTerrain: + return flatTerrain; + case proto::DetectedTrialFeature_INT_MIN_SENTINEL_DO_NOT_USE_: + return walking; + break; + case proto::DetectedTrialFeature_INT_MAX_SENTINEL_DO_NOT_USE_: + return walking; + break; + } + return walking; +} + +proto::DetectedTrialFeature detectedTrialFeatureToProto( + DetectedTrialFeature feature) +{ + switch (feature) + { + case walking: + return proto::DetectedTrialFeature::walking; + case running: + return proto::DetectedTrialFeature::running; + case unevenTerrain: + return proto::DetectedTrialFeature::unevenTerrain; + case flatTerrain: + return proto::DetectedTrialFeature::flatTerrain; + } + return proto::DetectedTrialFeature::walking; +} + SubjectOnDisk::SubjectOnDisk(const std::string& path) : mPath(path), mLoadedAllFrames(false) { @@ -3193,6 +3271,17 @@ void SubjectOnDiskTrial::setMissingGRFReason( mMissingGRFReason = missingGRFReason; } +std::vector SubjectOnDiskTrial::getHasManualGRFAnnotation() +{ + return mHasManualGRFAnnotation; +} + +void SubjectOnDiskTrial::setHasManualGRFAnnotation( + std::vector hasManualGRFAnnotation) +{ + mHasManualGRFAnnotation = hasManualGRFAnnotation; +} + void SubjectOnDiskTrial::setCustomValues( std::vector customValues) { @@ -3250,6 +3339,27 @@ std::vector SubjectOnDiskTrial::getForcePlates() return mForcePlates; } +void SubjectOnDiskTrial::setBasicTrialType(BasicTrialType type) +{ + mBasicTrialType = type; +} + +BasicTrialType SubjectOnDiskTrial::getBasicTrialType() +{ + return mBasicTrialType; +} + +void SubjectOnDiskTrial::setDetectedTrialFeatures( + std::vector features) +{ + mDetectedTrialFeatures = features; +} + +std::vector SubjectOnDiskTrial::getDetectedTrialFeatures() +{ + return mDetectedTrialFeatures; +} + std::shared_ptr SubjectOnDiskTrial::addPass() { mTrialPasses.push_back(std::make_shared()); @@ -3305,6 +3415,19 @@ void SubjectOnDiskTrial::read(const proto::SubjectOnDiskTrialHeader& proto) mMissingGRFReason.push_back( missingGRFReasonFromProto(proto.missing_grf_reason(i))); } + mHasManualGRFAnnotation.clear(); + for (int i = 0; i < proto.has_manual_grf_annotation_size(); i++) + { + mHasManualGRFAnnotation.push_back(proto.has_manual_grf_annotation(i)); + } + + mBasicTrialType = basicTrialTypeFromProto(proto.trial_type()); + mDetectedTrialFeatures.clear(); + for (int i = 0; i < proto.detected_trial_feature_size(); i++) + { + mDetectedTrialFeatures.push_back( + detectedTrialFeatureFromProto(proto.detected_trial_feature(i))); + } // /////////////////////////////////////////////////////////////////////////// // // Raw sensor observations, which are shared across processing passes @@ -3378,6 +3501,16 @@ void SubjectOnDiskTrial::write(proto::SubjectOnDiskTrialHeader* proto) proto->add_missing_grf_reason( missingGRFReasonToProto(mMissingGRFReason[i])); } + for (int i = 0; i < mHasManualGRFAnnotation.size(); i++) + { + proto->add_has_manual_grf_annotation(mHasManualGRFAnnotation[i]); + } + proto->set_trial_type(basicTrialTypeToProto(mBasicTrialType)); + for (int i = 0; i < mDetectedTrialFeatures.size(); i++) + { + proto->add_detected_trial_feature( + detectedTrialFeatureToProto(mDetectedTrialFeatures[i])); + } // /////////////////////////////////////////////////////////////////////////// // // Raw sensor observations, which are shared across processing passes diff --git a/dart/biomechanics/SubjectOnDisk.hpp b/dart/biomechanics/SubjectOnDisk.hpp index 0f4d0c177..fae66f9b0 100644 --- a/dart/biomechanics/SubjectOnDisk.hpp +++ b/dart/biomechanics/SubjectOnDisk.hpp @@ -347,6 +347,8 @@ class SubjectOnDiskTrial void setOriginalTrialEndTime(s_t endTime); std::vector getMissingGRFReason(); void setMissingGRFReason(std::vector missingGRFReason); + std::vector getHasManualGRFAnnotation(); + void setHasManualGRFAnnotation(std::vector hasManualGRFAnnotation); void setCustomValues(std::vector customValues); void setMarkerNamesGuessed(bool markersGuessed); std::vector> getMarkerObservations(); @@ -361,6 +363,10 @@ class SubjectOnDiskTrial void setExoTorques(std::map exoTorques); void setForcePlates(std::vector forcePlates); std::vector getForcePlates(); + void setBasicTrialType(BasicTrialType type); + BasicTrialType getBasicTrialType(); + void setDetectedTrialFeatures(std::vector features); + std::vector getDetectedTrialFeatures(); std::shared_ptr addPass(); std::vector> getPasses(); void read(const proto::SubjectOnDiskTrialHeader& proto); @@ -373,6 +379,7 @@ class SubjectOnDiskTrial std::vector mTrialTags; std::vector> mTrialPasses; std::vector mMissingGRFReason; + std::vector mHasManualGRFAnnotation; // This is true if we guessed the marker names, and false if we got them from // the uploaded user's file, which implies that they got them from human // observations. @@ -385,6 +392,9 @@ class SubjectOnDiskTrial s_t mOriginalTrialStartTime; s_t mOriginalTrialEndTime; + BasicTrialType mBasicTrialType; + std::vector mDetectedTrialFeatures; + /////////////////////////////////////////////////////////////////////////// // Recovered proto summaries, for incremental loading of Frames /////////////////////////////////////////////////////////////////////////// diff --git a/dart/biomechanics/enums.hpp b/dart/biomechanics/enums.hpp index 733880856..6a66ac0f8 100644 --- a/dart/biomechanics/enums.hpp +++ b/dart/biomechanics/enums.hpp @@ -29,6 +29,22 @@ enum MissingGRFReason extendedToNearestPeakForce }; +enum BasicTrialType +{ + treadmill, + overground, + staticTrial, + other +}; + +enum DetectedTrialFeature +{ + walking, + running, + unevenTerrain, + flatTerrain +}; + enum MissingGRFStatus { no = 0, // no will cast to `false` diff --git a/dart/proto/SubjectOnDisk.proto b/dart/proto/SubjectOnDisk.proto index 0ebd6f17d..f82103276 100644 --- a/dart/proto/SubjectOnDisk.proto +++ b/dart/proto/SubjectOnDisk.proto @@ -30,6 +30,20 @@ enum ProcessingPassType { accMinimizingFilter = 3; }; +enum BasicTrialType { + treadmill = 0; + overground = 1; + staticTrial = 2; + other = 3; +}; + +enum DetectedTrialFeature { + walking = 0; + running = 1; + unevenTerrain = 2; + flatTerrain = 3; +} + // Many of the ML tasks we want to support from SubjectOnDisk data include // effectively predicting the results of a downstream processing task from // an upstream processing task. Trivially, that's predicting physics from @@ -79,6 +93,7 @@ message SubjectOnDiskTrialHeader { // memory, but we really want to know this information when randomly picking // frames from the subject to sample. repeated MissingGRFReason missing_GRF_reason = 2; + repeated bool has_manual_GRF_annotation = 16; // This is how many frames are in this trial int32 trial_length = 3; // This is the timestep used in this trial (assumed constant throughout the trial) @@ -102,6 +117,10 @@ message SubjectOnDiskTrialHeader { int32 original_trial_end_frame = 13; float original_trial_start_time = 14; float original_trial_end_time = 15; + // This is the type of trial we're dealing with + BasicTrialType trial_type = 17; + // This is the detected features of this trial + repeated DetectedTrialFeature detected_trial_feature = 18; } message SubjectOnDiskPass { diff --git a/python/_nimblephysics/biomechanics/SubjectOnDisk.cpp b/python/_nimblephysics/biomechanics/SubjectOnDisk.cpp index bb4e16e5a..1a82aa0aa 100644 --- a/python/_nimblephysics/biomechanics/SubjectOnDisk.cpp +++ b/python/_nimblephysics/biomechanics/SubjectOnDisk.cpp @@ -50,6 +50,51 @@ void SubjectOnDisk(py::module& m) "This is the pass where we apply an acceleration minimizing " "filter to the kinematics and dynamics."); + auto basicTrialType + = ::py::enum_(m, "BasicTrialType") + .value( + "TREADMILL", + dart::biomechanics::BasicTrialType::treadmill, + "This is a trial where the subject is walking or " + "running on a treadmill.") + .value( + "OVERGROUND", + dart::biomechanics::BasicTrialType::overground, + "This is a trial where the subject is walking or " + "running overground.") + .value( + "STATIC_TRIAL", + dart::biomechanics::BasicTrialType::staticTrial, + "This is a trial where the subject is standing " + "still.") + .value( + "OTHER", + dart::biomechanics::BasicTrialType::other, + "This is a trial that doesn't fit into any of the " + "other categories."); + + auto detectedTrialFeature + = ::py::enum_( + m, "DetectedTrialFeature") + .value( + "WALKING", + dart::biomechanics::DetectedTrialFeature::walking, + "This is a trial where the subject is walking.") + .value( + "RUNNING", + dart::biomechanics::DetectedTrialFeature::running, + "This is a trial where the subject is running.") + .value( + "UNEVEN_TERRAIN", + dart::biomechanics::DetectedTrialFeature::unevenTerrain, + "This is a trial where the subject is walking or " + "running on uneven terrain.") + .value( + "FLAT_TERRAIN", + dart::biomechanics::DetectedTrialFeature::flatTerrain, + "This is a trial where the subject is walking or " + "running on flat terrain."); + auto framePass = ::py::class_< dart::biomechanics::FramePass, @@ -891,6 +936,15 @@ Note that these are specified in the local body frame, acting on the body at its .def( "getMissingGRFReason", &dart::biomechanics::SubjectOnDiskTrial::getMissingGRFReason) + .def( + "setHasManualGRFAnnotation", + &dart::biomechanics::SubjectOnDiskTrial:: + setHasManualGRFAnnotation, + ::py::arg("hasManualGRFAnnotation")) + .def( + "getHasManualGRFAnnotation", + &dart::biomechanics::SubjectOnDiskTrial:: + getHasManualGRFAnnotation) .def( "setCustomValues", &dart::biomechanics::SubjectOnDiskTrial::setCustomValues, @@ -929,6 +983,22 @@ Note that these are specified in the local body frame, acting on the body at its .def( "getForcePlates", &dart::biomechanics::SubjectOnDiskTrial::getForcePlates) + .def( + "setBasicTrialType", + &dart::biomechanics::SubjectOnDiskTrial::setBasicTrialType, + ::py::arg("type")) + .def( + "getBasicTrialType", + &dart::biomechanics::SubjectOnDiskTrial::getBasicTrialType) + .def( + "setDetectedTrialFeatures", + &dart::biomechanics::SubjectOnDiskTrial:: + setDetectedTrialFeatures, + ::py::arg("features")) + .def( + "getDetectedTrialFeatures", + &dart::biomechanics::SubjectOnDiskTrial:: + getDetectedTrialFeatures) .def( "addPass", &dart::biomechanics::SubjectOnDiskTrial::addPass,