OSVR Framework (Internal Development Docs)  0.6-1962-g59773924
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
diagnose-rotation.cpp
Go to the documentation of this file.
1 
12 // Copyright 2015 Sensics, Inc.
13 //
14 // Licensed under the Apache License, Version 2.0 (the "License");
15 // you may not use this file except in compliance with the License.
16 // You may obtain a copy of the License at
17 //
18 // http://www.apache.org/licenses/LICENSE-2.0
19 //
20 // Unless required by applicable law or agreed to in writing, software
21 // distributed under the License is distributed on an "AS IS" BASIS,
22 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 // See the License for the specific language governing permissions and
24 // limitations under the License.
25 
26 // Internal Includes
27 #include "ClientMainloopThread.h"
28 #include "RecomposeTransform.h"
29 #include "WrapRoute.h"
34 #include <osvr/Util/EigenInterop.h>
35 #include <osvr/Util/UniquePtr.h>
36 
37 // Library/third-party includes
38 #include <boost/program_options.hpp>
39 #include <boost/thread/thread.hpp>
40 #include <boost/date_time/posix_time/posix_time.hpp>
41 #include <json/value.h>
42 #include <json/reader.h>
43 
44 // Standard includes
45 #include <iostream>
46 #include <fstream>
47 #include <exception>
48 
49 using std::cout;
50 using std::cerr;
51 using std::endl;
52 
53 auto SETTLE_TIME = boost::posix_time::seconds(2);
54 
55 static const double minAbsRadians = 1.5;
56 static const int totalDots = 10;
57 
58 inline Eigen::Quaterniond
59 getOrientationState(osvr::clientkit::Interface &iface) {
61  OSVR_TimeValue timestamp;
62  OSVR_ReturnCode ret;
63  ret = osvrGetOrientationState(iface.get(), &timestamp, &state);
64  if (ret != OSVR_RETURN_SUCCESS) {
65  cerr << "Sorry, no orientation state available for this route - "
66  "are you sure you have a device plugged in and your "
67  "path correct?" << endl;
68  std::cin.ignore();
69  throw std::runtime_error("No orientation state available");
70  }
71  return osvr::util::fromQuat(state);
72 }
73 
74 Eigen::AngleAxisd getRotation(const char name[], ClientMainloopThread &client,
76  cout << "\n\n--- " << name << "---" << endl;
77  cout << "Current rotation: " << name << " - please see the image file for "
78  "desired axis and direction of "
79  "rotation." << endl;
80  cout << "Once you're ready, put your device in a level, forward-looking "
81  "orientation, then press enter." << endl;
82  std::cin.ignore();
83  Eigen::Quaterniond initial;
84  Eigen::Quaterniond current;
85  {
86  ClientMainloopThread::lock_type lock(client.getMutex());
87  initial = getOrientationState(iface);
88  cout << "Initial axes:" << endl;
89  cout << " - sensor X points "
90  << (initial * Eigen::Vector3d::UnitX()).transpose() << endl;
91  cout << " - sensor Y points "
92  << (initial * Eigen::Vector3d::UnitY()).transpose() << endl;
93  cout << " - sensor Z points "
94  << (initial * Eigen::Vector3d::UnitZ()).transpose() << endl;
95  cout << endl;
96  cout << "Now, please rotate the device as shown in the image. " << endl;
97  cout << "Keep rotating";
98  double absRads = 0;
99  int dots = 0;
100  do {
101  client.oneLoop();
102  current = getOrientationState(iface);
103  absRads = current.angularDistance(initial);
104  int currentDots = (absRads / minAbsRadians) * totalDots;
105  while (dots < currentDots) {
106  cout << ".";
107  dots++;
108  }
109  } while (absRads < minAbsRadians);
110  }
111  cout << " OK!" << endl;
112  auto relative = initial.conjugate() * current;
113  auto angleAxis = Eigen::AngleAxisd(relative);
114  cout << " - " << name << " - Rotated " << angleAxis.angle()
115  << " radians about " << angleAxis.axis().transpose() << "\n" << endl;
116  return angleAxis;
117 }
118 
119 int main(int argc, char *argv[]) {
120  namespace po = boost::program_options;
121  // clang-format off
122  po::options_description desc("Options");
123  desc.add_options()
124  ("help", "produce help message")
125  ("route", po::value<std::string>()->default_value("/me/head"), "route to diagnose")
126  ("reset", "temporarily remove all transforms before performing diagnosis")
127  ;
128  // clang-format on
129 
130  po::variables_map vm;
131  po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
132  po::notify(vm);
133 
135  if (vm.count("help")) {
136  cout << "Usage: diagnose-rotation [options]" << endl;
137  cout << desc << "\n";
138  return 1;
139  }
140 
141  osvr::clientkit::ClientContext ctx("com.osvr.bundled.diagnose-rotation");
142  std::string const dest = vm["route"].as<std::string>();
143 
144  bool resetTransform = (vm.count("reset") != 0);
145 
146  osvr::clientkit::Interface iface = ctx.getInterface(dest);
147  {
148 
149  ClientMainloopThread client(ctx);
150 
151  std::string origRouteString;
152  if (resetTransform) {
153  cout << "Running client mainloop briefly to get routes..." << endl;
154  client.loopForDuration(boost::chrono::seconds(2));
155 
156  cout << "Removing any existing transforms..." << endl;
157  Json::Value origRoute;
158  origRouteString =
159  ctx.get()->getRoutes().getRouteForDestination(dest);
160  Json::Reader reader;
161  if (!reader.parse(origRouteString, origRoute)) {
162  cerr << "Error parsing existing route!" << endl;
163  cerr << origRouteString << endl;
164  return -1;
165  }
166  Json::Value origTransforms =
167  origRoute[osvr::common::routing_keys::source()];
169  Json::Value cleanTransforms = remove_levels_if(
170  origTransforms, [](Json::Value const &) { return true; });
171  origRoute[osvr::common::routing_keys::source()] = cleanTransforms;
172  ctx.get()->sendRoute(origRoute.toStyledString());
173 
174  cout << "Sent cleaned route: " << origRoute.toStyledString()
175  << endl;
176  }
177  cout << "Running thread and waiting a few seconds "
178  "for startup..." << endl;
179  client.start();
180  boost::this_thread::sleep(SETTLE_TIME);
181 
182  auto pitch = getRotation("pitch", client, iface);
183  auto yaw = getRotation("yaw", client, iface);
184  auto roll = getRotation("roll", client, iface);
185 
186  cout << "Press enter to "
187  << (resetTransform ? "restore original transform and " : "")
188  << "exit.";
189  std::cin.ignore();
190  if (resetTransform) {
191  cout << "Restoring original transform/route" << endl;
192  ctx.get()->sendRoute(origRouteString);
193  }
194  boost::this_thread::sleep(SETTLE_TIME);
195  }
196  return 0;
197 }
Header.
Interface handle object. Typically acquired from a ClientContext.
Client context object: Create and keep one in your application. Handles lifetime management and provi...
Definition: Context_decl.h:57
void sendRoute(std::string const &route)
Sends a JSON route/transform object to the server.
Header to bring unique_ptr into the osvr namespace.
A structure defining a quaternion, often a unit quaternion representing 3D rotation.
Definition: QuaternionC.h:49
Json::Value remove_levels_if(Json::Value input, Predicate p)
Goes through your transform, starting at the outermost layer, and keeping and re-composing only the l...
Interface getInterface(const std::string &path)
Get the interface associated with the given path.
Definition: Context.h:61
OSVR_ClientInterface get()
Get the raw OSVR_ClientInterface from this wrapper.
Definition: Interface.h:55
Header.
#define OSVR_RETURN_SUCCESS
The "success" value for an OSVR_ReturnCode.
Definition: ReturnCodesC.h:45
OSVR_ClientContext get()
Gets the bare OSVR_ClientContext.
Definition: Context.h:109
Eigen::Quaterniond fromQuat(OSVR_Quaternion const &q)
Convert an OSVR_Quaternion to an Eigen::Quaterniond.
Definition: EigenInterop.h:63
Header for interoperation between the Eigen math library, the internal mini math library, and VRPN's quatlib.
int main(int argc, char *argv[])
OSVR_ReturnCode osvrGetOrientationState(OSVR_ClientInterface iface, struct OSVR_TimeValue *timestamp, OSVR_OrientationState *state)
Get Orientation state from an interface, returning failure if none \ * exists.
Standardized, portable parallel to struct timeval for representing both absolute times and time inter...
Definition: TimeValueC.h:81