Bike-X  0.8
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Util_LatencyTest.cpp
Go to the documentation of this file.
1 /************************************************************************************
2 
3 Filename : Util_LatencyTest.cpp
4 Content : Wraps the lower level LatencyTester interface and adds functionality.
5 Created : February 14, 2013
6 Authors : Lee Cooper
7 
8 Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
9 
10 Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License");
11 you may not use the Oculus VR Rift SDK except in compliance with the License,
12 which is provided at the time of installation or download, or which
13 otherwise accompanies this software in either electronic or hard copy form.
14 
15 You may obtain a copy of the License at
16 
17 http://www.oculusvr.com/licenses/LICENSE-3.1
18 
19 Unless required by applicable law or agreed to in writing, the Oculus VR SDK
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24 
25 *************************************************************************************/
26 
27 #include "Util_LatencyTest.h"
28 
29 #include "../Kernel/OVR_Log.h"
30 #include "../Kernel/OVR_Timer.h"
31 
32 namespace OVR { namespace Util {
33 
38 static const UInt32 DEFAULT_NUMBER_OF_SAMPLES = 10; // For both color 1->2 and color 2->1 transitions.
42 static const Color CALIBRATE_BLACK(0, 0, 0);
43 static const Color CALIBRATE_WHITE(255, 255, 255);
44 static const Color COLOR1(0, 0, 0);
45 static const Color COLOR2(255, 255, 255);
46 static const Color SENSOR_DETECT_THRESHOLD(128, 255, 255);
47 static const float BIG_FLOAT = 1000000.0f;
48 static const float SMALL_FLOAT = -1000000.0f;
49 
50 //-------------------------------------------------------------------------------------
51 // ***** LatencyTest
52 
54  : Handler(getThis())
55 {
56  if (device != NULL)
57  {
58  SetDevice(device);
59  }
60 
61  reset();
62 
63  srand(Timer::GetTicksMs());
64 }
65 
67 {
69 }
70 
72 {
73 
74  if (device != Device)
75  {
77 
78  Device = device;
79 
80  if (Device != NULL)
81  {
82  Device->AddMessageHandler(&Handler);
83 
84  // Set trigger threshold.
85  LatencyTestConfiguration configuration(SENSOR_DETECT_THRESHOLD, false); // No samples streaming.
86  Device->SetConfiguration(configuration, true);
87 
88  // Set display to initial (3 dashes).
89  LatencyTestDisplay ltd(2, 0x40400040);
90  Device->SetDisplay(ltd);
91  }
92  }
93 
94  return true;
95 }
96 
98 {
99  UInt32 val = rand() % range;
100  return val;
101 }
102 
104 {
106  {
107  // Set color to black and wait a while.
109 
111  OVR_DEBUG_LOG(("State_WaitingForButton -> State_WaitingForSettlePreCalibrationColorBlack."));
112 
114  }
115 }
116 
117 void LatencyTest::handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage)
118 {
119  // For debugging.
120 /* if (msg.Type == Message_LatencyTestSamples)
121  {
122  MessageLatencyTestSamples* pSamples = (MessageLatencyTestSamples*) &msg;
123 
124  if (pSamples->Samples.GetSize() > 0)
125  {
126  // Just show the first one for now.
127  Color c = pSamples->Samples[0];
128  OVR_DEBUG_LOG(("%d %d %d", c.R, c.G, c.B));
129  }
130  return;
131  }
132 */
133 
134  if (latencyTestMessage == LatencyTest_Timer)
135  {
136  if (!Device)
137  {
138  reset();
139  return;
140  }
141 
143  {
144  // Send calibrate message to device and wait a while.
145  Device->SetCalibrate(CALIBRATE_BLACK);
146 
148  OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorBlack -> State_WaitingForSettlePostCalibrationColorBlack."));
149 
151  }
153  {
154  // Change color to white and wait a while.
156 
158  OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorBlack -> State_WaitingForSettlePreCalibrationColorWhite."));
159 
161  }
163  {
164  // Send calibrate message to device and wait a while.
165  Device->SetCalibrate(CALIBRATE_WHITE);
166 
168  OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorWhite -> State_WaitingForSettlePostCalibrationColorWhite."));
169 
171  }
173  {
174  // Calibration is done. Switch to color 1 and wait for it to settle.
176 
178  OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorWhite -> State_WaitingForSettlePostMeasurement."));
179 
181  setTimer(waitTime);
182  }
184  {
185  // Prepare for next measurement.
186 
187  // Create a new result object.
188  MeasurementResult* pResult = new MeasurementResult();
189  Results.PushBack(pResult);
190 
192  OVR_DEBUG_LOG(("State_WaitingForSettlePostMeasurement -> State_WaitingToTakeMeasurement."));
193  }
195  {
196  // We timed out waiting for 'TestStarted'. Abandon this measurement and setup for the next.
198 
200  OVR_DEBUG_LOG(("** Timed out waiting for 'TestStarted'."));
201  OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForSettlePostMeasurement."));
202 
204  setTimer(waitTime);
205  }
207  {
208  // We timed out waiting for 'ColorDetected'. Abandon this measurement and setup for the next.
210 
212  OVR_DEBUG_LOG(("** Timed out waiting for 'ColorDetected'."));
213  OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement."));
214 
216  setTimer(waitTime);
217  }
218  }
219  else if (latencyTestMessage == LatencyTest_ProcessInputs)
220  {
222  {
223  if (!Device)
224  {
225  reset();
226  return;
227  }
228 
229  // Send 'StartTest' feature report with opposite target color.
230  if (RenderColor == COLOR1)
231  {
233  }
234  else
235  {
237  }
238 
240 
241  // Record time so we can determine usb roundtrip time.
243 
244  Device->SetStartTest(RenderColor);
245 
247  OVR_DEBUG_LOG(("State_WaitingToTakeMeasurement -> State_WaitingForTestStarted."));
248 
250 
251  LatencyTestDisplay ltd(2, 0x40090040);
252  Device->SetDisplay(ltd);
253  }
254  }
255  else if (msg.Type == Message_LatencyTestButton)
256  {
257  BeginTest();
258  }
259  else if (msg.Type == Message_LatencyTestStarted)
260  {
262  {
263  clearTimer();
264 
265  // Record time so we can determine usb roundtrip time.
267 
269  OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForColorDetected."));
270 
272  }
273  }
274  else if (msg.Type == Message_LatencyTestColorDetected)
275  {
277  {
278  // Record time to detect color.
280  UInt16 elapsedTime = pDetected->Elapsed;
281  OVR_DEBUG_LOG(("Time to 'ColorDetected' = %d", elapsedTime));
282 
284 
285  if (areResultsComplete())
286  {
287  // We're done.
288  processResults();
289  reset();
290  }
291  else
292  {
293  // Run another measurement.
295  OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement."));
296 
298  setTimer(waitTime);
299 
300  LatencyTestDisplay ltd(2, 0x40400040);
301  Device->SetDisplay(ltd);
302  }
303  }
304  }
305  else if (msg.Type == Message_DeviceRemoved)
306  {
307  reset();
308  }
309 }
310 
312 {
313  OVR_ASSERT(!Results.IsEmpty());
314  return Results.GetLast();
315 }
316 
318 {
319  ActiveTimerMilliS = timeMilliS;
320 }
321 
323 {
324  ActiveTimerMilliS = 0;
325 }
326 
328 {
331 
332  HaveOldTime = false;
333  ActiveTimerMilliS = 0;
334 }
335 
337 {
338  while(!Results.IsEmpty())
339  {
340  MeasurementResult* pElem = Results.GetFirst();
341  pElem->RemoveNode();
342  delete pElem;
343  }
344 }
345 
347 {
349 }
350 
352 {
353  pLatencyTestUtil->handleMessage(msg);
354 }
355 
357 {
360 }
361 
363 {
365 
367  {
368  return false;
369  }
370 
371  colorToDisplay = RenderColor;
372  return true;
373 }
374 
376 {
378  {
380  return ReturnedResultString.ToCStr();
381  }
382 
383  return NULL;
384 }
385 
387 {
388  UInt32 initialMeasurements = 0;
389 
390  UInt32 measurements1to2 = 0;
391  UInt32 measurements2to1 = 0;
392 
393  MeasurementResult* pCurr = Results.GetFirst();
394  while(true)
395  {
396  // Process.
397  if (!pCurr->TimedOutWaitingForTestStarted &&
399  {
400  initialMeasurements++;
401 
402  if (initialMeasurements > INITIAL_SAMPLES_TO_IGNORE)
403  {
404  if (pCurr->TargetColor == COLOR2)
405  {
406  measurements1to2++;
407  }
408  else
409  {
410  measurements2to1++;
411  }
412  }
413  }
414 
415  if (Results.IsLast(pCurr))
416  {
417  break;
418  }
419  pCurr = Results.GetNext(pCurr);
420  }
421 
422  if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES &&
423  measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES)
424  {
425  return true;
426  }
427 
428  return false;
429 }
430 
432 {
433 
434  UInt32 minTime1To2 = UINT_MAX;
435  UInt32 maxTime1To2 = 0;
436  float averageTime1To2 = 0.0f;
437  UInt32 minTime2To1 = UINT_MAX;
438  UInt32 maxTime2To1 = 0;
439  float averageTime2To1 = 0.0f;
440 
441  float minUSBTripMilliS = BIG_FLOAT;
442  float maxUSBTripMilliS = SMALL_FLOAT;
443  float averageUSBTripMilliS = 0.0f;
444  UInt32 countUSBTripTime = 0;
445 
446  UInt32 measurementsCount = 0;
447  UInt32 measurements1to2 = 0;
448  UInt32 measurements2to1 = 0;
449 
450  MeasurementResult* pCurr = Results.GetFirst();
451  UInt32 count = 0;
452  while(true)
453  {
454  count++;
455 
456  if (!pCurr->TimedOutWaitingForTestStarted &&
458  {
459  measurementsCount++;
460 
461  if (measurementsCount > INITIAL_SAMPLES_TO_IGNORE)
462  {
463  if (pCurr->TargetColor == COLOR2)
464  {
465  measurements1to2++;
466 
467  if (measurements1to2 <= DEFAULT_NUMBER_OF_SAMPLES)
468  {
469  UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS;
470 
471  minTime1To2 = Alg::Min(elapsed, minTime1To2);
472  maxTime1To2 = Alg::Max(elapsed, maxTime1To2);
473 
474  averageTime1To2 += (float) elapsed;
475  }
476  }
477  else
478  {
479  measurements2to1++;
480 
481  if (measurements2to1 <= DEFAULT_NUMBER_OF_SAMPLES)
482  {
483  UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS;
484 
485  minTime2To1 = Alg::Min(elapsed, minTime2To1);
486  maxTime2To1 = Alg::Max(elapsed, maxTime2To1);
487 
488  averageTime2To1 += (float) elapsed;
489  }
490  }
491 
492  float usbRountripElapsedMilliS = Timer::MsPerSecond * (float) (pCurr->TestStartedSeconds - pCurr->StartTestSeconds);
493  minUSBTripMilliS = Alg::Min(usbRountripElapsedMilliS, minUSBTripMilliS);
494  maxUSBTripMilliS = Alg::Max(usbRountripElapsedMilliS, maxUSBTripMilliS);
495  averageUSBTripMilliS += usbRountripElapsedMilliS;
496  countUSBTripTime++;
497  }
498  }
499 
500  if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES &&
501  measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES)
502  {
503  break;
504  }
505 
506  if (Results.IsLast(pCurr))
507  {
508  break;
509  }
510  pCurr = Results.GetNext(pCurr);
511  }
512 
513  averageTime1To2 /= (float) DEFAULT_NUMBER_OF_SAMPLES;
514  averageTime2To1 /= (float) DEFAULT_NUMBER_OF_SAMPLES;
515 
516  averageUSBTripMilliS /= countUSBTripTime;
517 
518  float finalResult = 0.5f * (averageTime1To2 + averageTime2To1);
519  finalResult += averageUSBTripMilliS;
520 
522  ResultsString.AppendFormat("RESULT=%.1f (add half Tracker period) [b->w %d|%.1f|%d] [w->b %d|%.1f|%d] [usb rndtrp %.1f|%.1f|%.1f] [cnt %d] [tmouts %d]",
523  finalResult,
524  minTime1To2, averageTime1To2, maxTime1To2,
525  minTime2To1, averageTime2To1, maxTime2To1,
526  minUSBTripMilliS, averageUSBTripMilliS, maxUSBTripMilliS,
527  DEFAULT_NUMBER_OF_SAMPLES*2, count - measurementsCount);
528 
529  // Display result on latency tester display.
530  LatencyTestDisplay ltd(1, (int)finalResult);
531  Device->SetDisplay(ltd);
532 }
533 
535 {
536  if (!HaveOldTime)
537  {
538  HaveOldTime = true;
540  return;
541  }
542 
543  UInt32 newTime = Timer::GetTicksMs();
544  UInt32 elapsedMilliS = newTime - OldTime;
545  if (newTime < OldTime)
546  {
547  elapsedMilliS = OldTime - newTime;
548  elapsedMilliS = UINT_MAX - elapsedMilliS;
549  }
550  OldTime = newTime;
551 
552  elapsedMilliS = Alg::Min(elapsedMilliS, (UInt32) 100); // Clamp at 100mS in case we're not being called very often.
553 
554 
555  if (ActiveTimerMilliS == 0)
556  {
557  return;
558  }
559 
560  if (elapsedMilliS >= ActiveTimerMilliS)
561  {
562  ActiveTimerMilliS = 0;
564  return;
565  }
566 
567  ActiveTimerMilliS -= elapsedMilliS;
568 }
569 
570 }} // namespace OVR::Util
LatencyTestHandler Handler
static const float BIG_FLOAT
static const Color SENSOR_DETECT_THRESHOLD(128, 255, 255)
static const UInt32 TIMEOUT_WAITING_FOR_TEST_STARTED
MeasurementResult * getActiveResult()
const char * GetResultsString()
OVR_FORCE_INLINE const T Max(const T a, const T b)
Definition: OVR_Alg.h:49
static const UInt32 DEFAULT_NUMBER_OF_SAMPLES
void setTimer(UInt32 timeMilliS)
#define NULL
bool DisplayScreenColor(Color &colorToDisplay)
uint16_t UInt16
Definition: OVR_Types.h:251
void handleMessage(const Message &msg, LatencyTestMessageType latencyTestMessage=LatencyTest_None)
static const Color CALIBRATE_BLACK(0, 0, 0)
uint32_t UInt32
Definition: OVR_Types.h:253
const char * ToCStr() const
Definition: OVR_String.h:437
static const Color COLOR1(0, 0, 0)
static const UInt32 TIMEOUT_WAITING_FOR_COLOR_DETECTED
Definition: Device.h:9
static const UInt32 INITIAL_SAMPLES_TO_IGNORE
static UInt32 OVR_STDCALL GetTicksMs()
Definition: OVR_Timer.h:64
MessageType Type
static const UInt32 TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION
const char * ToCStr() const
Definition: OVR_String.h:186
static const Color CALIBRATE_WHITE(255, 255, 255)
void RemoveNode()
Definition: OVR_List.h:58
static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS
#define OVR_ASSERT(p)
List< MeasurementResult > Results
static const float SMALL_FLOAT
LatencyTest(LatencyTestDevice *device=NULL)
static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT
bool SetDevice(LatencyTestDevice *device)
void AppendFormat(const char *format,...)
static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION
OVR_FORCE_INLINE const T Min(const T a, const T b)
Definition: OVR_Alg.h:46
static double OVR_STDCALL GetSeconds()
Definition: OVR_Timer.cpp:51
bool IsEmpty() const
Definition: OVR_String.h:442
virtual void OnMessage(const Message &msg)
#define OVR_DEBUG_LOG(args)
Definition: OVR_Log.h:196
static const Color COLOR2(255, 255, 255)
UInt32 getRandomComponent(UInt32 range)