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>
53 auto SETTLE_TIME = boost::posix_time::seconds(2);
55 static const double minAbsRadians = 1.5;
56 static const int totalDots = 10;
58 inline Eigen::Quaterniond
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;
69 throw std::runtime_error(
"No orientation state available");
76 cout <<
"\n\n--- " << name <<
"---" << endl;
77 cout <<
"Current rotation: " << name <<
" - please see the image file for "
78 "desired axis and direction of "
80 cout <<
"Once you're ready, put your device in a level, forward-looking "
81 "orientation, then press enter." << endl;
83 Eigen::Quaterniond initial;
84 Eigen::Quaterniond current;
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;
96 cout <<
"Now, please rotate the device as shown in the image. " << endl;
97 cout <<
"Keep rotating";
102 current = getOrientationState(iface);
103 absRads = current.angularDistance(initial);
104 int currentDots = (absRads / minAbsRadians) * totalDots;
105 while (dots < currentDots) {
109 }
while (absRads < minAbsRadians);
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;
119 int main(
int argc,
char *argv[]) {
120 namespace po = boost::program_options;
122 po::options_description desc(
"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")
130 po::variables_map vm;
131 po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);
135 if (vm.count(
"help")) {
136 cout <<
"Usage: diagnose-rotation [options]" << endl;
137 cout << desc <<
"\n";
142 std::string
const dest = vm[
"route"].as<std::string>();
144 bool resetTransform = (vm.count(
"reset") != 0);
151 std::string origRouteString;
152 if (resetTransform) {
153 cout <<
"Running client mainloop briefly to get routes..." << endl;
154 client.loopForDuration(boost::chrono::seconds(2));
156 cout <<
"Removing any existing transforms..." << endl;
157 Json::Value origRoute;
159 ctx.
get()->getRoutes().getRouteForDestination(dest);
161 if (!reader.parse(origRouteString, origRoute)) {
162 cerr <<
"Error parsing existing route!" << endl;
163 cerr << origRouteString << endl;
166 Json::Value origTransforms =
167 origRoute[osvr::common::routing_keys::source()];
170 origTransforms, [](Json::Value
const &) {
return true; });
171 origRoute[osvr::common::routing_keys::source()] = cleanTransforms;
174 cout <<
"Sent cleaned route: " << origRoute.toStyledString()
177 cout <<
"Running thread and waiting a few seconds "
178 "for startup..." << endl;
180 boost::this_thread::sleep(SETTLE_TIME);
182 auto pitch = getRotation(
"pitch", client, iface);
183 auto yaw = getRotation(
"yaw", client, iface);
184 auto roll = getRotation(
"roll", client, iface);
186 cout <<
"Press enter to "
187 << (resetTransform ?
"restore original transform and " :
"")
190 if (resetTransform) {
191 cout <<
"Restoring original transform/route" << endl;
194 boost::this_thread::sleep(SETTLE_TIME);
Interface handle object. Typically acquired from a ClientContext.
Client context object: Create and keep one in your application. Handles lifetime management and provi...
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.
Interface getInterface(const std::string &path)
Get the interface associated with the given path.
OSVR_ClientInterface get()
Get the raw OSVR_ClientInterface from this wrapper.
#define OSVR_RETURN_SUCCESS
The "success" value for an OSVR_ReturnCode.
OSVR_ClientContext get()
Gets the bare OSVR_ClientContext.
Eigen::Quaterniond fromQuat(OSVR_Quaternion const &q)
Convert an OSVR_Quaternion to an Eigen::Quaterniond.
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...