Skip to content

Commit

Permalink
Split marker_tracking (#154)
Browse files Browse the repository at this point in the history
Summary: Pull Request resolved: #154

Reviewed By: cdtwigg

Differential Revision: D66831016
  • Loading branch information
jeongseok-meta authored and facebook-github-bot committed Dec 6, 2024
1 parent f0d03d0 commit 4abf7f9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 233 deletions.
14 changes: 14 additions & 0 deletions pymomentum/cmake/build_variables.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,17 @@ skel_state_public_headers = [
skel_state_sources = [
"skel_state/skel_state_pybind.cpp",
]

marker_tracking_public_headers = [
]

marker_tracking_sources = [
"marker_tracking/marker_tracking_pybind.cpp",
]

marker_tracking_extensions_public_headers = [
]

marker_tracking_extensions_sources = [
"marker_tracking_extensions/marker_tracking_extensions_pybind.cpp",
]
239 changes: 6 additions & 233 deletions pymomentum/marker_tracking/marker_tracking_pybind.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.

#include <marker_tracking/analysis_utils/marker_error_utils.hpp> // @manual=fbsource//arvr/projects/kuiper_belt/projects/marker_tracking:analysis_utils
#include <marker_tracking/metrics/self_collision_detector.h> // @manual=fbsource//arvr/projects/kuiper_belt/projects/marker_tracking:self_collision_detector
#include <marker_tracking/validate_c3d.h> // @manual=fbsource//arvr/projects/kuiper_belt/projects/marker_tracking:validate_c3d

#include <momentum/character/marker.h>
#include <momentum/marker_tracking/marker_tracker.h>
#include <momentum/marker_tracking/process_markers.h>
Expand All @@ -13,12 +9,13 @@
#include <pybind11/eigen.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include <string>

namespace py = pybind11;

// Python bindings for marker tracking APIs defined under:
// //arvr/projects/kuiper_belt/projects/marker_tracking
// //arvr/libraries/momentum/marker_tracking

// @dep=fbsource//arvr/libraries/dispenso:dispenso

Expand All @@ -29,180 +26,6 @@ PYBIND11_MODULE(marker_tracking, m) {
pybind11::module_::import(
"pymomentum.geometry"); // @dep=fbcode//pymomentum:geometry

// Bindings for APIs and types defined in
// marker_tracking/analysis_utils/marker_error_utils.h
// (https://pybind11.readthedocs.io/en/latest/classes.html#creating-bindings-for-a-custom-type)
auto markerErrorReport = py::class_<marker_tracking::MarkerErrorReport>(
m,
"MarkerErrorReport",
"Represents a report generated from computed marker errors");

py::class_<marker_tracking::MarkerErrorReport::LocatorEntry>(
markerErrorReport,
"LocatorEntry",
"a struct within MarkerErrorReport, called LocatorEntry")
.def(py::init<>())
.def_readwrite(
"locator_name",
&marker_tracking::MarkerErrorReport::LocatorEntry::locatorName)
.def_readwrite(
"frames_error",
&marker_tracking::MarkerErrorReport::LocatorEntry::framesError)
.def_readwrite(
"has_data",
&marker_tracking::MarkerErrorReport::LocatorEntry::hasData)
.def_readwrite(
"average_error",
&marker_tracking::MarkerErrorReport::LocatorEntry::averageError);

py::class_<marker_tracking::MarkerErrorReport::OcclusionInfo>(
markerErrorReport,
"OcclusionInfo",
"a struct within MarkerErrorReport, called OcclusionInfo")
.def(py::init<>())
.def_readwrite(
"frame_id",
&marker_tracking::MarkerErrorReport::OcclusionInfo::frameId)
.def_readwrite(
"locator_names",
&marker_tracking::MarkerErrorReport::OcclusionInfo::locatorNames);

markerErrorReport.def(py::init<>())
.def_readwrite(
"unused_locators",
&marker_tracking::MarkerErrorReport::unusedLocators,
"Locators that are not used")
.def_readwrite(
"unused_markers",
&marker_tracking::MarkerErrorReport::unusedMarkers,
"Markers that are not used")
.def_readwrite(
"entries",
&marker_tracking::MarkerErrorReport::entries,
"vector<struct called LocatorEntry>")
.def_readwrite(
"occluded",
&marker_tracking::MarkerErrorReport::occluded,
"vector<struct called OcclusionInfo>");

// (see find_segment_collisions)
m.def(
"generate_marker_error_report_on_files",
[](const std::string& markerFile, const std::string& motionGlbFile)
-> marker_tracking::MarkerErrorReport {
return marker_tracking::generateMarkerErrorReportOnFiles(
markerFile, motionGlbFile);
},
py::arg("marker_file"),
py::arg("motion_glb_file"));

// Bindings for APIs and types defined in
// marker_tracking/metrics/self_collision_detector.h
auto bodySegmentCollisionResult = py::class_<
marker_tracking::BodySegmentCollisionResult>(
m,
"BodySegmentCollisionResult",
"Represents a body part segment collision result e.g. left hand collides with right hand.");

bodySegmentCollisionResult.def(py::init<>())
.def_readonly(
"first_segment",
&marker_tracking::BodySegmentCollisionResult::firstSegment,
"Name of the first body segment")
.def_readonly(
"second_segment",
&marker_tracking::BodySegmentCollisionResult::secondSegment,
"Name of the second body segment")
.def_readonly(
"num_contacts",
&marker_tracking::BodySegmentCollisionResult::numContacts,
"Number of contacts between two body segments")
.def_readonly(
"max_penetration_depth",
&marker_tracking::BodySegmentCollisionResult::maxPenetrationDepth,
"Max penetration depth from detected contacts");
;

auto frameCollisionResult = py::class_<marker_tracking::FrameCollisionResult>(
m,
"FrameCollisionResult",
"Represents the body part segment collision pairs in one frame");

frameCollisionResult.def(py::init<>())
.def_readonly(
"segment_collision_results",
&marker_tracking::FrameCollisionResult::segmentCollisionResults,
"List of all body part segment collisions at the current frame");

auto motionSequenceCollisionResult =
py::class_<marker_tracking::MotionSequenceCollisionResult>(
m,
"MotionSequenceCollisionResult",
"Represents collision results for a motion sequence.");

motionSequenceCollisionResult.def(py::init<>())
.def_readonly(
"sequence_name",
&marker_tracking::MotionSequenceCollisionResult::sequenceName,
"Name of the sequence file")
.def_readonly(
"body_segment_root_names",
&marker_tracking::MotionSequenceCollisionResult::bodySegmentRootNames,
"List of body part segment names used for collision detection")
.def_readonly(
"frame_collision_results",
&marker_tracking::MotionSequenceCollisionResult::
frameCollisionResults,
"Collision results for all frames in the mocap sequence");

py::list bodySegmentRootNameList;
for (const std::string& s : marker_tracking::kBodySegmentRootNames) {
bodySegmentRootNameList.append(s);
}
m.attr("body_segment_roots_default") = bodySegmentRootNameList;
m.def(
"create_body_segments_to_vertices_mapping",
&marker_tracking::createBodySegmentsToVerticesMapping);
m.def(
"find_segment_collisions",
[](const momentum::Character& character,
Eigen::Ref<const Eigen::VectorXf> jointParams,
const std::unordered_map<std::string, std::vector<size_t>>&
bodySegmentToVertices,
const size_t maxContacts) {
return marker_tracking::findSegmentCollisions(
character, jointParams, bodySegmentToVertices, maxContacts);
},
py::arg("character"),
py::arg("joint_params"),
py::arg("body_segment_to_vertices"),
py::arg("max_contacts"));

m.def(
"find_collision",
[](const momentum::Mesh& mesh1,
const momentum::Mesh& mesh2,
const size_t maxContacts) {
return marker_tracking::findCollision(mesh1, mesh2, maxContacts);
},
py::arg("mesh_1"),
py::arg("mesh_2"),
py::arg("max_contacts"));

m.def(
"create_body_segment_mesh",
[](const momentum::Mesh& originalMesh,
const std::vector<size_t>& vertexIds,
const std::vector<Eigen::Vector3f>& newVertices) {
return marker_tracking::createBodySegmentMesh(
originalMesh, vertexIds, newVertices);
},
py::arg("original_mesh"),
py::arg("vertices_ids"),
py::arg("pose_vertices"));

m.def("detect_self_collisions", &marker_tracking::detectSelfCollisions);

// Bindings for types defined in marker_tracking/marker_tracker.h
auto baseConfig = py::class_<marker_tracking::BaseConfig>(
m, "BaseConfig", "Represents base config class");
Expand All @@ -217,7 +40,7 @@ PYBIND11_MODULE(marker_tracking, m) {
.def_readwrite(
"min_vis_percent",
&marker_tracking::BaseConfig::minVisPercent,
"Minimum percetange of visible markers to be used")
"Minimum percentage of visible markers to be used")
.def_readwrite(
"loss_alpha",
&marker_tracking::BaseConfig::lossAlpha,
Expand Down Expand Up @@ -339,7 +162,7 @@ PYBIND11_MODULE(marker_tracking, m) {
.def_readwrite(
"parameters",
&marker_tracking::ModelOptions::parameters,
"Path of parameter trasform model file e.g. blueman.model")
"Path of parameter transform model file e.g. blueman.model")
.def_readwrite(
"locators",
&marker_tracking::ModelOptions::locators,
Expand Down Expand Up @@ -444,15 +267,15 @@ PYBIND11_MODULE(marker_tracking, m) {
const marker_tracking::RefineConfig& refineConfig) {
// python and cpp have the motion matrix transposed from each other.
// Let's do that on the way in and out here so it's consistent for both
// lanangues.
// languages.
Eigen::MatrixXf inputMotion(motion.transpose());

// If input identity is not empty, it means the motion is stripped of
// identity field (eg. read from a glb file), so we need to fill it in.
// If the input identity is empty, we assume the identity fields already
// exist in the motion matrix.
if (identity.size() > 0) {
marker_tracking::ParameterSet idParamSet =
momentum::ParameterSet idParamSet =
character.parameterTransform.getScalingParameters();
marker_tracking::fillIdentity(idParamSet, identity, inputMotion);
}
Expand All @@ -466,54 +289,4 @@ PYBIND11_MODULE(marker_tracking, m) {
py::arg("motion"),
py::arg("marker_data"),
py::arg("refine_config"));

auto markerActorStats = py::class_<marker_tracking::MarkerActorStats>(
m,
"markerActorStats",
"Class to collect stats from a single actor of a marker file");

markerActorStats.def(py::init<>())
.def_readonly(
"actor_name",
&marker_tracking::MarkerActorStats::actorName,
"Name of a given actor in the marker file")
.def_readonly(
"num_frames",
&marker_tracking::MarkerActorStats::numFrames,
"Number of frames characterizing the marker sequence of the given actor")
.def_readonly(
"fps",
&marker_tracking::MarkerActorStats::fps,
"FPS characterizing the marker sequence of the given actor")
.def_readonly(
"marker_names",
&marker_tracking::MarkerActorStats::markerNames,
"List of all the marker names")
.def_readonly(
"min_count_markers",
&marker_tracking::MarkerActorStats::minCountMarkers,
"Minimum amount of non-occluded markers across the motion sequence")
.def_readonly(
"max_count_markers",
&marker_tracking::MarkerActorStats::maxCountMarkers,
"Maximum amount of non-occluded markers across the motion sequence")
.def_readonly(
"mean_count_markers",
&marker_tracking::MarkerActorStats::meanCountMarkers,
"Average amount of non-occluded markers across the motion sequence");

auto markerFileStats = py::class_<marker_tracking::MarkerFileStats>(
m, "markerFileStats", "Class to extract stats from an input marker file");

markerFileStats.def(py::init<>())
.def_readonly(
"num_actors",
&marker_tracking::MarkerFileStats::numActors,
"Name of actors in the input marker file")
.def_readonly(
"marker_actor_stats",
&marker_tracking::MarkerFileStats::markerActorStats,
"List of the stats related to all actors in the marker file");

m.def("stats_from_marker_file", &marker_tracking::statsFromMarkerFile);
}

0 comments on commit 4abf7f9

Please sign in to comment.