Skip to content

Commit 62be71f

Browse files
authored
Merge pull request #4 from Nat-Lab/separated-control
improve leap controller
2 parents d361dfa + c3a8129 commit 62be71f

File tree

4 files changed

+148
-25
lines changed

4 files changed

+148
-25
lines changed

chuniio/chuniio.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ static LONG chuni_ir_height = 5000;
3030
static UINT chuni_ir_leap_trigger = 500;
3131
static UINT chuni_ir_leap_step = 300;
3232
static uint8_t leap_orientation = LEAP_Y;
33+
static BOOL leap_inverted = FALSE;
3334

3435
static LONG chuni_key_start = 31800;
3536
static LONG chuni_key_width = 4000;
@@ -156,7 +157,7 @@ static void make_control_window() {
156157
D2D1_FACTORY_OPTIONS opt = { D2D1_DEBUG_LEVEL_INFORMATION };
157158
if (D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory, &opt, (void **) &d2df) != S_OK) {
158159
log_fatal("can't create d2d factoy.\n");
159-
// return?
160+
return;
160161
}
161162
const char *name = "chuni-controller";
162163

@@ -195,14 +196,14 @@ static void make_control_window() {
195196

196197
if (ID2D1Factory_CreateHwndRenderTarget(d2df, &rtp, &hrtp, &target) < 0) {
197198
log_fatal("can't create d2d render target.\n");
198-
// return
199+
return;
199200
}
200201

201202
for (int i = 0; i < 32; i++) {
202203
D2D1_COLOR_F color = { i/32., i/32., i/32., 1. };
203204
if (ID2D1HwndRenderTarget_CreateSolidColorBrush(target, &color, NULL, &brushes[i]) < 0) {
204205
log_fatal("d2d brush creation failed.\n");
205-
// return
206+
return;
206207
}
207208
}
208209

@@ -219,8 +220,8 @@ void leap_handler(const LEAP_TRACKING_EVENT *ev) {
219220
if (leap_orientation == LEAP_Y) pos = hand->palm.position.y;
220221
if (leap_orientation == LEAP_Z) pos = hand->palm.position.z;
221222

222-
if (pos > chuni_ir_leap_trigger) {
223-
int8_t ir_id = (pos - chuni_ir_leap_trigger) / chuni_ir_leap_step - 1;
223+
if ((!leap_inverted && pos > chuni_ir_leap_trigger) || (leap_inverted && chuni_ir_leap_trigger > pos)) {
224+
int8_t ir_id = (leap_inverted ? -1 : 1) * (pos - chuni_ir_leap_trigger) / chuni_ir_leap_step + 1;
224225
if (ir_id > 5) ir_id = 5;
225226
if (ir_id < 0) ir_id = 0;
226227
chuni_io_ir(&chuni_ir_map_local, ir_id, true);
@@ -247,8 +248,8 @@ HRESULT chuni_io_jvs_init(void) {
247248
separate_control = GetPrivateProfileIntW(L"options", L"separate_control", FALSE, CONFIG);
248249
chuni_ir_height = GetPrivateProfileIntW(L"ir", L"touch_height", 50, CONFIG);
249250
chuni_ir_trigger_threshold = GetPrivateProfileIntW(L"ir", L"touch_trigger", 70, CONFIG);
250-
chuni_ir_leap_trigger = GetPrivateProfileIntW(L"ir", L"leap_trigger", 500, CONFIG);
251-
chuni_ir_leap_step = GetPrivateProfileIntW(L"ir", L"leap_step", 300, CONFIG);
251+
chuni_ir_leap_trigger = GetPrivateProfileIntW(L"ir", L"leap_trigger", 50, CONFIG);
252+
chuni_ir_leap_step = GetPrivateProfileIntW(L"ir", L"leap_step", 30, CONFIG);
252253
chuni_key_start = GetPrivateProfileIntW(L"slider", L"offset", 318, CONFIG);
253254
chuni_key_width = GetPrivateProfileIntW(L"slider", L"width", 40, CONFIG);
254255
raw_input = GetPrivateProfileIntW(L"io", L"raw_input", 0, CONFIG);
@@ -280,6 +281,9 @@ HRESULT chuni_io_jvs_init(void) {
280281
/**/ if (wcscmp(str_leap_orientation, L"x") == 0) leap_orientation = LEAP_X;
281282
else if (wcscmp(str_leap_orientation, L"y") == 0) leap_orientation = LEAP_Y;
282283
else if (wcscmp(str_leap_orientation, L"z") == 0) leap_orientation = LEAP_Z;
284+
else if (wcscmp(str_leap_orientation, L"-x") == 0) { leap_orientation = LEAP_X; leap_inverted = TRUE; }
285+
else if (wcscmp(str_leap_orientation, L"-y") == 0) { leap_orientation = LEAP_Y; leap_inverted = TRUE; }
286+
else if (wcscmp(str_leap_orientation, L"-z") == 0) { leap_orientation = LEAP_Z; leap_inverted = TRUE; }
283287

284288
for(int i = 0; i < MAXFINGERS; i++) finger_ids[i] = -1;
285289

leap-configurator/leap-configurator.c

Lines changed: 131 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,54 @@
1+
#include <math.h>
12
#include "leapio/leapio.h"
23
#include "log.h"
34

4-
static BOOL _test_mode = false;
5+
#define CONFIG L".\\chunitouch.ini"
6+
7+
static BOOL _test_mode = FALSE;
58
static uint32_t _n_hands = 0;
6-
float _x, _y, _z;
9+
static float _x, _y, _z;
10+
static BOOL use_leap;
11+
static UINT leap_trigger;
12+
static UINT leap_step;
13+
static UINT leap_orientation;
14+
static BOOL leap_inverted;
15+
16+
#define LEAP_X 0
17+
#define LEAP_Y 1
18+
#define LEAP_Z 2
719

8-
void log_tracks(const LEAP_TRACKING_EVENT *ev) {
9-
log_debug("saw %u hands.\n", ev->nHands);
20+
void handle_track(const LEAP_TRACKING_EVENT *ev) {
21+
// log_debug("saw %u hands.\n", ev->nHands);
22+
static int8_t last_id = -1;
1023
_n_hands = ev->nHands;
1124
for(uint32_t h = 0; h < ev->nHands; h++) {
1225
const LEAP_HAND* hand = &(ev->pHands[h]);
13-
log_debug("hand %u is a %s hand. location (%f, %f, %f).\n",
14-
hand->id, hand->type == eLeapHandType_Left ? "left" : "right",
15-
hand->palm.position.x, hand->palm.position.y, hand->palm.position.z);
26+
_x = hand->palm.position.x;
27+
_y = hand->palm.position.y;
28+
_z = hand->palm.position.z;
29+
30+
if (_test_mode) {
31+
int8_t id = -1;
32+
float pos = 0;
33+
if (leap_orientation == LEAP_X) pos = _x;
34+
if (leap_orientation == LEAP_Y) pos = _y;
35+
if (leap_orientation == LEAP_Z) pos = _z;
36+
if ((!leap_inverted && pos > leap_trigger) || (leap_inverted && leap_trigger > pos)) {
37+
id = (leap_inverted ? -1 : 1) * (pos - leap_trigger) / leap_step - 1;
38+
if (id > 5) id = 5;
39+
if (id < 0) id = 0;
40+
}
41+
42+
if (last_id != id) {
43+
if (id >= 0) log_info("IR %d triggered.\n", id + 1);
44+
else log_info("No IR triggered.\n");
45+
last_id = id;
46+
}
47+
}
48+
49+
//log_debug("hand %u is a %s hand. location (%f, %f, %f).\n",
50+
// hand->id, hand->type == eLeapHandType_Left ? "left" : "right",
51+
// hand->palm.position.x, hand->palm.position.y, hand->palm.position.z);
1652
}
1753
}
1854

@@ -32,11 +68,26 @@ char prompt(const char *p, const char *s, uint8_t n) {
3268
}
3369

3470
void configure() {
35-
bool low_ok = false, high_ok = false;
36-
float low_x, low_y, low_z, high_x;
71+
float low_x, low_y, low_z, high_x, high_y, high_z;
72+
73+
while (TRUE) {
74+
prompt("Put your hand at the location you want the bottommost sensor to be activated, press [ENTER] when you are ready.", NULL, 0);
75+
if (_n_hands == 0) {
76+
printf("I can't see any hands.\n");
77+
continue;
78+
}
79+
if (_n_hands > 1) {
80+
printf("I saw more than one hand.\n");
81+
continue;
82+
}
83+
low_x = _x;
84+
low_y = _y;
85+
low_z = _z;
86+
break;
87+
}
3788

38-
while (!low_ok) {
39-
prompt("Put your hand at the lowest location you want the IR sensor to be triggered, then press [ENTER]", NULL, 0);
89+
while (TRUE) {
90+
prompt("Put your hand at the location you want the topmost sensor to be activated, press [ENTER] when you are ready.", NULL, 0);
4091
if (_n_hands == 0) {
4192
printf("I can't see any hands.\n");
4293
continue;
@@ -45,20 +96,87 @@ void configure() {
4596
printf("I saw more than one hand.\n");
4697
continue;
4798
}
99+
high_x = _x;
100+
high_y = _y;
101+
high_z = _z;
102+
break;
48103
}
49104

105+
log_info("low: (%f, %f, %f), high: (%f, %f, %f).\n", low_x, low_y, low_z, high_x, high_y, high_z);
106+
float dx = high_x - low_x;
107+
float dy = high_y - low_y;
108+
float dz = high_z - low_z;
109+
float dmax = max(max(fabs(dx), fabs(dy)), fabs(dz));
110+
WCHAR leap_orientation_char;
111+
112+
if (dmax == fabs(dx)) {
113+
leap_orientation_char = 'x';
114+
leap_orientation = LEAP_X;
115+
leap_trigger = low_x;
116+
}
117+
if (dmax == fabs(dy)) {
118+
leap_orientation_char = 'y';
119+
leap_orientation = LEAP_Y;
120+
leap_trigger = low_y;
121+
}
122+
if (dmax == fabs(dz)) {
123+
leap_orientation_char = 'z';
124+
leap_orientation = LEAP_Z;
125+
leap_trigger = low_z;
126+
}
127+
if (leap_orientation == LEAP_X && dx < 0) {
128+
leap_inverted = TRUE;
129+
}
130+
if (leap_orientation == LEAP_Y && dy < 0) {
131+
leap_inverted = TRUE;
132+
}
133+
if (leap_orientation == LEAP_Z && dz < 0) {
134+
leap_inverted = TRUE;
135+
}
136+
leap_step = dmax/6;
137+
use_leap = TRUE;
138+
139+
WCHAR leap_trigger_str[16];
140+
WCHAR leap_step_str[16];
141+
WCHAR leap_orientation_str[16];
142+
143+
swprintf_s(leap_trigger_str, 16, L"%d", leap_trigger);
144+
swprintf_s(leap_step_str, 16, L"%d", leap_step);
145+
swprintf_s(leap_orientation_str, 16, L"%s%c", leap_inverted ? L"-" : L"", leap_orientation_char);
146+
147+
WritePrivateProfileStringW(L"ir", L"leap_trigger", leap_trigger_str, CONFIG);
148+
WritePrivateProfileStringW(L"ir", L"leap_step", leap_step_str, CONFIG);
149+
WritePrivateProfileStringW(L"ir", L"leap_orientation", leap_orientation_str, CONFIG);
50150
}
51151

52152
void test() {
53153
printf("Move your hand around. Configurator will print out which IR sensor is being activated.\n");
54154
prompt("Press [ENTER] to begin test, press [ENTER] again to end.", NULL, 0);
55155
_test_mode = true;
56156
(void) getchar();
157+
_test_mode = false;
57158
}
58159

59160
int main () {
161+
leap_trigger = GetPrivateProfileIntW(L"ir", L"leap_trigger", 50, CONFIG);
162+
leap_step = GetPrivateProfileIntW(L"ir", L"leap_step", 30, CONFIG);
163+
164+
WCHAR str_control_src[16];
165+
WCHAR str_leap_orientation[16];
166+
167+
GetPrivateProfileStringW(L"ir", L"control_source", L"touch", str_control_src, 16, CONFIG);
168+
GetPrivateProfileStringW(L"ir", L"leap_orientation", L"y", str_leap_orientation, 16, CONFIG);
169+
use_leap = wcscmp(str_control_src, L"leap") == 0;
170+
171+
/**/ if (wcscmp(str_leap_orientation, L"x") == 0) leap_orientation = LEAP_X;
172+
else if (wcscmp(str_leap_orientation, L"y") == 0) leap_orientation = LEAP_Y;
173+
else if (wcscmp(str_leap_orientation, L"z") == 0) leap_orientation = LEAP_Z;
174+
else if (wcscmp(str_leap_orientation, L"-x") == 0) { leap_orientation = LEAP_X; leap_inverted = TRUE; }
175+
else if (wcscmp(str_leap_orientation, L"-y") == 0) { leap_orientation = LEAP_Y; leap_inverted = TRUE; }
176+
else if (wcscmp(str_leap_orientation, L"-z") == 0) { leap_orientation = LEAP_Z; leap_inverted = TRUE; }
177+
60178
log_info("connecting to leap service...\n");
61-
leap_set_tracking_handler(log_tracks); // debug
179+
leap_set_tracking_handler(handle_track); // debug
62180

63181
leap_connect(NULL);
64182
while (!leap_is_connected()) {
@@ -68,6 +186,7 @@ int main () {
68186

69187
while (TRUE) {
70188
printf("chuni-touch: leap configurator\n");
189+
printf("current configured values: enabled: %s, trigger: %d, step: %d, orientation: %s%d.\n", use_leap ? "true" : "false", leap_trigger, leap_step, leap_inverted ? "-" : "", leap_orientation);
71190
printf(" c) configure\n");
72191
printf(" t) test\n");
73192
printf("\n");

leapio/leapio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static void leap_log(const LEAP_LOG_EVENT* e) {
4242
case eLeapLogSeverity_Unknown: log_notice("%s.\n", e->message); break;
4343
case eLeapLogSeverity_Critical: log_fatal("%s.\n", e->message); break;
4444
case eLeapLogSeverity_Warning: log_warn("%s.\n", e->message); break;
45-
case eLeapLogSeverity_Information: log_info("%s.\n", e->message); break;
45+
// case eLeapLogSeverity_Information: log_info("%s.\n", e->message); break;
4646
}
4747
}
4848

readme.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,21 @@ separate_control = 0
3030
[ir]
3131
; source of control. 'touch' for touchscreen and 'leap' for leap motion.
3232
control_source = touch
33-
; height of each touch IR sensor
33+
; height of each touch IR sensor (unit: pixel)
3434
touch_height = 50
3535
; touch IR trigger threshold (number of pixels required to move up for a move to
3636
; be registered as air)
3737
touch_trigger = 70
38-
; specifies the axis to track hands on. x, y, or z.
38+
; specifies the axis to track hands on. x, y, z, -x, -y, or -z.
3939
leap_orientation = y
4040
; the minimum height of your hand(s) need to be for it to be registered as air
4141
; (unit: millimeters)
42-
leap_trigger = 500
42+
leap_trigger = 100
4343
; the height of each virtual IR sensor (unit: millimeters)
44-
leap_step = 300
44+
leap_step = 30
4545
4646
[slider]
47-
; slider's width
47+
; slider's width (unit: pixel)
4848
width = 40
4949
; slider's x-offset (pixels from the left of the screen)
5050
offset = 318

0 commit comments

Comments
 (0)