Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Tracker: New capture performance test tool

  • Loading branch information...
commit a75a1c26f0cbdcc43c990b41798a27506f8fdd68 1 parent bde8a6a
@thp authored
View
6 CMakeLists.txt
@@ -346,8 +346,10 @@ if(PSMOVE_BUILD_TESTS)
endforeach(TESTNAME)
if(PSMOVE_BUILD_TRACKER)
- add_executable(test_tracker examples/c/test_tracker.c)
- target_link_libraries(test_tracker psmoveapi psmoveapi_tracker)
+ foreach(TESTNAME tracker capture_performance)
+ add_executable(test_${TESTNAME} examples/c/test_${TESTNAME}.c)
+ target_link_libraries(test_${TESTNAME} psmoveapi psmoveapi_tracker)
+ endforeach(TESTNAME)
if (PSMOVE_BUILD_OPENGL_EXAMPLES)
foreach(EXAMPLE test_opengl test_opengl2 test_opengl3)
View
160 examples/c/test_capture_performance.c
@@ -0,0 +1,160 @@
+
+ /**
+ * PS Move API - An interface for the PS Move Motion Controller
+ * Copyright (c) 2012 Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **/
+
+
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "psmove.h"
+#include "psmove_tracker.h"
+
+/* This performance test application uses private APIs */
+#include "../../src/psmove_private.h"
+#include "../../src/tracker/psmove_tracker_private.h"
+
+/* OpenCV used for saving screenshots */
+#include "opencv2/core/core_c.h"
+#include "opencv2/highgui/highgui_c.h"
+
+struct TestContext {
+ int count;
+ PSMoveTracker *tracker;
+ PSMove **moves;
+
+ /* Capture timestamps */
+ PSMove_timestamp capture_begin;
+ PSMove_timestamp capture_grab;
+ PSMove_timestamp capture_retrieve;
+ PSMove_timestamp capture_converted;
+};
+
+void
+setup(struct TestContext *context)
+{
+ int i;
+
+ context->count = psmove_count_connected();
+ context->tracker = psmove_tracker_new();
+ psmove_tracker_set_mirror(context->tracker, PSMove_True);
+ context->moves = calloc(context->count, sizeof(PSMove *));
+
+ for (i=0; i<context->count; i++) {
+ context->moves[i] = psmove_connect_by_id(i);
+ assert(context->moves[i]);
+ while (psmove_tracker_enable(context->tracker,
+ context->moves[i]) != Tracker_CALIBRATED);
+ }
+}
+
+void
+teardown(struct TestContext *context)
+{
+ int i;
+
+ for (i=0; i<context->count; i++) {
+ psmove_tracker_disable(context->tracker,
+ context->moves[i]);
+ psmove_disconnect(context->moves[i]);
+ }
+
+ free(context->moves);
+ psmove_tracker_free(context->tracker);
+}
+
+#define ITERATIONS 500
+
+void
+save(int i, struct TestContext *context)
+{
+ void *frame = psmove_tracker_get_frame(context->tracker);
+ char path[512];
+ snprintf(path, sizeof(path), "capture_perf_%03d.jpg", i);
+ int imgParams[] = { CV_IMWRITE_JPEG_QUALITY, 90, 0 };
+ cvSaveImage(path, frame, imgParams);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct TestContext context;
+
+ setup(&context);
+
+ printf("\n -- PS Move API Camera Performance Test -- \n");
+
+ printf("\nTesting frame grab performance\n");
+ FILE *fp = fopen("capture_grab.csv", "w");
+ assert(fp != NULL);
+ fprintf(fp, "frame,grab,retrieve,converted");
+ int j;
+ for (j=0; j<context.count; j++) {
+ fprintf(fp, ",tracking%d", j);
+ }
+ fprintf(fp, "\n");
+ int i;
+ for (i=0; i<ITERATIONS; i++) {
+ psmove_tracker_update_image(context.tracker);
+ _psmove_tracker_retrieve_stats(context.tracker,
+ &(context.capture_begin),
+ &(context.capture_grab),
+ &(context.capture_retrieve),
+ &(context.capture_converted));
+
+ psmove_tracker_annotate(context.tracker);
+ save(i, &context);
+
+ float grab = _psmove_timestamp_value(_psmove_timestamp_diff(context.capture_grab, context.capture_begin));
+ float retrieve = _psmove_timestamp_value(_psmove_timestamp_diff(context.capture_retrieve, context.capture_grab));
+ float converted = _psmove_timestamp_value(_psmove_timestamp_diff(context.capture_converted, context.capture_retrieve));
+ fprintf(fp, "%d,%.10f,%.10f,%.10f", i, grab, retrieve, converted);
+
+ for (j=0; j<context.count; j++) {
+ PSMove_timestamp track_begin = _psmove_timestamp();
+ psmove_tracker_update(context.tracker, context.moves[j]);
+ PSMove_timestamp track_end = _psmove_timestamp();
+ float tracking = _psmove_timestamp_value(_psmove_timestamp_diff(track_end, track_begin));
+ fprintf(fp, ",%.10f", tracking);
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+
+ //printf("\nTesting SMART READ performance (rate-limited LED setting)\n");
+ //printf("\nTesting BAD READ performance (continous LED setting)\n");
+ //printf("\nTesting RAW READ performance (no LED setting)\n");
+
+ printf("\n");
+
+ teardown(&context);
+ return 0;
+}
+
View
1  examples/c/test_tracker.c
@@ -125,6 +125,7 @@ int main(int arg, char** args) {
while ((cvWaitKey(1) & 0xFF) != 27) {
psmove_tracker_update_image(tracker);
psmove_tracker_update(tracker, NULL);
+ psmove_tracker_annotate(tracker);
frame = psmove_tracker_get_frame(tracker);
if (frame) {
View
12 include/psmove_tracker.h
@@ -252,6 +252,18 @@ ADDAPI int
ADDCALL psmove_tracker_update(PSMoveTracker *tracker, PSMove *move);
/**
+ * This draws tracking statistics into the current camera image.
+ *
+ * This function has to be called after psmove_tracker_update(), and will
+ * annotate the camera image with sphere positions and other information.
+ *
+ * tracker - the Tracker to use
+ */
+ADDAPI void
+ADDCALL psmove_tracker_annotate(PSMoveTracker* tracker);
+
+
+/**
* Retrieves the most recently processed image by psmove_tracker_update
*
* tracker - A valid PSMoveTracker * instance
View
28 src/psmove.c
@@ -1769,3 +1769,31 @@ _psmove_normalize_btaddr(const char *addr, int lowercase, char separator)
return result;
}
+PSMove_timestamp
+_psmove_timestamp()
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts;
+}
+
+PSMove_timestamp
+_psmove_timestamp_diff(PSMove_timestamp a, PSMove_timestamp b)
+{
+ struct timespec ts;
+ if (a.tv_nsec >= b.tv_nsec) {
+ ts.tv_sec = a.tv_sec - b.tv_sec;
+ ts.tv_nsec = a.tv_nsec - b.tv_nsec;
+ } else {
+ ts.tv_sec = a.tv_sec - b.tv_sec - 1;
+ ts.tv_nsec = 1000000000 + a.tv_nsec - b.tv_nsec;
+ }
+ return ts;
+}
+
+double
+_psmove_timestamp_value(PSMove_timestamp ts)
+{
+ return ts.tv_sec + ts.tv_nsec * 0.000000001;
+}
+
View
12 src/psmove_private.h
@@ -38,6 +38,7 @@ extern "C" {
#include <stdio.h>
#include <wchar.h>
+#include <time.h>
/**
* PRIVATE DEFINITIONS FOR USE IN psmove.c AND psmove_*.c
@@ -186,6 +187,17 @@ ADDAPI int
ADDCALL _psmove_read_btaddrs(PSMove *move, PSMove_Data_BTAddr *host, PSMove_Data_BTAddr *controller);
+/* Performance measurement structures and functions */
+typedef struct timespec PSMove_timestamp;
+
+ADDAPI PSMove_timestamp
+ADDCALL _psmove_timestamp();
+
+ADDAPI PSMove_timestamp
+ADDCALL _psmove_timestamp_diff(PSMove_timestamp a, PSMove_timestamp b);
+
+ADDAPI double
+ADDCALL _psmove_timestamp_value(PSMove_timestamp ts);
#ifdef __cplusplus
View
16 src/tracker/camera_control.c
@@ -130,7 +130,7 @@ camera_control_read_calibration(CameraControl* cc,
if (intrinsic && distortion) {
if (!cc->frame3chUndistort) {
cc->frame3chUndistort = cvCloneImage(
- camera_control_query_frame(cc));
+ camera_control_query_frame(cc, NULL, NULL));
}
int width, height;
@@ -148,7 +148,8 @@ camera_control_read_calibration(CameraControl* cc,
}
IplImage *
-camera_control_query_frame(CameraControl* cc)
+camera_control_query_frame(CameraControl* cc,
+ PSMove_timestamp *ts_grab, PSMove_timestamp *ts_retrieve)
{
IplImage* result;
@@ -166,9 +167,14 @@ camera_control_query_frame(CameraControl* cc)
result = cc->frame3ch;
#else
- long start = psmove_util_get_ticks();
- result = cvQueryFrame(cc->capture);
- psmove_DEBUG("cvQueryFrame: %ld ms\n", psmove_util_get_ticks() - start);
+ cvGrabFrame(cc->capture);
+ if (ts_grab != NULL) {
+ *ts_grab = _psmove_timestamp();
+ }
+ result = cvRetrieveFrame(cc->capture, 0);
+ if (ts_retrieve != NULL) {
+ *ts_retrieve = _psmove_timestamp();
+ }
#endif
if (cc->deinterlace == PSMove_True) {
View
4 src/tracker/camera_control.h
@@ -34,6 +34,7 @@ extern "C" {
#endif
#include "psmove.h"
+#include "../psmove_private.h"
#include "opencv2/core/core_c.h"
struct _CameraControl;
@@ -51,7 +52,8 @@ camera_control_set_deinterlace(CameraControl *cc,
enum PSMove_Bool enabled);
IplImage *
-camera_control_query_frame(CameraControl* cc);
+camera_control_query_frame(CameraControl* cc,
+ PSMove_timestamp *ts_grab, PSMove_timestamp *ts_retrieve);
void
camera_control_delete(CameraControl* cc);
View
40 src/tracker/platform/camera_control_linux.c
@@ -113,24 +113,26 @@ void camera_control_restore_system_settings(CameraControl* cc, const char* file)
}
}
-void camera_control_set_parameters(CameraControl* cc, int autoE, int autoG, int autoWB, int exposure, int gain, int wbRed, int wbGreen, int wbBlue, int contrast,
- int brightness) {
- int fd = open_v4l2_device(cc->cameraID);
-
- if (fd != -1) {
- if (autoE >= 0)
- v4l2_set_control(fd, V4L2_CID_EXPOSURE_AUTO, autoE);
- if (autoG >= 0)
- v4l2_set_control(fd, V4L2_CID_AUTOGAIN, autoG);
- if (gain >= 0)
- v4l2_set_control(fd, V4L2_CID_GAIN, gain);
- if (exposure >= 0)
- v4l2_set_control(fd, V4L2_CID_EXPOSURE, exposure);
- if (contrast >= 0)
- v4l2_set_control(fd, V4L2_CID_CONTRAST, contrast);
- if (brightness >= 0)
- v4l2_set_control(fd, V4L2_CID_BRIGHTNESS, brightness);
- v4l2_close(fd);
- }
+void
+camera_control_set_parameters(CameraControl* cc, int autoE, int autoG, int autoWB,
+ int exposure, int gain,
+ int wbRed, int wbGreen, int wbBlue,
+ int contrast, int brightness)
+{
+ int fd = open_v4l2_device(cc->cameraID);
+
+ if (fd != -1) {
+ v4l2_set_control(fd, V4L2_CID_EXPOSURE, exposure);
+ v4l2_set_control(fd, V4L2_CID_GAIN, gain);
+
+ v4l2_set_control(fd, V4L2_CID_EXPOSURE_AUTO, autoE);
+ v4l2_set_control(fd, V4L2_CID_AUTOGAIN, autoG);
+ v4l2_set_control(fd, V4L2_CID_AUTO_WHITE_BALANCE, autoWB);
+#if 0
+ v4l2_set_control(fd, V4L2_CID_CONTRAST, contrast);
+ v4l2_set_control(fd, V4L2_CID_BRIGHTNESS, brightness);
+#endif
+ v4l2_close(fd);
+ }
}
View
55 src/tracker/psmove_tracker.c
@@ -40,6 +40,7 @@
#include "psmove_tracker.h"
#include "../psmove_private.h"
+#include "psmove_tracker_private.h"
#include "camera_control.h"
#include "tracker_helpers.h"
@@ -49,11 +50,10 @@
# include "platform/psmove_linuxsupport.h"
#endif
-#define PRINT_DEBUG_STATS // shall graphical statistics be printed to the image
//#define DEBUG_WINDOWS // shall additional windows be shown
#define ROIS 4 // the number of levels of regions of interest (roi)
#define BLINKS 2 // number of diff images to create during calibration
-#define BLINK_DELAY 100 // number of milliseconds to wait between a blink
+#define BLINK_DELAY 200 // number of milliseconds to wait between a blink
#define CALIB_MIN_SIZE 50 // minimum size of the estimated glowing sphere during calibration process (in pixel)
#define CALIB_SIZE_STD 10 // maximum standard deviation (in %) of the glowing spheres found during calibration process
#define CALIB_MAX_DIST 30 // maximum displacement of the separate found blobs
@@ -183,6 +183,13 @@ pseye_distance_parameters = {
struct _PSMoveTracker {
CameraControl* cc;
+
+ /* Timestamps for performance measurements */
+ PSMove_timestamp ts_camera_begin; // when the capture was started
+ PSMove_timestamp ts_camera_grab; // when the image was grabbed
+ PSMove_timestamp ts_camera_retrieve; // when the image was retrieved
+ PSMove_timestamp ts_camera_converted; // when the image was converted
+
IplImage* frame; // the current frame of the camera
IplImage *frame_rgb; // the frame as tightly packed RGB data
int exposure; // the exposure to use
@@ -309,13 +316,6 @@ void psmove_tracker_set_roi(PSMoveTracker* tracker, TrackedController* tc, int r
*/
int psmove_tracker_update_controller(PSMoveTracker* tracker, TrackedController *tc);
-/**
- * This draws tracking statistics into the current camera image. This is only used internally.
- *
- * tracker - the Tracker to use
- */
-void psmove_tracker_draw_tracking_stats(PSMoveTracker* tracker);
-
/*
* This finds the biggest contour within the given image.
*
@@ -595,7 +595,7 @@ psmove_tracker_new_with_camera(int camera) {
// just query a frame so that we know the camera works
IplImage* frame = NULL;
while (!frame) {
- frame = camera_control_query_frame(tracker->cc);
+ frame = camera_control_query_frame(tracker->cc, NULL, NULL);
}
// prepare ROI data structures
@@ -684,9 +684,9 @@ psmove_tracker_enable(PSMoveTracker *tracker, PSMove *move)
struct PSMove_RGBValue preset_colors[] = {
{0xFF, 0x00, 0xFF}, /* magenta */
{0x00, 0xFF, 0xFF}, /* cyan */
- {0x00, 0x00, 0xFF}, /* blue */
{0xFF, 0xFF, 0x00}, /* yellow */
- {0x00, 0xFF, 0x00}, /* green */
+ {0xFF, 0x00, 0x00}, /* red */
+ {0x00, 0x00, 0xFF}, /* blue */
};
for (i=0; i<ARRAY_LENGTH(preset_colors); i++) {
@@ -1163,7 +1163,10 @@ psmove_tracker_get_image(PSMoveTracker *tracker)
void psmove_tracker_update_image(PSMoveTracker *tracker) {
psmove_return_if_fail(tracker != NULL);
- tracker->frame = camera_control_query_frame(tracker->cc);
+
+ tracker->ts_camera_begin = _psmove_timestamp();
+ tracker->frame = camera_control_query_frame(tracker->cc,
+ &(tracker->ts_camera_grab), &(tracker->ts_camera_retrieve));
if (tracker->mirror) {
/**
* Mirror image on the X axis (works for me with the PS Eye on Linux,
@@ -1175,6 +1178,7 @@ void psmove_tracker_update_image(PSMoveTracker *tracker) {
**/
cvFlip(tracker->frame, NULL, 1);
}
+ tracker->ts_camera_converted = _psmove_timestamp();
}
int
@@ -1419,11 +1423,6 @@ psmove_tracker_update(PSMoveTracker *tracker, PSMove *move)
tracker->duration = psmove_util_get_ticks() - started;
-#ifdef PRINT_DEBUG_STATS
- // draw all/one controller information to camera image
- psmove_tracker_draw_tracking_stats(tracker);
-#endif
-
return spheres_found;
}
@@ -1571,7 +1570,7 @@ psmove_tracker_wait_for_frame(PSMoveTracker *tracker, IplImage **frame, int dela
while (elapsed_time < delay) {
usleep(1000 * step);
- *frame = camera_control_query_frame(tracker->cc);
+ *frame = camera_control_query_frame(tracker->cc, NULL, NULL);
elapsed_time += step;
}
}
@@ -1629,7 +1628,7 @@ void psmove_tracker_set_roi(PSMoveTracker* tracker, TrackedController* tc, int r
tc->roi_y = tracker->frame->height - roi_height;
}
-void psmove_tracker_draw_tracking_stats(PSMoveTracker* tracker) {
+void psmove_tracker_annotate(PSMoveTracker* tracker) {
CvPoint p;
IplImage* frame = tracker->frame;
@@ -1692,7 +1691,7 @@ void psmove_tracker_draw_tracking_stats(PSMoveTracker* tracker) {
} else {
roi_w = tracker->roiI[tc->roi_level]->width;
roi_h = tracker->roiI[tc->roi_level]->height;
- cvRectangle(frame, cvPoint(tc->roi_x, tc->roi_y), cvPoint(tc->roi_x + roi_w, tc->roi_y + roi_h), TH_COLOR_RED, 3, 8, 0);
+ cvRectangle(frame, cvPoint(tc->roi_x, tc->roi_y), cvPoint(tc->roi_x + roi_w, tc->roi_y + roi_h), tc->eColor, 3, 8, 0);
}
}
}
@@ -1851,3 +1850,17 @@ psmove_tracker_color_is_used(PSMoveTracker *tracker, struct PSMove_RGBValue colo
return 0;
}
+
+void
+_psmove_tracker_retrieve_stats(PSMoveTracker *tracker,
+ PSMove_timestamp *ts_begin, PSMove_timestamp *ts_grab,
+ PSMove_timestamp *ts_retrieve, PSMove_timestamp *ts_converted)
+{
+ psmove_return_if_fail(tracker != NULL);
+
+ *ts_begin = tracker->ts_camera_begin;
+ *ts_grab = tracker->ts_camera_grab;
+ *ts_retrieve = tracker->ts_camera_retrieve;
+ *ts_converted = tracker->ts_camera_converted;
+}
+
View
53 src/tracker/psmove_tracker_private.h
@@ -0,0 +1,53 @@
+
+/**
+ * PS Move API - An interface for the PS Move Motion Controller
+ * Copyright (c) 2012 Thomas Perl <m@thp.io>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ **/
+
+#ifndef PSMOVE_TRACKER_PRIVATE_H
+#define PSMOVE_TRACKER_PRIVATE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "psmove.h"
+#include "psmove_tracker.h"
+
+#include "../psmove_private.h"
+
+/* Performance measurement private APIs (used in tests) */
+ADDAPI void
+ADDCALL _psmove_tracker_retrieve_stats(PSMoveTracker *tracker,
+ PSMove_timestamp *ts_begin, PSMove_timestamp *ts_grab,
+ PSMove_timestamp *ts_retrieve, PSMove_timestamp *ts_converted);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Please sign in to comment.
Something went wrong with that request. Please try again.