You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
546 lines
21 KiB
546 lines
21 KiB
#include <pybind11/pybind11.h>
|
|
#include <pybind11/chrono.h>
|
|
#include <pybind11/stl.h>
|
|
#include <thread>
|
|
#include <iostream>
|
|
#include <mutex>
|
|
#include <sstream>
|
|
#include <array>
|
|
#include <nlohmann/json.hpp>
|
|
#include "PXREARobotSDK.h"
|
|
|
|
|
|
using json = nlohmann::json;
|
|
|
|
std::array<double, 7> LeftControllerPose;
|
|
std::array<double, 7> RightControllerPose;
|
|
std::array<double, 7> HeadsetPose;
|
|
|
|
std::array<std::array<double, 7>, 26> LeftHandTrackingState;
|
|
double LeftHandScale = 1.0;
|
|
int LeftHandIsActive = 0;
|
|
std::array<std::array<double, 7>, 26> RightHandTrackingState;
|
|
double RightHandScale = 1.0;
|
|
int RightHandIsActive = 0;
|
|
|
|
// Whole body motion data - 24 joints for body tracking
|
|
std::array<std::array<double, 7>, 24> BodyJointsPose; // Position and rotation for each joint
|
|
std::array<std::array<double, 6>, 24> BodyJointsVelocity; // Velocity and angular velocity for each joint
|
|
std::array<std::array<double, 6>, 24> BodyJointsAcceleration; // Acceleration and angular acceleration for each joint
|
|
std::array<int64_t, 24> BodyJointsTimestamp; // IMU timestamp for each joint
|
|
int64_t BodyTimeStampNs = 0; // Body data timestamp
|
|
bool BodyDataAvailable = false; // Flag to indicate if body data is available
|
|
|
|
std::array<std::array<double, 7>, 3> MotionTrackerPose; // Position and rotation for each joint
|
|
std::array<std::array<double, 6>, 3> MotionTrackerVelocity; // Velocity and angular velocity for each joint
|
|
std::array<std::array<double, 6>, 3> MotionTrackerAcceleration; // Acceleration and angular acceleration for each joint
|
|
std::array<std::string, 3> MotionTrackerSerialNumbers; // Serial numbers of the motion trackers
|
|
int64_t MotionTimeStampNs = 0; // Motion data timestamp
|
|
int NumMotionDataAvailable = 0; // number of motion trackers
|
|
|
|
|
|
bool LeftMenuButton;
|
|
double LeftTrigger;
|
|
double LeftGrip;
|
|
std::array<double, 2> LeftAxis{0.0, 0.0};
|
|
bool LeftAxisClick;
|
|
bool LeftPrimaryButton;
|
|
bool LeftSecondaryButton;
|
|
|
|
bool RightMenuButton;
|
|
double RightTrigger;
|
|
double RightGrip;
|
|
std::array<double, 2> RightAxis{0.0, 0.0};
|
|
bool RightAxisClick;
|
|
bool RightPrimaryButton;
|
|
bool RightSecondaryButton;
|
|
|
|
int64_t TimeStampNs;
|
|
|
|
std::mutex leftMutex;
|
|
std::mutex rightMutex;
|
|
std::mutex headsetPoseMutex;
|
|
std::mutex timestampMutex;
|
|
std::mutex leftHandMutex;
|
|
std::mutex rightHandMutex;
|
|
std::mutex bodyMutex; // Mutex for body tracking data
|
|
std::mutex motionMutex;
|
|
|
|
|
|
|
|
std::array<double, 7> stringToPoseArray(const std::string& poseStr) {
|
|
std::array<double, 7> result{0};
|
|
std::stringstream ss(poseStr);
|
|
std::string value;
|
|
int i = 0;
|
|
while (std::getline(ss, value, ',') && i < 7) {
|
|
result[i++] = std::stod(value);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::array<double, 6> stringToVelocityArray(const std::string& velocityStr) {
|
|
std::array<double, 6> result{0};
|
|
std::stringstream ss(velocityStr);
|
|
std::string value;
|
|
int i = 0;
|
|
while (std::getline(ss, value, ',') && i < 6) {
|
|
result[i++] = std::stod(value);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void OnPXREAClientCallback(void* context, PXREAClientCallbackType type, int status, void* userData)
|
|
{
|
|
switch (type)
|
|
{
|
|
case PXREAServerConnect:
|
|
std::cout << "server connect\n" << std::endl;
|
|
break;
|
|
case PXREAServerDisconnect:
|
|
std::cout << "server disconnect\n" << std::endl;
|
|
break;
|
|
case PXREADeviceFind:
|
|
std::cout << "device found\n" << (const char*)userData << std::endl;
|
|
break;
|
|
case PXREADeviceMissing:
|
|
std::cout << "device missing\n" << (const char*)userData << std::endl;
|
|
break;
|
|
case PXREADeviceConnect:
|
|
std::cout << "device connect\n" << (const char*)userData << status << std::endl;
|
|
break;
|
|
case PXREADeviceStateJson:
|
|
auto& dsj = *((PXREADevStateJson*)userData);
|
|
|
|
|
|
try {
|
|
json data = json::parse(dsj.stateJson);
|
|
if (data.contains("value")) {
|
|
auto value = json::parse(data["value"].get<std::string>());
|
|
if (value["Controller"].contains("left")) {
|
|
auto& left = value["Controller"]["left"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
LeftControllerPose = stringToPoseArray(left["pose"].get<std::string>());
|
|
LeftTrigger = left["trigger"].get<double>();
|
|
LeftGrip = left["grip"].get<double>();
|
|
LeftMenuButton = left["menuButton"].get<bool>();
|
|
LeftAxis[0] = left["axisX"].get<double>();
|
|
LeftAxis[1] = left["axisY"].get<double>();
|
|
LeftAxisClick = left["axisClick"].get<bool>();
|
|
LeftPrimaryButton = left["primaryButton"].get<bool>();
|
|
LeftSecondaryButton = left["secondaryButton"].get<bool>();
|
|
}
|
|
}
|
|
if (value["Controller"].contains("right")) {
|
|
auto& right = value["Controller"]["right"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
RightControllerPose = stringToPoseArray(right["pose"].get<std::string>());
|
|
RightTrigger = right["trigger"].get<double>();
|
|
RightGrip = right["grip"].get<double>();
|
|
RightMenuButton = right["menuButton"].get<bool>();
|
|
RightAxis[0] = right["axisX"].get<double>();
|
|
RightAxis[1] = right["axisY"].get<double>();
|
|
RightAxisClick = right["axisClick"].get<bool>();
|
|
RightPrimaryButton = right["primaryButton"].get<bool>();
|
|
RightSecondaryButton = right["secondaryButton"].get<bool>();
|
|
}
|
|
}
|
|
if (value.contains("Head")) {
|
|
auto& headset = value["Head"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(headsetPoseMutex);
|
|
HeadsetPose = stringToPoseArray(headset["pose"].get<std::string>());
|
|
}
|
|
}
|
|
if (value.contains("timeStampNs")) {
|
|
std::lock_guard<std::mutex> lock(timestampMutex);
|
|
TimeStampNs = value["timeStampNs"].get<int64_t>();
|
|
}
|
|
if (value["Hand"].contains("leftHand")) {
|
|
auto& leftHand = value["Hand"]["leftHand"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(leftHandMutex);
|
|
|
|
LeftHandScale = leftHand["scale"].get<double>();
|
|
LeftHandIsActive = leftHand["isActive"].get<int>();
|
|
for (int i = 0; i < 26; i++) {
|
|
LeftHandTrackingState[i] = stringToPoseArray(leftHand["HandJointLocations"][i]["p"].get<std::string>());
|
|
}
|
|
}
|
|
}
|
|
if (value["Hand"].contains("rightHand")) {
|
|
auto& rightHand = value["Hand"]["rightHand"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(rightHandMutex);
|
|
RightHandScale = rightHand["scale"].get<double>();
|
|
RightHandIsActive = rightHand["isActive"].get<int>();
|
|
for (int i = 0; i < 26; i++) {
|
|
RightHandTrackingState[i] = stringToPoseArray(rightHand["HandJointLocations"][i]["p"].get<std::string>());
|
|
}
|
|
}
|
|
}
|
|
// Parse Body data for whole body motion capture
|
|
if (value.contains("Body")) {
|
|
auto& body = value["Body"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
|
|
if (body.contains("timeStampNs")) {
|
|
BodyTimeStampNs = body["timeStampNs"].get<int64_t>();
|
|
}
|
|
|
|
if (body.contains("joints") && body["joints"].is_array()) {
|
|
auto joints = body["joints"];
|
|
int jointCount = std::min(static_cast<int>(joints.size()), 24);
|
|
|
|
for (int i = 0; i < jointCount; i++) {
|
|
auto& joint = joints[i];
|
|
|
|
// Parse pose (position and rotation)
|
|
if (joint.contains("p")) {
|
|
BodyJointsPose[i] = stringToPoseArray(joint["p"].get<std::string>());
|
|
}
|
|
|
|
// Parse velocity and angular velocity
|
|
if (joint.contains("va")) {
|
|
BodyJointsVelocity[i] = stringToVelocityArray(joint["va"].get<std::string>());
|
|
}
|
|
|
|
// Parse acceleration and angular acceleration
|
|
if (joint.contains("wva")) {
|
|
BodyJointsAcceleration[i] = stringToVelocityArray(joint["wva"].get<std::string>());
|
|
}
|
|
|
|
// Parse IMU timestamp
|
|
if (joint.contains("t")) {
|
|
BodyJointsTimestamp[i] = joint["t"].get<int64_t>();
|
|
}
|
|
}
|
|
|
|
BodyDataAvailable = true;
|
|
}
|
|
}
|
|
}
|
|
//parse individual tracker data
|
|
if (value.contains("Motion")) {
|
|
auto& motion = value["Motion"];
|
|
{
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
if (motion.contains("timeStampNs")) {
|
|
MotionTimeStampNs = motion["timeStampNs"].get<int64_t>();
|
|
}
|
|
if (motion.contains("joints") && motion["joints"].is_array()) {
|
|
auto joints = motion["joints"];
|
|
NumMotionDataAvailable = std::min(static_cast<int>(joints.size()), 3);
|
|
|
|
for (int i = 0; i < NumMotionDataAvailable; i++) {
|
|
auto& joint = joints[i];
|
|
|
|
// Parse pose (position and rotation)
|
|
if (joint.contains("p")) {
|
|
MotionTrackerPose[i] = stringToPoseArray(joint["p"].get<std::string>());
|
|
}
|
|
|
|
// Parse velocity and angular velocity
|
|
if (joint.contains("va")) {
|
|
MotionTrackerVelocity[i] = stringToVelocityArray(joint["va"].get<std::string>());
|
|
}
|
|
|
|
// Parse acceleration and angular acceleration
|
|
if (joint.contains("wva")) {
|
|
MotionTrackerAcceleration[i] = stringToVelocityArray(joint["wva"].get<std::string>());
|
|
}
|
|
|
|
if (joint.contains("sn")) {
|
|
MotionTrackerSerialNumbers[i] = joint["sn"].get<std::string>();
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (const json::exception& e) {
|
|
std::cerr << "JSON parsing error: " << e.what() << std::endl;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void init() {
|
|
if (PXREAInit(NULL, OnPXREAClientCallback, PXREAFullMask) != 0) {
|
|
throw std::runtime_error("PXREAInit failed");
|
|
}
|
|
}
|
|
|
|
void deinit() {
|
|
PXREADeinit();
|
|
}
|
|
|
|
std::array<double, 7> getLeftControllerPose() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftControllerPose;
|
|
}
|
|
|
|
std::array<double, 7> getRightControllerPose() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightControllerPose;
|
|
}
|
|
|
|
std::array<double, 7> getHeadsetPose() {
|
|
std::lock_guard<std::mutex> lock(headsetPoseMutex);
|
|
return HeadsetPose;
|
|
}
|
|
|
|
double getLeftTrigger() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftTrigger;
|
|
}
|
|
|
|
double getLeftGrip() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftGrip;
|
|
}
|
|
|
|
double getRightTrigger() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightTrigger;
|
|
}
|
|
|
|
double getRightGrip() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightGrip;
|
|
}
|
|
|
|
bool getLeftMenuButton() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftMenuButton;
|
|
}
|
|
|
|
bool getRightMenuButton() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightMenuButton;
|
|
}
|
|
|
|
bool getLeftAxisClick() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftAxisClick;
|
|
}
|
|
|
|
bool getRightAxisClick() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightAxisClick;
|
|
}
|
|
|
|
std::array<double, 2> getLeftAxis() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftAxis;
|
|
}
|
|
|
|
|
|
std::array<double, 2> getRightAxis() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightAxis;
|
|
}
|
|
|
|
bool getLeftPrimaryButton() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftPrimaryButton;
|
|
}
|
|
|
|
bool getRightPrimaryButton() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightPrimaryButton;
|
|
}
|
|
|
|
bool getLeftSecondaryButton() {
|
|
std::lock_guard<std::mutex> lock(leftMutex);
|
|
return LeftSecondaryButton;
|
|
}
|
|
|
|
bool getRightSecondaryButton() {
|
|
std::lock_guard<std::mutex> lock(rightMutex);
|
|
return RightSecondaryButton;
|
|
}
|
|
|
|
int64_t getTimeStampNs() {
|
|
std::lock_guard<std::mutex> lock(timestampMutex);
|
|
return TimeStampNs;
|
|
}
|
|
|
|
std::array<std::array<double, 7>, 26> getLeftHandTrackingState() {
|
|
std::lock_guard<std::mutex> lock(leftHandMutex);
|
|
return LeftHandTrackingState;
|
|
}
|
|
|
|
int getLeftHandScale() {
|
|
std::lock_guard<std::mutex> lock(leftHandMutex);
|
|
return LeftHandScale;
|
|
}
|
|
|
|
int getLeftHandIsActive() {
|
|
std::lock_guard<std::mutex> lock(leftHandMutex);
|
|
return LeftHandIsActive;
|
|
}
|
|
|
|
std::array<std::array<double, 7>, 26> getRightHandTrackingState() {
|
|
std::lock_guard<std::mutex> lock(rightHandMutex);
|
|
return RightHandTrackingState;
|
|
}
|
|
|
|
int getRightHandScale() {
|
|
std::lock_guard<std::mutex> lock(rightHandMutex);
|
|
return RightHandScale;
|
|
}
|
|
|
|
int getRightHandIsActive() {
|
|
std::lock_guard<std::mutex> lock(rightHandMutex);
|
|
return RightHandIsActive;
|
|
}
|
|
|
|
// Body tracking functions
|
|
bool isBodyDataAvailable() {
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
return BodyDataAvailable;
|
|
}
|
|
|
|
std::array<std::array<double, 7>, 24> getBodyJointsPose() {
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
return BodyJointsPose;
|
|
}
|
|
|
|
std::array<std::array<double, 6>, 24> getBodyJointsVelocity() {
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
return BodyJointsVelocity;
|
|
}
|
|
|
|
std::array<std::array<double, 6>, 24> getBodyJointsAcceleration() {
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
return BodyJointsAcceleration;
|
|
}
|
|
|
|
std::array<int64_t, 24> getBodyJointsTimestamp() {
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
return BodyJointsTimestamp;
|
|
}
|
|
|
|
int64_t getBodyTimeStampNs() {
|
|
std::lock_guard<std::mutex> lock(bodyMutex);
|
|
return BodyTimeStampNs;
|
|
}
|
|
|
|
int numMotionDataAvailable() {
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
return NumMotionDataAvailable;
|
|
}
|
|
|
|
std::vector<std::array<double, 7>> getMotionTrackerPose() {
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
std::vector<std::array<double, 7>> result;
|
|
for (int i = 0; i < NumMotionDataAvailable; i++) {
|
|
result.push_back(MotionTrackerPose[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<std::array<double, 6>> getMotionTrackerVelocity() {
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
std::vector<std::array<double, 6>> result;
|
|
for (int i = 0; i < NumMotionDataAvailable; i++) {
|
|
result.push_back(MotionTrackerVelocity[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<std::array<double, 6>> getMotionTrackerAcceleration() {
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
std::vector<std::array<double, 6>> result;
|
|
for (int i = 0; i < NumMotionDataAvailable; i++) {
|
|
result.push_back(MotionTrackerAcceleration[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::vector<std::string> getMotionTrackerSerialNumbers() {
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
std::vector<std::string> result;
|
|
for (int i = 0; i < NumMotionDataAvailable; i++) {
|
|
result.push_back(MotionTrackerSerialNumbers[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
int64_t getMotionTimeStampNs() {
|
|
std::lock_guard<std::mutex> lock(motionMutex);
|
|
return MotionTimeStampNs;
|
|
}
|
|
|
|
int DeviceControlJsonWrapper(const std::string& dev_id, const std::string& json_str) {
|
|
const int rc = PXREADeviceControlJson(dev_id.c_str(), json_str.c_str());
|
|
if (rc != 0) {
|
|
throw std::runtime_error("device_control_json failed");
|
|
}
|
|
return rc; // 0
|
|
}
|
|
|
|
int SendBytesToDeviceWrapper(const std::string& dev_id, pybind11::bytes blob) {
|
|
std::string s = blob; // copy Python bytes to std::string
|
|
const int rc = PXREASendBytesToDevice(dev_id.c_str(), s.data(), static_cast<unsigned>(s.size()));
|
|
if (rc != 0) {
|
|
throw std::runtime_error("send_bytes_to_device failed");
|
|
}
|
|
return rc; // 0
|
|
}
|
|
|
|
|
|
PYBIND11_MODULE(xrobotoolkit_sdk, m) {
|
|
m.def("init", &init, "Initialize the PXREARobot SDK.");
|
|
m.def("close", &deinit, "Deinitialize the PXREARobot SDK.");
|
|
m.def("get_left_controller_pose", &getLeftControllerPose, "Get the left controller pose.");
|
|
m.def("get_right_controller_pose", &getRightControllerPose, "Get the right controller pose.");
|
|
m.def("get_headset_pose", &getHeadsetPose, "Get the headset pose.");
|
|
m.def("get_left_trigger", &getLeftTrigger, "Get the left trigger value.");
|
|
m.def("get_left_grip", &getLeftGrip, "Get the left grip value.");
|
|
m.def("get_right_trigger", &getRightTrigger, "Get the right trigger value.");
|
|
m.def("get_right_grip", &getRightGrip, "Get the right grip value.");
|
|
m.def("get_left_menu_button", &getLeftMenuButton, "Get the left menu button state.");
|
|
m.def("get_right_menu_button", &getRightMenuButton, "Get the right menu button state.");
|
|
m.def("get_left_axis_click", &getLeftAxisClick, "Get the left axis click state.");
|
|
m.def("get_right_axis_click", &getRightAxisClick, "Get the right axis click state.");
|
|
m.def("get_left_axis", &getLeftAxis, "Get the left axis values (x, y).");
|
|
m.def("get_right_axis", &getRightAxis, "Get the right axis values (x, y).");
|
|
m.def("get_X_button", &getLeftPrimaryButton, "Get the left primary button state.");
|
|
m.def("get_A_button", &getRightPrimaryButton, "Get the right primary button state.");
|
|
m.def("get_Y_button", &getLeftSecondaryButton, "Get the left secondary button state.");
|
|
m.def("get_B_button", &getRightSecondaryButton, "Get the right secondary button state.");
|
|
m.def("get_time_stamp_ns", &getTimeStampNs, "Get the timestamp in nanoseconds.");
|
|
m.def("get_left_hand_tracking_state", &getLeftHandTrackingState, "Get the left hand state.");
|
|
m.def("get_right_hand_tracking_state", &getRightHandTrackingState, "Get the right hand state.");
|
|
m.def("get_left_hand_is_active", &getLeftHandIsActive, "Get the left hand tracking quality (0 = low, 1 = high).");
|
|
m.def("get_right_hand_is_active", &getRightHandIsActive, "Get the right hand tracking quality (0 = low, 1 = high).");
|
|
|
|
// Body tracking functions
|
|
m.def("is_body_data_available", &isBodyDataAvailable, "Check if body tracking data is available.");
|
|
m.def("get_body_joints_pose", &getBodyJointsPose, "Get the body joints pose data (24 joints, 7 values each: x,y,z,qx,qy,qz,qw).");
|
|
m.def("get_body_joints_velocity", &getBodyJointsVelocity, "Get the body joints velocity data (24 joints, 6 values each: vx,vy,vz,wx,wy,wz).");
|
|
m.def("get_body_joints_acceleration", &getBodyJointsAcceleration, "Get the body joints acceleration data (24 joints, 6 values each: ax,ay,az,wax,way,waz).");
|
|
m.def("get_body_joints_timestamp", &getBodyJointsTimestamp, "Get the body joints IMU timestamp data (24 joints).");
|
|
m.def("get_body_timestamp_ns", &getBodyTimeStampNs, "Get the body data timestamp in nanoseconds.");
|
|
|
|
// Motion tracker functions
|
|
m.def("num_motion_data_available", &numMotionDataAvailable, "Check if motion tracker data is available.");
|
|
m.def("get_motion_tracker_pose", &getMotionTrackerPose, "Get the motion tracker pose data (3 trackers, 7 values each: x,y,z,qx,qy,qz,qw).");
|
|
m.def("get_motion_tracker_velocity", &getMotionTrackerVelocity, "Get the motion tracker velocity data (3 trackers, 6 values each: vx,vy,vz,wx,wy,wz).");
|
|
m.def("get_motion_tracker_acceleration", &getMotionTrackerAcceleration, "Get the motion tracker acceleration data (3 trackers, 6 values each: ax,ay,az,wax,way,waz).");
|
|
m.def("get_motion_tracker_serial_numbers", &getMotionTrackerSerialNumbers, "Get the serial numbers of the motion trackers.");
|
|
m.def("get_motion_timestamp_ns", &getMotionTimeStampNs, "Get the motion data timestamp in nanoseconds.");
|
|
|
|
|
|
// send json bytes functions
|
|
m.def("device_control_json", &DeviceControlJsonWrapper, "Send a JSON control command to a device");
|
|
m.def("send_bytes_to_device", &SendBytesToDeviceWrapper, "Send raw bytes to a device");
|
|
|
|
m.doc() = "Python bindings for PXREARobot SDK using pybind11.";
|
|
}
|