Hermes SDK Documentation
Introduction

Welcome to the documentation for the Manus Core C++ SDK! We've designed it to allow you to get data off the Manus Gloves as quickly and easily as possible.

A few things to note:

  • This documentation is geared specifically towards the C++ SDK - other documentation can be found here: Unity Core Plugin, Unity Polygon Plugin and Unreal Plugin.
  • Our company is called Manus. Our software is called Manus Core. "Manus Core" used to be called Hermes, and our C++ SDK still uses the old name "Hermes" in most places.
  • When in doubt, reference the test implementations. This should be enough to get you through most problems.
  • This documentation is, as with all software projects, a work in progress. If you have questions or problems to report, please e-mail us at suppo.nosp@m.rt@m.nosp@m.anus-.nosp@m.vr.c.nosp@m.om.

Good luck!

Generate Solution files

  • Run any of these to generate a solution file for your version of Microsoft Visual Studio:
    • SDK\cpp\Generate_vs2017.bat
    • SDK\cpp\Generate_vs2019.bat

Solution layout

Open the solution file SDK\cpp\Generated\Solution\HermesSDK.sln with Visual Studio. In the Solution Explorer, there are 4 projects:

  • For static linking (against a .lib):
    • Project "HermesSDK" with header file HermesSDK.h.
      • Contains sources to build the static library.
      • This version has the most features.
    • Project "HermesClient" contains an example implementation for static linking.
  • For dynamic linking (against a .dll):
    • Project "CoreSdkWrapper" with header file CoreSdkWrapper.h.
      • Is a wrapper for dynamic linking against the static "HermesSDK" library.
      • This version has no dependency on "protobuf".
      • This version can also be used in clients written in plain "C".
      • We use this version for our Unreal and Motion Builder plugins.
    • Project "WrapperClient" contains an example implementation for dynamic linking.

Documentation for the HermesSDK and CoreSdkWrapper are separated into "Modules" on the Modules page. Because the CoreSdkWrapper interface is plain "C", the interface does not contain classes, so the Classes page only shows classes for the HermesSDK interface.

Folder layout

In your windows file explorer, there are at least 3 folders:

  • SDK
    • docs
      • index.html: this documentation.
    • protodefinitions
      • The definitions for "protobuf", the protocol we use to communicate to Manus Core, human-readable and for your reference.
    • core
      • Contains "HermesSDK" source files for static linking.
    • cpp
      • Generated
        • Output: The build output folder.
        • Solution: The Visual studio solution files.
      • protodefinitions: the headers that are generated from the "protobuf" definitions, not easy to read.
      • cpp
        • test.cpp: the sample implementation for static linking.
      • wrapper
        • The source files for the "CoreSdkWrapper" and "WrapperClient" for dynamic linking.

The Files page gives an overview where the most important headers are located.

Building

In your version of Visual Studio, click Build > Build Solution.

Running

  • Start ManusCore_Console.exe (because it shows debug output) or ManusCore.exe (the tray application without debug output). Default it is located in C:\Program Files\ManusVRPrime\ManusCore.
  • Open Manus Dashboard in ManusCore\Manus_Dashboard\Manus_Dashboard.exe
  • Connect your dongle, turn on your gloves, make sure they show up in the Manus Dashboard and everything looks ok.

Run one of the console window testclients:

  • HermesClient.exe that shows static linking (cpp\Generated\Output<Buildconfig>\x64\HermesClient.exe).
    • A console window should show glove data, and the "landscape" of dongles, gloves, trackers and users in a console window.
    • Press [tab] to cycle through printing joint angles as normalized values, degrees or quaternions.
    • If you have a haptics glove, press numeric keys [0]-[9] to rumble individual fingers.
  • WrapperClient.exe that shows dynamic linking (cpp\Generated\Output<Buildconfig>\x64\WrapperClient.exe).
    • Select if you want to connect locally [L] or connect to another host on the network [H].
    • A console window should show glove data of the left and right glove.

You can also debug the testclients in Visual Studio:

  • In the Solution Explorer, right-click on the "HermesClient" or "WrapperClient" project, and select "Set as StartUp project".
  • In the menu, go to Debug > Start Debugging (F5).

Integration in your application

  • For static linking in your own application, as in the HermesClient project, make sure you:
    • Add the following include directories:
      • cpp\Externals\protobuf-3.11.2\src
      • core
    • Include header file core\HermesSDK.h
    • Link against cpp\Generated\Output<Buildconfig>\x64\HermesSDK.lib
  • For dynamic linking in your own application, as in the WrapperClient project, make sure you:
    • Add the following include directories:
      • cpp\wrapper
    • Include header file cpp\wrapper\CoreSdkWrapper.h
    • Link against cpp\Generated\Output<Buildconfig>\x64\CoreSdkWrapper.dll

How it works

To pass data around, we use Google Protocol Buffers. This has a number of implications for your understanding of what's going on here:

  • We've provided you with (for the most part) the very same protocol definition files that we use internally. This makes perfect sense, because they govern how the messages that get passed between ManusCore and you, are structured. When you use the HermesSDK static linking, nearly every bit of communication you have with ManusCore is going to involve protocol definitions in some capacity. They take a moment of getting used to, but once you're comfortable you'll appreciate having such a clearly defined message schema.
  • When in doubt, reference our example to see how to construct/deconstruct messages. You could try to look straight at the generated protocol files as well, but that's not nearly as fun. There's a bit of nuance to it, so don't be surprised if you get an error the first or second time.

ManusCore communicates with you through a connection CareTaker, which is in charge of session maintenance and delivery/sending of data.

ManusCore (the host) and its clients find each other through the Hive, which is designed to facilitate easy connection without having to worry about port setup. There were days when you would get errors because the port that you were trying to use was also being used by another program - no longer!

There's a lot going on under the hood to get all your precious glove data to you safely, but very little of it should demand your attention. The most important thing you need to concern yourself with is the setup of the connection to ManusCore. For that, point yourself to test.cpp, specifically the HermesSDK::ConnectLocal() function. A few important things happen here:

  1. We set up a Hive, and tell it to find a local Coordinator. This more or less tells the Hive to looks for instances of Manus Core (local to your PC) that are broadcasting their existence. When we do that we pass some callback functions to be executed when these instances are found or removed. The important one here in onLocalNodeFound() - we'll come back to it in two steps!
  2. We also set up a connection CareTaker, and we pass it callback functions as well. These are all important, but probably the one you'll end up doing the most work on is onDeviceData(). This gets called every time new data comes in from the gloves (in protobuf format!) and you can use it to do whatever you want with that data.
  3. If you look at onLocalNodeFound(), you can see that at the very end we tell the CareTaker to connect to the found Coordinator. That officially sets up our session with Manus Core, after which point we begin receiving glove data.

That's it, for the most part! As you get started, feel free to crib callback functions and such straight from the test, and then replace them bit by bit to customize them to your use case.

Support

If you have questions please get in touch with us at suppo.nosp@m.rt@m.nosp@m.anus-.nosp@m.vr.c.nosp@m.om.