diff --git a/CMakeLists.txt b/CMakeLists.txt index b50ef41..38bd671 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -144,7 +144,7 @@ osvr_add_plugin(com_osvr_Vive "${CMAKE_CURRENT_BINARY_DIR}/com_osvr_Vive_json.h" "${CMAKE_CURRENT_BINARY_DIR}/com_osvr_ViveSync_json.h") -target_link_libraries(com_osvr_Vive ViveLoaderLib) +target_link_libraries(com_osvr_Vive ViveLoaderLib JsonCpp::JsonCpp) target_include_directories(com_osvr_Vive PRIVATE ${EIGEN3_INCLUDE_DIR}) diff --git a/OSVRViveTracker.cpp b/OSVRViveTracker.cpp index 657e7ac..931d842 100644 --- a/OSVRViveTracker.cpp +++ b/OSVRViveTracker.cpp @@ -32,6 +32,7 @@ #include "com_osvr_Vive_json.h" // Library/third-party includes +#include "json/reader.h" #include #include #include @@ -49,8 +50,9 @@ namespace vive { /// sensor numbers in SteamVR and for tracking static const auto HMD_SENSOR = 0; static const auto CONTROLLER_SENSORS = {1, 2}; - static const auto PUCK_SENSOR = 3; static const auto MAX_CONTROLLER_ID = 2; + static const auto BASE_STATIONS_SENSORS = {3, 4}; + static const auto PUCK_SENSOR = 5; static const auto NUM_ANALOGS = 7; static const auto NUM_BUTTONS = 14; @@ -80,6 +82,11 @@ namespace vive { static const auto TRACKPAD_Y_ANALOG_OFFSET = 1; static const auto TRIGGER_ANALOG_OFFSET = 2; + /// Device descriptor values + static const auto TRACKER_VALUE = "tracker"; + static const auto PUCK_KEY = "pucks"; + static const auto SEMANTIC_KEY = "semantic"; + /// Add a util::time::TimeValue and a std::chrono::duration, returning a /// TimeValue again. /// @@ -117,7 +124,8 @@ namespace vive { ViveDriverHost::ViveDriverHost() : m_universeXform(Eigen::Isometry3d::Identity()), m_universeRotation(Eigen::Quaterniond::Identity()), - m_logger(osvr::util::log::make_logger(PREFIX)) {} + m_logger(osvr::util::log::make_logger(PREFIX)), + m_puckIdx(PUCK_SENSOR), m_devDescriptor(com_osvr_Vive_json) {} ViveDriverHost::StartResult ViveDriverHost::start(OSVR_PluginRegContext ctx, @@ -139,7 +147,7 @@ namespace vive { m_logger->info("null input device"); return false; } - auto ret = activateDevice(dev, eDeviceClass); + auto ret = activateDevice(serialNum, dev, eDeviceClass); if (!ret) { m_logger->error("Device with serial number ") << serialNum << " couldn't be added to the devices vector."; @@ -215,7 +223,7 @@ namespace vive { m_dev.initSync(ctx, "Vive", opts); /// Send JSON descriptor - m_dev.sendJsonDescriptor(com_osvr_Vive_json); + m_dev.sendJsonDescriptor(m_devDescriptor); /// Register update callback m_dev.registerUpdateCallback(this); @@ -292,9 +300,10 @@ namespace vive { } ViveDriverHost::DevIdReturnValue - ViveDriverHost::activateDevice(vr::ITrackedDeviceServerDriver *dev, + ViveDriverHost::activateDevice(const char *serialNumber, + vr::ITrackedDeviceServerDriver *dev, vr::ETrackedDeviceClass trackedDeviceClass) { - auto ret = activateDeviceImpl(dev, trackedDeviceClass); + auto ret = activateDeviceImpl(serialNumber, dev, trackedDeviceClass); vr::TrackedDeviceIndex_t idx = ret.value; auto mfrProp = getProperty(idx); auto modelProp = getProperty(idx); @@ -311,7 +320,7 @@ namespace vive { } ViveDriverHost::DevIdReturnValue ViveDriverHost::activateDeviceImpl( - vr::ITrackedDeviceServerDriver *dev, + const char *serialNumber, vr::ITrackedDeviceServerDriver *dev, vr::ETrackedDeviceClass trackedDeviceClass) { auto &devs = m_vive->devices(); if (getComponent(dev)) { @@ -325,8 +334,17 @@ namespace vive { /// This is a controller.... or a puck! if (trackedDeviceClass == vr::ETrackedDeviceClass::TrackedDeviceClass_GenericTracker) { - // puck - return devs.addAndActivateDeviceAt(dev, PUCK_SENSOR); + /// find the next available device id because number of pucks + /// is dynamic + while (devs.hasDeviceAt(m_puckIdx)) { + m_puckIdx++; + } + auto ret = devs.addAndActivateDeviceAt(dev, m_puckIdx); + // need to update device descriptor + AddDeviceToDevDescriptor(serialNumber, m_puckIdx); + DeviceDescriptorUpdated(); + m_puckIdx++; + return ret; } // controllers for (auto ctrlIdx : CONTROLLER_SENSORS) { @@ -336,6 +354,16 @@ namespace vive { } } + /// this is a base station + if (trackedDeviceClass == + vr::ETrackedDeviceClass::TrackedDeviceClass_TrackingReference) { + for (auto ctrlIdx : BASE_STATIONS_SENSORS) { + if (!devs.hasDeviceAt(ctrlIdx)) { + return devs.addAndActivateDeviceAt(dev, ctrlIdx); + } + } + } + /// This still may be a controller, if somehow there are more than /// 2... return devs.addAndActivateDevice(dev); @@ -787,13 +815,47 @@ namespace vive { state, eventTimeOffset); } } -#if 0 - void - ViveDriverHost::DeviceDescriptorUpdated(std::string const &json) { - m_dev.sendJsonDescriptor(json); + void ViveDriverHost::DeviceDescriptorUpdated() { + try { + m_dev.sendJsonDescriptor(m_devDescriptor); + } catch (std::logic_error &e) { + /// dev token hasn't been activated yet + /// we already update device descriptor so it will be sent once + /// token is activated + m_logger->info(e.what()); + } + } + + void ViveDriverHost::AddDeviceToDevDescriptor(const char *serialNumber, + uint32_t deviceIndex) { + + m_logger->debug("AddDeviceToDevDescriptor, serialNumber: ") + << std::string(serialNumber); + + Json::Value root; + Json::Reader reader; + if (!reader.parse(m_devDescriptor, root)) { + m_logger->error("Could not parse device descriptor"); + } else { + std::ostringstream trackerVal; + trackerVal << TRACKER_VALUE << "/" << deviceIndex; + std::string puckAlias = serialNumber; + /// in case serial number is not available + if (puckAlias.empty()) { + m_logger->info("Serial number not available. Using device " + "index to enumerate Vive Tracker (Puck) in " + "device descriptor"); + uint32_t puckIdx = deviceIndex - PUCK_SENSOR; + puckAlias = std::to_string(puckIdx); + } + root[SEMANTIC_KEY][PUCK_KEY][puckAlias] = trackerVal.str(); + m_logger->info("Added Vive Tracker (Puck) : " + "/com_osvr_Vive/Vive/semantic/pucks/") + << puckAlias << " -> /com_osvr_Vive/Vive/" << trackerVal.str(); + m_devDescriptor = root.toStyledString(); + } } -#endif } // namespace vive } // namespace osvr diff --git a/OSVRViveTracker.h b/OSVRViveTracker.h index fa7817b..8b2d8e6 100644 --- a/OSVRViveTracker.h +++ b/OSVRViveTracker.h @@ -106,7 +106,8 @@ namespace vive { /// to activate. Delegates the real work - this just displays /// information. DevIdReturnValue - activateDevice(vr::ITrackedDeviceServerDriver *dev, + activateDevice(const char *serialNumber, + vr::ITrackedDeviceServerDriver *dev, vr::ETrackedDeviceClass trackedDeviceClass); /// @name ServerDriverHost overrides - called from a tracker thread (not @@ -140,11 +141,15 @@ namespace vive { const VRControllerAxis_t &axisState) override; IVRSettings *GetSettings(const char *) { return nullptr; } -/// @} + /// @} + + /// Add new Vive Tracker aka Puck to the device descriptor + /// Called when more than 1 puck is connected + /// todo Can be expanded to add controllers + void AddDeviceToDevDescriptor(const char *serialNumber, + uint32_t deviceIndex); -#if 0 - void DeviceDescriptorUpdated(std::string const &json); -#endif + void DeviceDescriptorUpdated(); private: std::ostream &msg() const; @@ -175,7 +180,8 @@ namespace vive { /// Does the real work of adding a new device. DevIdReturnValue - activateDeviceImpl(vr::ITrackedDeviceServerDriver *dev, + activateDeviceImpl(const char *serialNumber, + vr::ITrackedDeviceServerDriver *dev, vr::ETrackedDeviceClass trackedDeviceClass); osvr::pluginkit::DeviceToken m_dev; @@ -238,6 +244,8 @@ namespace vive { Eigen::Quaterniond m_universeRotation; std::vector m_trackingResults; + std::uint32_t m_puckIdx; + std::string m_devDescriptor; /// @} }; using DriverHostPtr = std::unique_ptr; diff --git a/PropertyTraits.h b/PropertyTraits.h index e90d6e6..9fb60fe 100644 --- a/PropertyTraits.h +++ b/PropertyTraits.h @@ -96,6 +96,8 @@ namespace vive { ViveSystemButtonFixRequired = vr::Prop_ViveSystemButtonFixRequired_Bool, ParentDriver = vr::Prop_ParentDriver_Uint64, ResourceRoot = vr::Prop_ResourceRoot_String, + RegisteredDeviceType = vr::Prop_RegisteredDeviceType_String, + InputProfileName = vr::Prop_InputProfileName_String, ReportsTimeSinceVSync = vr::Prop_ReportsTimeSinceVSync_Bool, SecondsFromVsyncToPhotons = vr::Prop_SecondsFromVsyncToPhotons_Float, DisplayFrequency = vr::Prop_DisplayFrequency_Float, @@ -145,6 +147,18 @@ namespace vive { vr::Prop_DriverDirectModeSendsVsyncEvents_Bool, DisplayDebugMode = vr::Prop_DisplayDebugMode_Bool, GraphicsAdapterLuid = vr::Prop_GraphicsAdapterLuid_Uint64, + DriverProvidedChaperonePath = + vr::Prop_DriverProvidedChaperonePath_String, + ExpectedTrackingReferenceCount = + vr::Prop_ExpectedTrackingReferenceCount_Int32, + ExpectedControllerCount = vr::Prop_ExpectedControllerCount_Int32, + NamedIconPathControllerLeftDeviceOff = + vr::Prop_NamedIconPathControllerLeftDeviceOff_String, + NamedIconPathControllerRightDeviceOff = + vr::Prop_NamedIconPathControllerRightDeviceOff_String, + NamedIconPathTrackingReferenceDeviceOff = + vr::Prop_NamedIconPathTrackingReferenceDeviceOff_String, + DoNotApplyPrediction = vr::Prop_DoNotApplyPrediction_Bool, AttachedDeviceId = vr::Prop_AttachedDeviceId_String, SupportedButtons = vr::Prop_SupportedButtons_Uint64, Axis0Type = vr::Prop_Axis0Type_Int32, @@ -314,6 +328,13 @@ namespace vive { using type = std::string; }; template <> + struct PropertyTypeTrait { + using type = std::string; + }; + template <> struct PropertyTypeTrait { + using type = std::string; + }; + template <> struct PropertyTypeTrait { using type = bool; }; @@ -481,6 +502,38 @@ namespace vive { struct PropertyTypeTrait { using type = uint64_t; }; + template <> + struct PropertyTypeTrait { + using type = std::string; + }; + template <> + struct PropertyTypeTrait< + vr::Prop_ExpectedTrackingReferenceCount_Int32> { + using type = int32_t; + }; + template <> + struct PropertyTypeTrait { + using type = int32_t; + }; + template <> + struct PropertyTypeTrait< + vr::Prop_NamedIconPathControllerLeftDeviceOff_String> { + using type = std::string; + }; + template <> + struct PropertyTypeTrait< + vr::Prop_NamedIconPathControllerRightDeviceOff_String> { + using type = std::string; + }; + template <> + struct PropertyTypeTrait< + vr::Prop_NamedIconPathTrackingReferenceDeviceOff_String> { + using type = std::string; + }; + template <> + struct PropertyTypeTrait { + using type = bool; + }; template <> struct PropertyTypeTrait { using type = std::string; }; diff --git a/ServerDriverHost.cpp b/ServerDriverHost.cpp index 6cd3cea..20ef057 100644 --- a/ServerDriverHost.cpp +++ b/ServerDriverHost.cpp @@ -125,4 +125,11 @@ void ServerDriverHost::GetRawTrackedDevicePoses( logger_->debug("GetRawTrackedDevicePoses(") << fPredictedSecondsFromNow << ", " << unTrackedDevicePoseArrayCount << ")"; +} + +void ServerDriverHost::TrackedDeviceDisplayTransformUpdated( + uint32_t unWhichDevice, HmdMatrix34_t eyeToHeadLeft, + HmdMatrix34_t eyeToHeadRight) { + logger_->debug("TrackedDeviceDisplayTransformUpdated(") + << unWhichDevice << ", eyeToHeadLeft, eyeToHeadRight)"; } \ No newline at end of file diff --git a/ServerDriverHost.h b/ServerDriverHost.h index 1751d4a..c6ef57b 100644 --- a/ServerDriverHost.h +++ b/ServerDriverHost.h @@ -98,6 +98,11 @@ class ServerDriverHost : public vr::IVRServerDriverHost { TrackedDevicePose_t *pTrackedDevicePoseArray, uint32_t unTrackedDevicePoseArrayCount); + virtual void + TrackedDeviceDisplayTransformUpdated(uint32_t unWhichDevice, + HmdMatrix34_t eyeToHeadLeft, + HmdMatrix34_t eyeToHeadRight); + IVRSettings *vrSettings = nullptr; private: diff --git a/com_osvr_Vive.json b/com_osvr_Vive.json index 3706fe0..bf05014 100644 --- a/com_osvr_Vive.json +++ b/com_osvr_Vive.json @@ -19,14 +19,16 @@ } }, "semantic": { - "hmd": { + "hmd": { "$target": "tracker/0", - "button": "button/0", + "button": "button/0", "proximity": "button/1" - }, - "puck": { - "$target": "tracker/3" - }, + }, + "baseStations": { + "0": "tracker/3", + "1": "tracker/4" + }, + "pucks": {}, "ipd": "analog/0", "controller": { "left": { @@ -65,7 +67,6 @@ }, "automaticAliases": { "/me/head": "semantic/hmd", - "/me/puck": "semantic/puck", "/me/ipd": "semantic/ipd", "/controller": "semantic/controller/*", "/me/hands/left": "semantic/controller/left", diff --git a/vendor/openvr b/vendor/openvr index bcac1bf..167e26e 160000 --- a/vendor/openvr +++ b/vendor/openvr @@ -1 +1 @@ -Subproject commit bcac1bfbe2be3c1ff37e4f62b8e412fcdf29248e +Subproject commit 167e26e4b9b352614c5f3a83a8434b185f63ed0f