Spaces:
Running on Zero
Running on Zero
| # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| import torch | |
| def foot_detect_from_pos_and_vel( | |
| positions: torch.Tensor, | |
| velocity: torch.Tensor, | |
| skeleton, | |
| vel_thres: float, | |
| height_thresh: float, | |
| ) -> torch.Tensor: | |
| """Compute foot contact labels using heuristics combining joint height and velocities. | |
| Args: | |
| positions (torch.Tensor): [X, T, J, 3] global joint positions | |
| velocity (torch.Tensor): [X, T, J, 3] velocities (already padded correctly), already multiplied by 1 / dt | |
| skeleton: skeleton providing left/right foot joint indices | |
| vel_thres (float): threshold for joint velocity | |
| height_thresh (float): threshold for joint height | |
| Returns: | |
| torch.Tensor: [X, T, 4] contact labels (left heel, left toe, right heel, | |
| right toe), 1 for foot plant | |
| """ | |
| device = positions.device | |
| fid_l = skeleton.left_foot_joint_idx | |
| fid_r = skeleton.right_foot_joint_idx | |
| velfactor, heightfactor = ( | |
| torch.tensor([vel_thres, vel_thres], device=device), | |
| torch.tensor([height_thresh, height_thresh], device=device), | |
| ) | |
| feet_l_v = torch.linalg.norm(velocity[:, :, fid_l], axis=-1) | |
| feet_l_h = positions[:, :, fid_l, 1] | |
| feet_l = torch.logical_and( | |
| feet_l_v < velfactor, | |
| feet_l_h < heightfactor, | |
| ).to(positions.dtype) | |
| feet_r_v = torch.linalg.norm(velocity[:, :, fid_r], axis=-1) | |
| feet_r_h = positions[:, :, fid_r, 1] | |
| feet_r = torch.logical_and( | |
| feet_r_v < velfactor, | |
| feet_r_h < heightfactor, | |
| ).to(positions.dtype) | |
| foot_contacts = torch.cat((feet_l, feet_r), axis=-1) | |
| return foot_contacts | |