OSVR-Vive

来源:互联网 发布:淘宝退货怎么寄件 编辑:程序博客网 时间:2024/05/17 08:18
DriverWrapper类(DriverWrapper.h),主要有:

1.openvr_driver.h中接口:


vr::ITrackedDeviceServerDriver:

@brief:表示一个追踪设备。在驱动动态库中实现,如vive的driver_lighthouse.dll,运行时被vrserver加载,可用ITrackedDeviceServerProvider对象的Cleanup方法卸载。

vr::IVRServerDriverHost:

@brief:向server发送各类事件通知(Pose或Button按键信息等),提供以下函数功能:

1>.TrackedDeviceAdded:通知server一个追踪设备已经被添加。若返回true,则server将调用该设备的Active函数,若返回false,则该设备不会被active

2>.TrackedDevicePoseUpdated:往server发送pose信息

3>.TrackedDeviceAxisUpdated:往server发送x,y坐标轴信息(Joystick触摸板)

4>.GetRawTrackedDevicePoses:v1.0.7版本添加的函数,为驱动提供设备裸Pose信息


vr::IServerTrackedDeviceProvider:

@brief:用于查询发送追踪设备信息并往server发送,可理解为一个client与server的中间桥梁作用,在驱动dll动态库中实现,运行时被vrserver加载调用。提供以下函数:

1>.HmdError Init( IDriverLog *pDriverLog, vr::IServerDriverHost *pDriverHost, const char *pchUserDriverConfigDir, const char *pchDriverInstallDir ):

@brief:初始化驱动,该函数最先被调用(在任何函数之前)。当且仅当返回HmdError_None时,dll驱动才会被调用。

@pchUserDriverConfigDir:驱动用户配置文件的绝对路径,如:Steam\config

@pchDriverInstallDir:驱动根目录绝对路径,如:Steam\steamapps\common\SteamVR\drivers\lighthouse\bin\win64

@note:在V1.0.6之后,若provider含有HMD,则需在Init返回前,调用TrackedDeviceAdded添加HMD的详细信息。其他设备则可在任何时候调用TrackedDeviceAdded添加。

后续版本被virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0所取代。

其中IVRDriverContext在后面分析。

2>.virtual void Cleanup():

@brief: 卸载vr::ITrackedDeviceServerDriver声明的驱动。

3>.virtual const char * const *GetInterfaceVersions() = 0:

@brief:返回驱动使用的vr::ITrackedDeviceServerDriver接口的版本号

4>.virtual void RunFrame() = 0:

@brief:在server的main循环中被调用,通过vr::ITrackedDeviceServerDriver提供的数据接口循环往server发送pose或button或axis等信息

5>.uint32_t GetTrackedDeviceCount():

@brief:返回驱动连接追踪设备的数量。在启动时,可用来初始化驱动的追踪设备链表。


vr::IVRDriverContext:

@brief:获取驱动所需使用到的接口以及获取驱动handle

1>.virtual void *GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError = nullptr ) = 0:

@berief:通过版本号获取接口,以供后续使用。如:

m_pVRServerDriverHost = (IVRServerDriverHost *)VRDriverContext()->GetGenericInterface( IVRServerDriverHost_Version, &eError );  static const char *IVRServerDriverHost_Version = "IVRServerDriverHost_004"; 
@note:在新版本vr::IServerTrackedDeviceProvider的Init使用到。

比如:

EVRInitError CServerDriver_Sample::Init( vr::IVRDriverContext *pDriverContext )  {      VR_INIT_SERVER_DRIVER_CONTEXT( pDriverContext );      InitDriverLog( vr::VRDriverLog() );        m_pNullHmdLatest = new CSampleDeviceDriver();      vr::VRServerDriverHost()->TrackedDeviceAdded( m_pNullHmdLatest->GetSerialNumber().c_str(), vr::TrackedDeviceClass_HMD, m_pNullHmdLatest );      return VRInitError_None;  }  
在VR_INIT_SERVER_DRIVER_CONTEXT( pDriverContext )初始化m_pVRServerDriverHost,m_pVRSettings,

m_propertyHelpers,m_pVRDriverLog,m_pVRDriverManager,m_pVRResources接口,以供后续调用它们的方法。

2>.virtual DriverHandle_t GetDriverHandle() = 0:
@brief:返回该驱动属性容器的句柄

vr::IVRSettings:

@brief:提供接口用来获取类似Steam\steamapps\common\SteamVR\resources\settings\default.vrsettings文件下的属性字段

vr::IVRDriverLog:

@virtual void Log( const char *pchLogMessage ) = 0:

将log输出到log文件,并在log文件名前加驱动名前缀。

vr::IVRProperties:

@brief:对设备的属性进行读写,设备属性有追踪设备系统名,产品型号,产品序列号等。

enum ETrackedDeviceProperty  {      Prop_Invalid                                = 0,        // general properties that apply to all device classes      Prop_TrackingSystemName_String              = 1000,      Prop_ModelNumber_String                     = 1001,      Prop_SerialNumber_String                    = 1002,      Prop_RenderModelName_String                 = 1003,      Prop_WillDriftInYaw_Bool                    = 1004,      Prop_ManufacturerName_String                = 1005,      Prop_TrackingFirmwareVersion_String         = 1006,      Prop_HardwareRevision_String                = 1007,      Prop_AllWirelessDongleDescriptions_String   = 1008,      Prop_ConnectedWirelessDongle_String         = 1009,      Prop_DeviceIsWireless_Bool                  = 1010,      Prop_DeviceIsCharging_Bool                  = 1011,      Prop_DeviceBatteryPercentage_Float          = 1012, // 0 is empty, 1 is full      Prop_StatusDisplayTransform_Matrix34        = 1013,      Prop_Firmware_UpdateAvailable_Bool          = 1014,      Prop_Firmware_ManualUpdate_Bool             = 1015,      Prop_Firmware_ManualUpdateURL_String        = 1016,      Prop_HardwareRevision_Uint64                = 1017,      Prop_FirmwareVersion_Uint64                 = 1018,      Prop_FPGAVersion_Uint64                     = 1019,      Prop_VRCVersion_Uint64                      = 1020,      Prop_RadioVersion_Uint64                    = 1021,      Prop_DongleVersion_Uint64                   = 1022,      Prop_BlockServerShutdown_Bool               = 1023,      Prop_CanUnifyCoordinateSystemWithHmd_Bool   = 1024,      Prop_ContainsProximitySensor_Bool           = 1025,      Prop_DeviceProvidesBatteryStatus_Bool       = 1026,      Prop_DeviceCanPowerOff_Bool                 = 1027,      Prop_Firmware_ProgrammingTarget_String      = 1028,      Prop_DeviceClass_Int32                      = 1029,      Prop_HasCamera_Bool                         = 1030,      Prop_DriverVersion_String                   = 1031,      Prop_Firmware_ForceUpdateRequired_Bool      = 1032,      Prop_ViveSystemButtonFixRequired_Bool       = 1033,      Prop_ParentDriver_Uint64                    = 1034,      Prop_ResourceRoot_String                    = 1035,        // Properties that are unique to TrackedDeviceClass_HMD      Prop_ReportsTimeSinceVSync_Bool             = 2000,      Prop_SecondsFromVsyncToPhotons_Float        = 2001,      Prop_DisplayFrequency_Float                 = 2002,      Prop_UserIpdMeters_Float                    = 2003,      Prop_CurrentUniverseId_Uint64               = 2004,       Prop_PreviousUniverseId_Uint64              = 2005,       Prop_DisplayFirmwareVersion_Uint64          = 2006,      Prop_IsOnDesktop_Bool                       = 2007,      Prop_DisplayMCType_Int32                    = 2008,      Prop_DisplayMCOffset_Float                  = 2009,      Prop_DisplayMCScale_Float                   = 2010,      Prop_EdidVendorID_Int32                     = 2011,      Prop_DisplayMCImageLeft_String              = 2012,      Prop_DisplayMCImageRight_String             = 2013,      Prop_DisplayGCBlackClamp_Float              = 2014,      Prop_EdidProductID_Int32                    = 2015,      Prop_CameraToHeadTransform_Matrix34         = 2016,      Prop_DisplayGCType_Int32                    = 2017,      Prop_DisplayGCOffset_Float                  = 2018,      Prop_DisplayGCScale_Float                   = 2019,      Prop_DisplayGCPrescale_Float                = 2020,      Prop_DisplayGCImage_String                  = 2021,      Prop_LensCenterLeftU_Float                  = 2022,      Prop_LensCenterLeftV_Float                  = 2023,      Prop_LensCenterRightU_Float                 = 2024,      Prop_LensCenterRightV_Float                 = 2025,      Prop_UserHeadToEyeDepthMeters_Float         = 2026,      Prop_CameraFirmwareVersion_Uint64           = 2027,      Prop_CameraFirmwareDescription_String       = 2028,      Prop_DisplayFPGAVersion_Uint64              = 2029,      Prop_DisplayBootloaderVersion_Uint64        = 2030,      Prop_DisplayHardwareVersion_Uint64          = 2031,      Prop_AudioFirmwareVersion_Uint64            = 2032,      Prop_CameraCompatibilityMode_Int32          = 2033,      Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034,      Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035,      Prop_DisplaySuppressed_Bool                 = 2036,      Prop_DisplayAllowNightMode_Bool             = 2037,      Prop_DisplayMCImageWidth_Int32              = 2038,      Prop_DisplayMCImageHeight_Int32             = 2039,      Prop_DisplayMCImageNumChannels_Int32        = 2040,      Prop_DisplayMCImageData_Binary              = 2041,      Prop_SecondsFromPhotonsToVblank_Float       = 2042,        // Properties that are unique to TrackedDeviceClass_Controller      Prop_AttachedDeviceId_String                = 3000,      Prop_SupportedButtons_Uint64                = 3001,      Prop_Axis0Type_Int32                        = 3002, // Return value is of type EVRControllerAxisType      Prop_Axis1Type_Int32                        = 3003, // Return value is of type EVRControllerAxisType      Prop_Axis2Type_Int32                        = 3004, // Return value is of type EVRControllerAxisType      Prop_Axis3Type_Int32                        = 3005, // Return value is of type EVRControllerAxisType      Prop_Axis4Type_Int32                        = 3006, // Return value is of type EVRControllerAxisType      Prop_ControllerRoleHint_Int32               = 3007, // Return value is of type ETrackedControllerRole        // Properties that are unique to TrackedDeviceClass_TrackingReference      Prop_FieldOfViewLeftDegrees_Float           = 4000,      Prop_FieldOfViewRightDegrees_Float          = 4001,      Prop_FieldOfViewTopDegrees_Float            = 4002,      Prop_FieldOfViewBottomDegrees_Float         = 4003,      Prop_TrackingRangeMinimumMeters_Float       = 4004,      Prop_TrackingRangeMaximumMeters_Float       = 4005,      Prop_ModeLabel_String                       = 4006,        // Properties that are used for user interface like icons names      Prop_IconPathName_String                        = 5000, // usually a directory named "icons"      Prop_NamedIconPathDeviceOff_String              = 5001, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceSearching_String        = 5002, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceSearchingAlert_String   = 5003, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceReady_String            = 5004, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceReadyAlert_String       = 5005, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceNotReady_String         = 5006, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceStandby_String          = 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others      Prop_NamedIconPathDeviceAlertLow_String         = 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others        // Properties that are used by helpers, but are opaque to applications      Prop_DisplayHiddenArea_Binary_Start             = 5100,      Prop_DisplayHiddenArea_Binary_End               = 5150,        // Properties that are unique to drivers      Prop_UserConfigPath_String                  = 6000,      Prop_InstallPath_String                     = 6001,      Prop_HasDisplayComponent_Bool               = 6002,      Prop_HasControllerComponent_Bool            = 6003,      Prop_HasCameraComponent_Bool                = 6004,      Prop_HasDriverDirectModeComponent_Bool      = 6005,      Prop_HasVirtualDisplayComponent_Bool        = 6006,        // Vendors are free to expose private debug data in this reserved region      Prop_VendorSpecific_Reserved_Start          = 10000,      Prop_VendorSpecific_Reserved_End            = 10999,  }  

在vr::ITrackedDeviceServerDriver设备驱动中使用如下:

virtual EVRInitError Activate( vr::TrackedDeviceIndex_t unObjectId )  {          m_unObjectId = unObjectId;          m_ulPropertyContainer = vr::VRProperties()->TrackedDeviceToPropertyContainer( m_unObjectId );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, Prop_ModelNumber_String, m_sModelNumber.c_str() );          vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, Prop_RenderModelName_String, m_sModelNumber.c_str() );          vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_UserIpdMeters_Float, m_flIPD );          vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_UserHeadToEyeDepthMeters_Float, 0.f );          vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_DisplayFrequency_Float, m_flDisplayFrequency );          vr::VRProperties()->SetFloatProperty( m_ulPropertyContainer, Prop_SecondsFromVsyncToPhotons_Float, m_flSecondsFromVsyncToPhotons );            // return a constant that's not 0 (invalid) or 1 (reserved for Oculus)          vr::VRProperties()->SetUint64Property( m_ulPropertyContainer, Prop_CurrentUniverseId_Uint64, 2 );            // avoid "not fullscreen" warnings from vrmonitor          vr::VRProperties()->SetBoolProperty( m_ulPropertyContainer, Prop_IsOnDesktop_Bool, false );            // Icons can be configured in code or automatically configured by an external file "drivername\resources\driver.vrresources".          // Icon properties NOT configured in code (post Activate) are then auto-configured by the optional presence of a driver's "drivername\resources\driver.vrresources".          // In this manner a driver can configure their icons in a flexible data driven fashion by using an external file.          //          // The structure of the driver.vrresources file allows a driver to specialize their icons based on their HW.          // Keys matching the value in "Prop_ModelNumber_String" are considered first, since the driver may have model specific icons.          // An absence of a matching "Prop_ModelNumber_String" then considers the ETrackedDeviceClass ("HMD", "Controller", "GenericTracker", "TrackingReference")          // since the driver may have specialized icons based on those device class names.          //          // An absence of either then falls back to the "system.vrresources" where generic device class icons are then supplied.          //          // Please refer to "bin\drivers\sample\resources\driver.vrresources" which contains this sample configuration.          //          // "Alias" is a reserved key and specifies chaining to another json block.          //          // In this sample configuration file (overly complex FOR EXAMPLE PURPOSES ONLY)....          //          // "Model-v2.0" chains through the alias to "Model-v1.0" which chains through the alias to "Model-v Defaults".          //          // Keys NOT found in "Model-v2.0" would then chase through the "Alias" to be resolved in "Model-v1.0" and either resolve their or continue through the alias.          // Thus "Prop_NamedIconPathDeviceAlertLow_String" in each model's block represent a specialization specific for that "model".          // Keys in "Model-v Defaults" are an example of mapping to the same states, and here all map to "Prop_NamedIconPathDeviceOff_String".          //          bool bSetupIconUsingExternalResourceFile = true;          if ( !bSetupIconUsingExternalResourceFile )          {              // Setup properties directly in code.              // Path values are of the form {drivername}\icons\some_icon_filename.png              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceOff_String, "{sample}/icons/headset_sample_status_off.png" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceSearching_String, "{sample}/icons/headset_sample_status_searching.gif" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceSearchingAlert_String, "{sample}/icons/headset_sample_status_searching_alert.gif" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceReady_String, "{sample}/icons/headset_sample_status_ready.png" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceReadyAlert_String, "{sample}/icons/headset_sample_status_ready_alert.png" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceNotReady_String, "{sample}/icons/headset_sample_status_error.png" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceStandby_String, "{sample}/icons/headset_sample_status_standby.png" );              vr::VRProperties()->SetStringProperty( m_ulPropertyContainer, vr::Prop_NamedIconPathDeviceAlertLow_String, "{sample}/icons/headset_sample_status_ready_low.png" );          }            return VRInitError_None;  }  
2.自定义类:

DeviceHolder类:


1>.addAndActivateDevice():代码如下:

IdReturnValue         addAndActivateDevice(vr::ITrackedDeviceServerDriver *dev) {             /// check to make sure it's not null and not already in there             if (!dev) {                 return IdReturnValue::makeError();             }             auto existing = findDevice(dev);//查找             if (existing) {                 /// @todo do we return an error or the existing location? This                 /// returns the existing location after re-activating.                 dev->Activate(existing.value);                 return existing;             }             auto newId = static_cast<std::uint32_t>(devices_.size());             devices_.push_back(dev);             dev->Activate(newId);             return IdReturnValue::makeValue(newId);         }  


@brief:查找容器devices_中是否存在dev设备驱动,若存在,则active它并返回它的id号;反之,则添加进devices_并返回id号。

2>.addAndActivateDeviceAt():代码如下:

/// Add and activate a device at a reserved id.          IdReturnValue          addAndActivateDeviceAt(vr::ITrackedDeviceServerDriver *dev,                                 std::uint32_t idx) {              /// check to make sure it's not null and not already in there              if (!dev) {                  return IdReturnValue::makeError();              }              auto existing = findDevice(dev);              if (existing && existing.value != idx) {                  // if we already found it in there and it's not at the desired                  // index...                  return IdReturnValue(existing.value, false);              }                if (existing) {                  // well, in this case, we might need to just activate it again.                  dev->Activate(idx);                  return IdReturnValue::makeValue(idx);              }                if (!(idx < devices_.size())) {                  // OK, we need to reserve more room.                  reserveIds(idx + 1);              }                if (devices_[idx]) {                  // there's already somebody else there...                  return IdReturnValue::makeError();              }                /// Finally, if we made it through that, it's our turn.              devices_[idx] = dev;              dev->Activate(idx);                return IdReturnValue::makeValue(idx);          }  
@brief:激活指定idx的设备。

InterfaceVersionSupport类:

@brief:辅助类,用于管理接口版本号

1>.InterfaceVersionSupport() : supportedInterfaces_(populate()) {}

@brief:接收populate的返回值

2>.populate:

/// Function to create and populate the supported interface        /// container, so the object's data member may be const.        static Container populate() {            Container ret;            // Populate a vector with all the supported interfaces.            for_each_const_string_array(                vr::k_InterfaceVersions,                [&](const char *str) { ret.emplace_back(str); });              // so we can use binary_search            std::sort(ret.begin(), ret.end());            return ret;        }  

@brief:将openvr_driver.h中声明的vr::k_InterfaceVersions传入lambda函数,加入vector。之后按序列从小到大排列,
并返回赋给supportedInterfaces_

namespace vr  {      static const char * const k_InterfaceVersions[] =      {          IVRSettings_Version,          ITrackedDeviceServerDriver_Version,          IVRDisplayComponent_Version,          IVRDriverDirectModeComponent_Version,          IVRControllerComponent_Version,          IVRCameraComponent_Version,          IServerTrackedDeviceProvider_Version,          IVRWatchdogProvider_Version,          IVRVirtualDisplay_Version,          IVRDriverManager_Version,          IVRResources_Version,          nullptr      };  ...    }  
2>.inline bool isInterfaceNameWeCareAbout(std::string const &interfaceName)

@brief:用于检查传入的接口类是否为该驱动所care的接口类

/// A list of just the interface names we actually use.          static const auto interfaceNamesWeCareAbout = {              "ITrackedDeviceServerDriver", "IVRDisplayComponent",              "IVRControllerComponent", //< @todo do we actually use/cast to                                        // this interface?              "IServerTrackedDeviceProvider", "IVRWatchdogProvider"};        } // namespace detail        inline bool isInterfaceNameWeCareAbout(std::string const &interfaceName) {          return std::find(detail::interfaceNamesWeCareAbout.begin(),                           detail::interfaceNamesWeCareAbout.end(),                           interfaceName) !=                 detail::interfaceNamesWeCareAbout.end();      } 

DriverLoader:
@brief:用来加载一个steamVR driver dll驱动,获取主入口点及其函数调用,这个类是驱动运行的必要条件。
1>. /// Factory function to make a driver loader.
        static std::unique_ptr<DriverLoader>
        make(std::string const &driverRoot, std::string const &driverFile);
@brief:工厂方法生成一个驱动加载对象。


loader_ = DriverLoader::make(locations_.driverRoot,                                           locations_.driverFile);  

驱动根目录(driverRoot)如:Steam\steamapps\common\SteamVR\drivers\lighthouse\bin\win64
驱动文件(driverFile)如:Steam\steamapps\common\SteamVR\drivers\lighthouse\bin\win64\driver_lighthouse.dll


2>.template <typename InterfaceType>
        ReturnValue<InterfaceType *, int> getInterface()
@brief:获取模板参数InterfaceType指定的接口类。最初由getProvider<vr::IServerTrackedDeviceProvider>调用。

3>.std::string const &getDriverRoot()

@brief:获取根目录,如:

Steam\steamapps\common\SteamVR\drivers\lighthouse\bin\win64

ChaperoneData:
@brief:一些已知的追踪器空间范围的数据。比如空间界限,游戏空间等。来自于chaperone_info,位于<Steam\config\chaperone_info.vrchap>

1>.struct UniverseData {
            CalibrationType type = CalibrationType::Standing;
            std::array<double, 3> translation;
            double yaw = 0.;
        };

@brief:空间数据。类型:站立。数据:位置信息以及偏航角。

2>.ChaperoneData::ChaperoneData(std::string const &steamConfigDir)
        : impl_(new Impl), configDir_(steamConfigDir)

@brief:从chaperone_info.vrchap文件中获取字段填充成员变量impl_,结构代码如下:

struct ChaperoneData::Impl {          Json::Value chaperoneInfo;          UniverseDataMap universes;          UniverseBaseSerials baseSerials;      };  

3>.UniverseData getDataForUniverse(UniverseId universe) const
@brief:获取外设数据。


ChaperoneData::UniverseData      ChaperoneData::getDataForUniverse(UniverseId universe) const {          auto it = impl_->universes.find(universe);          if (it == end(impl_->universes)) {              return UniverseData();          }          return it->second; // ChaperoneData::UniverseData类型      }  
@brief:通过universe号获取对应的键值
 
using UniverseDataMap =

        std::map<std::uint64_t, ChaperoneData::UniverseData>;


4>. UniverseId        guessUniverseIdFromBaseStations(BaseStationSerials const &bases);

using BaseStationSerials = std::vector<std::string>;    ChaperoneData::UniverseId ChaperoneData::guessUniverseIdFromBaseStations(          BaseStationSerials const &bases) {          auto providedSize = bases.size();          UniverseId ret = 0;          using UniverseRank = std::pair<float, UniverseId>;          /// Compare function for heap.          auto compare = [](UniverseRank const &a, UniverseRank const &b) {              return a.first < b.first;          };            /// Will contain heap of potential universes and their value (a fraction          /// of their base stations and provided base stations that were included          /// in the base station list provided to the function)          std::vector<UniverseRank> potentialUniverses;          auto push = [&](float value, UniverseId id) {              potentialUniverses.emplace_back(value, id);              std::push_heap(begin(potentialUniverses), end(potentialUniverses),                             compare);          };            for (auto &univBaseSerial : impl_->baseSerials) {              auto const &baseSerials = univBaseSerial.second;              std::size_t hits = 0;              auto b = begin(baseSerials);              auto e = end(baseSerials);              /// Count the number of entries that we were given that are also in              /// this universe's list.              auto found = std::count_if(begin(bases), end(bases),                                         [&](std::string const &needle) {                                             return std::find(b, e, needle) != e;                                         });              if (found > 0) {                  /// This is meant to combine the influence of "found" in both                  /// providedSize and universe size, and the +1 in the                  /// denominator is to avoid division by zero.                  auto weight = 2.f * static_cast<float>(found) /                                (baseSerials.size() + providedSize + 1);  #if 0                  std::cout << "Guessing produced weight of " << weight << " for "                            << univBaseSerial.first << std::endl;  #endif                  push(weight, univBaseSerial.first);              }          }          if (!potentialUniverses.empty()) {              /// it's a heap, so the best one is always on top.              return potentialUniverses.front().second;          }          return ret;      }  

@brief:由基站预测id。


com_osvr_Vive.cpp为OSVR插件一般结构:

OSVR_ReturnCode update(){          if (m_startedInSuccess) {              return OSVR_RETURN_SUCCESS;          }            if (!m_shouldAttemptDetection) {              /// We said we shouldn't and wouldn't try again.              return OSVR_RETURN_FAILURE;          }            /// Hand the Vive object off to the OSVR driver.          auto startResult = finishViveStartup();// 进入          if (startResult) {              /// and it started up the rest of the way just fine!              /// We'll keep the driver around!              m_logger->info("Vive driver finished startup successfully!");              m_startedInSuccess = true;              return OSVR_RETURN_SUCCESS;          }            m_logger->error("Vive driver startup failed.");            if (m_shouldAttemptDetection) {              m_logger->info(" Unloading to perhaps try again later.");          }            return OSVR_RETURN_FAILURE;      }  

finishViveStartup()中调用ViveDriverHost中的start方法。

ViveDriverHost类:继承自vr::IVRServerDriverHost:
ViveDriverHost::StartResult      ViveDriverHost::start(OSVR_PluginRegContext ctx,                            osvr::vive::DriverWrapper &&inVive)  {          if (!inVive) {              m_logger->error(                  "Called ViveDriverHost::start() with an invalid vive object!");              return StartResult::TemporaryFailure;          }          /// Take ownership of the Vive.          m_vive.reset(new osvr::vive::DriverWrapper(std::move(inVive)));            /// define the lambda to handle the ServerDriverHost::TrackedDeviceAdded          auto handleNewDevice = [&](const char *serialNum,                                     ETrackedDeviceClass eDeviceClass,                                     ITrackedDeviceServerDriver *pDriver) {              auto dev = pDriver;              if (!dev) {                  m_logger->info("null input device");                  return false;              }              auto ret = activateDevice(dev, eDeviceClass);              if (!ret) {                  m_logger->error("Device with serial number ")                      << serialNum << " couldn't be added to the devices vector.";                  return false;              }              NewDeviceReport out{std::string{serialNum}, ret.value};              {                  std::lock_guard<std::mutex> lock(m_mutex);                  m_newDevices.submitNew(std::move(out), lock);              }              return true;          };            m_vive->driverHost().onTrackedDeviceAdded = handleNewDevice;            /// Finish setting up the Vive.          try {              if (!m_vive->startServerDeviceProvider()) {                  m_logger->error("Could not start the server device provider in "                                  "the Vive driver. Exiting.");                  return StartResult::TemporaryFailure;              }          } catch (CouldNotGetInterface &e) {              m_logger->error("Caught exception trying to start Vive server "                              "device provider: ")                  << e.what();              m_logger->error("SteamVR interface version may have changed, may "                              "need to be rebuilt against an updated header or "                              "use an older SteamVR version. Exiting.");              return StartResult::PermanentFailure;          }            /// Check for interface compatibility          if (DriverWrapper::InterfaceVersionStatus::InterfaceMismatch ==              m_vive->checkServerDeviceProviderInterfaces()) {              m_logger->error(                  "SteamVR lighthouse driver requires unavailable/unsupported "                  "SteamVR lighthouse driver requires unavailable/unsupported "                  "interface versions - either too old or too new for this "                  "build. Specifically, the following critical mismaches: ");              for (auto iface : m_vive->getUnsupportedRequestedInterfaces()) {                  if (isInterfaceNameWeCareAbout(                          detail::getInterfaceName(iface))) {                      auto supported =                          m_vive->getSupportedInterfaceVersions()                              .findSupportedVersionOfInterface(iface);                      m_logger->error(" - SteamVR lighthouse: ")                          << iface << "\t\t OSVR-Vive: " << supported;                  }              }              m_logger->error("Cannot continue.\n");              return StartResult::PermanentFailure;          }            /// Power the system up.          m_vive->serverDevProvider().LeaveStandby();            /// Reserve ID 0 for the HMD          m_vive->devices().reserveIds(1);            /// Finish setting this up as an OSVR device.          /// Create the initialization options          OSVR_DeviceInitOptions opts = osvrDeviceCreateInitOptions(ctx);            osvrDeviceTrackerConfigure(opts, &m_tracker);          osvrDeviceAnalogConfigure(opts, &m_analog, NUM_ANALOGS);          osvrDeviceButtonConfigure(opts, &m_button, NUM_BUTTONS);            /// Because the callbacks may not come from the same thread that          /// calls RunFrame, we need to be careful to not send directly from          /// those callbacks. We can't use an Async device token because the          /// waits are too long and they goof up the SteamVR Lighthouse driver.          m_dev.initSync(ctx, "Vive", opts);            /// Send JSON descriptor          m_dev.sendJsonDescriptor(com_osvr_Vive_json);            /// Register update callback          m_dev.registerUpdateCallback(this);            return StartResult::Success;      }  

1>.将参数DriverWrapper类对象inVive赋给成员变量m_vive
2>.将lambda函数指针handleNewDevice赋给onTrackedDeviceAdded(由m_vive控制的driverHost类):
lambda函数截获串号(类似hydra_controller1或hydra_controller2之类的字符串形式),设备类别(类似HMD PUCK等)以及
设备驱动。通过参数传入将指定idx的外设添加到容器std::vector<vr::ITrackedDeviceServerDriver *> devices_中
,并激活它,激活后返回它的idx值赋值给ret.value。之后,将serialNum与ret.value构造一个NewDeviceReport类,将该类存入
队列deque_。
3>.将lambda函数赋给 m_vive->driverHost().onTrackedDeviceAdded。将在ServerDeviceProvider启动后,在Init中被调用。
4>.startServerDeviceProvider:
初始化vr::IVRSettings,vr::IVRDriverLog,vr::IVRProperties类对象,并使用它们构建一个vr::DriverContext类对象,再通过
VR_INIT_SERVER_DRIVER_CONTEXT(context_)本质上是给COpenVRDriverContext类的m_pVRSettings,m_pVRDriverLog,m_pVRProperties
赋值。以供后续如TrackedDeviceAdded使用。

#define VR_INIT_SERVER_DRIVER_CONTEXT( pContext ) \            { \            vr::EVRInitError eError = vr::InitServerDriverContext( pContext ); \            if( eError != vr::VRInitError_None ) \                return eError; \            }  

在将环境准备好之后,serverDeviceProvider_ =
                getProvider<vr::IServerTrackedDeviceProvider>(
                    std::move(loader_), context_);
 
传入模板参数vr::IServerTrackedDeviceProvider, 随后:

template <typename InterfaceType>      inline ProviderPtr<InterfaceType>      getProvider(std::unique_ptr<DriverLoader> &&loader,                  vr::IVRDriverContext *context) {          static_assert(              InterfaceExpectedFromEntryPointTrait<InterfaceType>::value,              "Function only valid for those 'provider' interface types "              "expected to be provided by the driver entry point.");          return detail::getProviderImpl<InterfaceType>(              std::move(loader), context, [](SharedDriverLoader const &) {});      }  

传入一个lambda函数指针(不捕获时才可转换为函数指针)。

template <typename InterfaceType, typename F>          inline ProviderPtr<InterfaceType>          getProviderImpl(std::unique_ptr<DriverLoader> &&loader,                          vr::IVRDriverContext *context,                          F &&driverLoaderFunctor) {              using return_type = ProviderPtr<InterfaceType>;                if (!loader) {                  return return_type{};              }              /// Move into local pointer, so if something goes wrong, the driver              /// gets unloaded.              std::unique_ptr<DriverLoader> myLoader(std::move(loader));              auto rawPtr = myLoader->getInterfaceThrowing<InterfaceType>();              auto initResults = rawPtr->Init(context);              if (vr::VRInitError_None != initResults) {                  /// Failed, reset the loader pointer to unload the driver.                  std::cout << "Got error code " << initResults << std::endl;                  myLoader.reset();                  return return_type{};              }                /// OK, so this is the interface. Move the loader into a shared              /// pointer, make the loader responsible for cleanup of the              /// interface, and get the shared pointer of the interface pointer              /// returned.              SharedDriverLoader sharedLoader(std::move(myLoader));              sharedLoader->cleanupInterfaceOnDestruction(rawPtr);                /// Call the hook              (std::forward<F>(driverLoaderFunctor))(sharedLoader);                /// Create the return value: another shared pointer.              /// This is the so-called "aliasing" constructor - this pointer will              /// actually keep the DriverLoader alive and do nothing with the              /// lifetime of rawPtr (which is why the loader is responsible for              /// calling Cleanup, see above)              return_type ret(sharedLoader, rawPtr);                return ret;          }  

(std::forward<F>(driverLoaderFunctor))(sharedLoader):钩子获取dll中的接口,与driver_lighthouse.dll衔接。

其中sharedLoader最初由loader_ = DriverLoader::make(locations_.driverRoot,locations_.driverFile);构建而成。

std::unique_ptr<DriverLoader>      DriverLoader::make(std::string const &driverRoot,                         std::string const &driverFile) {          std::unique_ptr<DriverLoader> ret(              new DriverLoader(driverRoot, driverFile));          return ret;      }  

返回一个DriverLoader对象。

DriverLoader::DriverLoader(std::string const &driverRoot,                               std::string const &driverFile)        : impl_(new Impl),          logger_(osvr::util::log::make_logger("DriverLoader")) {        /// Set the PATH to include the driver directory so it can        /// find its deps.        SearchPathExtender extender(driverRoot);  f defined(OSVR_WINDOWS)        impl_->driver_ = LoadLibraryA(driverFile.c_str());<strong><span style="font-size:14px;">// 加载steam目录下的driver_lighthouse.dll文件</span></strong>        if (!impl_->driver_) {            reset();            throw CouldNotLoadDriverModule();        }          auto proc = GetProcAddress(impl_->driver_, ENTRY_POINT_FUNCTION_NAME);<strong><span style="font-size:14px;">// 获取dll文件中的HmdDriverFactory接口地址</span></strong>        if (!proc) {            reset();            throw CouldNotLoadEntryPoint();        }        factory_ = reinterpret_cast<DriverFactory>(proc);<strong><span style="font-size:14px;">// 强制转换为void *(*)(const char *, int *)类型</span></strong>  lif defined(OSVR_LINUX) || defined(OSVR_MACOSX)        impl_->driver_ = dlopen(driverFile.c_str(), RTLD_NOW | RTLD_GLOBAL);        if (!impl_->driver_) {            reset();            throw CouldNotLoadDriverModule(dlerror());        }          auto proc = dlsym(impl_->driver_, ENTRY_POINT_FUNCTION_NAME);        if (!proc) {            reset();            throw CouldNotLoadEntryPoint(dlerror());        }        factory_ = reinterpret_cast<DriverFactory>(proc);  ndif    } 
static const auto ENTRY_POINT_FUNCTION_NAME = "HmdDriverFactory";

using DriverFactory = void *(*)(const char *, int *);
目的是存储一个地址到变量:factory_
在driver_lighthouse.dll中的vr::IServerTrackedDeviceProvider已提供接口如下:
CServerDriver g_ServerTrackedDeviceProvider;

HMD_DLL_EXPORT  void *HmdDriverFactory(const char *pInterfaceName, int *pReturnCode)  {      if (0 == strcmp(IServerTrackedDeviceProvider_Version, pInterfaceName)) {          return &g_ServerTrackedDeviceProvider;      }        if (pReturnCode) {          *pReturnCode = VRInitError_Init_InterfaceNotFound;      }        return NULL;  }  

回到ViveDriverHost::start中,checkServerDeviceProviderInterfaces检测驱动需要的接口openvr_driver.h是否支持。

enum class InterfaceVersionStatus {             /// All mentioned interface version strings are handled/described by             /// the header we've built against.             AllInterfacesOK,// 驱动请求使用的所有接口类 openvr_driver.h中都支持             /// Not all mentioned interface version strings are             /// handled/described by the header we've built against, but the             /// interfaces that we use match.             AllUsedInterfacesOK, // 不是所有请求的接口类openvr_driver.h中都支持,但是所使用到的类都支持。             /// At least one of the interfaces that we use doesn't match the             /// version we built against.             InterfaceMismatch //至少一个所使用到的接口类在openvr_driver.h中不支持         };           static const char * const k_InterfaceVersions[] =     {         IVRSettings_Version,         ITrackedDeviceServerDriver_Version,         IVRDisplayComponent_Version,         IVRDriverDirectModeComponent_Version,         IVRControllerComponent_Version,         IVRCameraComponent_Version,         IServerTrackedDeviceProvider_Version,         IVRWatchdogProvider_Version,         IVRVirtualDisplay_Version,         nullptr     };  

serverDevProvider().GetInterfaceVersions()返回的是以上openvr_driver.h中的接口类名,并比较是否所有接口类版本都支持。
若一个版本不支持,则将其入队,并将其与本驱动care的版本进行对比,若是必须要使用的但是又不被openvr_driver.h所支持。
则allUsedSupported=false.

/// A list of just the interface names we actually use.          static const auto interfaceNamesWeCareAbout = {              "ITrackedDeviceServerDriver", "IVRDisplayComponent",              "IVRControllerComponent", //< @todo do we actually use/cast to                                        // this interface?              "IServerTrackedDeviceProvider", "IVRWatchdogProvider"};  

关于数据传输部分:
在driver_lighthouse.dll中通过RunFrame()中的vr::VRServerDriverHost()->TrackedDevicePoseUpdated(m_unObjectId, GetPose(), sizeof(DriverPose_t));
往vive中的以下接口发:

void ViveDriverHost::TrackedDevicePoseUpdated(uint32_t unWhichDevice,                                                    const DriverPose_t &newPose,                                                    uint32_t unPoseStructSize) {          submitTrackingReport(unWhichDevice, osvr::util::time::getNow(),                               newPose);      }    void ViveDriverHost::submitTrackingReport(uint32_t unWhichDevice,                                                OSVR_TimeValue const &tv,                                                const DriverPose_t &newPose) {          TrackingReport out;          out.timestamp = tv;          out.sensor = unWhichDevice;          out.report = newPose;          {              std::lock_guard<std::mutex> lock(m_mutex);              m_trackingReports.submitNew(std::move(out), lock);          }      }  
因此,整个数据过程为:
通过DriverLoader.cpp加载dll后,再通过m_vive->startServerDeviceProvider()获取dll实现的
vr::IServerTrackedDeviceProvider接口, update中通过调用m_vive->serverDevProvider().RunFrame()结构,通过submitNew往deque_中push,vive osvr端通过grabItems到vector_。最后在update中再通过accessWorkItems获取

vector_。最终通过convertAndSendTracker中的osvrDeviceTrackerSendPoseTimestamped往应用程序传数据。其中chaperone
配置文件中的数据在handleUniverseChange中被处理。

2017-6-27------------------------------------------------------------------------


无论是在直连或者扩展模式上,HTC Vive和它的控制器被OSVR所支持且可以在任何OSVR应用程序上使用,还支持畸变校正,全方位追踪以及输入支持。

通过OSVR,OSVR-Vive插件及其工具访问Vive硬件。


兼容性:

然后改驱动应该兼容所有的Vive家族设备,到目前为止,它只在HTC Vive和Vive PRE(非早期开发版本)上测试过。

OSVR-Vive驱动与为Vive服务的SteamVR驱动交互(driver_lighthouse),因此与SteamVR版本也有关联。


安装流程:

首先确保Vive在SteamVR上工作正常且已经安排了一个房间,最好是进行一个站立状态或房间级别的校准作为游戏空间。然后,下载

与OSVR服务相对应位数的插件二进制包。

在下载的解压包内有以下文件:

1>.一个插件文件。在Windows上,这是一个在bin/osvr-plugins-0目录下的.dll文件。将它放在OSVR server相同目录下。

2>.在bin目录内,一个ViveDisplayExtractor工具---拷贝到OSVR server的bin目录下。

3>.一个起始样例配置文件osvr_server_config(还有一些可以快速替换的预设显示描述符以及网格文件)


首先应该在不需要改变任何SteamVR设置的基础上,能够以直连模式在Vive头显上运行一个OSVR的应用程序。如果Vive在SteamVR上以

直联模式工作正常,但是在OSVR上不能以直连模式打开,则原因可能是在OSVR应用程序启动之前SteamVR没有退出(需要确保在

OSVR应用程序启动之前SteamVR已经退出)。在一些系统上,退出SteamVR之前,在SteamVR菜单内可能需要禁止直连模式。


一次安装:Vive需要一个客户显示描述以及网格畸变数据文件,使用ViveDisplayExtractor工具提取这些文件数据。确保ViveDisplayExtractor与

osvr_server一起运行,也就是Vive与PC连接,SteamVR已经退出,运行ViveDisplayExtractor。


如果成功,将会看到类似以下:

[DisplayExtractor] Writing distortion mesh data file:
C:/Users/Ryan/Desktop/OSVR/bin/displays/HTC_Vive_PRE_meshdata.json

[DisplayExtractor] Writing display descriptor file:
C:/Users/Ryan/Desktop/OSVR/bin/displays/HTC_Vive_PRE.json

[DisplayExtractor] Press enter to quit...


Note:结果配置包含一个到网格数据的绝对路径,因此如果改变了osvr server所在目录,只需要再次运行ViveDisplayExtractor。

以上就是所有的了!现在可以使用样例osvr_server_config.vive.sample.json  文件作为服务配置文件了(将它改为默认名: osvr_server_config.json

),可以在Vive上运行OSVR启动的应用程序了。

如果想要运行SteamVR APP,没问题:只要关闭OSVR Server并且任何在直连模式运行的OSVR Apps即可。



原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 有头屑头痒掉头发怎么办 老是头痒掉头发怎么办 头屑头痒掉头发怎么办 头痒头屑多掉头发怎么办 洗头发时总是掉发怎么办 染头发染到脸上洗不掉怎么办 总爱掉头发怎么办20岁 头发开叉长的慢怎么办 洗头时掉很多头发怎么办 出门前头发很油怎么办 关于头发头顶头发少怎么办 每天掉100根头发怎么办 小孩嘴巴烂了该怎么办 小孩吃烧烤嘴巴肿好大该怎么办 脸特别瘦的人怎么办 怀孕宝宝太懒了怎么办 奶油胶手机壳脏了怎么办 为什么电脑桌面壁纸变成黑色怎么办 仓鼠妈妈老忘了宝宝怎么办 木工三排多轴钻床气缸坏了怎么办? 水溶笔洗不掉怎么办 针管笔没有墨了怎么办 二岁小儿不爱吃饭怎么办 狗狗一直挠痒痒怎么办 手被铅笔扎了怎么办 小孩智力轻度低下该怎么办 发侮辱人的信息怎么办 宋民国表情我能怎么办 苹果手机微信弄成听筒模式怎么办 我的小可爱丢了怎么办 法斗犬老是皮肤病看也看不好怎么办 项链水晶不亮了怎么办 美甲画画手抖怎么办 微信中的表情符号不全怎么办 球球大作战找不到团战服务器怎么办 小孩的腰有点弯怎么办 小朋友不听话被老师罚站怎么办 幼儿园小朋友被老师罚站怎么办 生完小孩弯腰驼背怎么办 小孩爱捡垃圾是怎么办 腰扭了不敢弯腰怎么办