Revision 0d2003bb

View differences:

examples/demo_korg_slider/CMakeLists.txt
1
SET( PROJECT_NAME demo_korg_slider )
2
PROJECT( ${PROJECT_NAME} )
3
# set (CMAKE_VERBOSE_MAKEFILE true)
4
#profiling
5
#set(CMAKE_CXX_FLAGS "-Wall -g -pg")
6
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
7

  
8

  
9
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} /homes/sschulz/src/ros_workspace/install/share/humotion/cmake/)
10
# set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /homes/sschulz/src/ros_workspace/install/lib/pkg_config)
11

  
12
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
13
INCLUDE(FindPkgConfig)
14

  
15
# search for Boost version 1.34
16
find_package( Boost 1.40 COMPONENTS thread program_options system filesystem regex )
17
link_directories ( ${Boost_LIBRARY_DIRS}  )
18
include_directories ( ${Boost_INCLUDE_DIRS} )
19
# message(${Boost_LIBRARIES})
20

  
21

  
22

  
23
SET(PREFIX ${CMAKE_INSTALL_PREFIX})
24
SET(BINDIR "${PREFIX}/bin")
25
SET(INCLUDEDIR "${PREFIX}/include")
26
SET(MANDIR "${PREFIX}/man")
27
SET(LIBDIR "${PREFIX}/lib")
28
SET(DATADIR "${PREFIX}/share/${NAME}")
29

  
30
find_package(humotion 0.0.1)
31
IF (humotion_FOUND)
32
	message("> using humotion includes from " ${humotion_INCLUDE_DIRS})
33
ELSE (humotion_FOUND)
34
	message(FATAL_ERROR "> error: can not find libhumotion")
35
endif (humotion_FOUND)
36

  
37
SET(SRC_FILES
38
	korg_input.cpp
39
)
40

  
41
LINK_DIRECTORIES(${LIBDIR} ${humotion_LIBRARY_DIRS} )
42
INCLUDE_DIRECTORIES( ${humotion_INCLUDE_DIRS} )
43

  
44
ADD_EXECUTABLE( ${PROJECT_NAME} main.cpp ${SRC_FILES})
45
TARGET_LINK_LIBRARIES(  ${PROJECT_NAME} ${Boost_LIBRARIES} ${Boost_LIBS}  ${humotion_LIBRARIES} portmidi porttime) 
46

  
47

  
48
#FILE(GLOB conf_files "${CMAKE_CURRENT_SOURCE_DIR}/*.mcfg")
49
#install (FILES ${conf_files} DESTINATION etc/xsc2)
50

  
51
install (TARGETS ${PROJECT_NAME} DESTINATION bin )
52
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
53
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
54

  
examples/demo_korg_slider/korg_input.cpp
1
#include "korg_input.h"
2
#include <assert.h>
3
#include <stdlib.h>
4

  
5
#define DEBUG_SHOW_MIDI_DEVICES 1
6
#define DEBUG_INCOMING_DATA 1
7

  
8
//defines for portmidi
9
#define INPUT_BUFFER_SIZE 100
10
#define OUTPUT_BUFFER_SIZE 0
11
#define DRIVER_INFO NULL
12
#define TIME_PROC ((int32_t (*)(void *)) Pt_Time)
13
#define TIME_INFO NULL
14
#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */
15

  
16
//! constructor
17
KorgInput::KorgInput(){
18
	midi = NULL;
19
	//first try old device:
20
	device_open = open_device();
21
	for(int i=0; i<256; i++){
22
		data[i] = 64;
23
		data_new[i] = false;
24
	}
25
}
26

  
27
//! destructor
28
KorgInput::~KorgInput(){
29
	if (device_open){
30
		//close
31
		Pm_Close(midi);
32
	}
33
}
34

  
35
//! fetch device id
36
//! \param char array with device name
37
//! \return id of device, or -1 if not found
38
int KorgInput::fetch_device_id(const char *name, bool output=false){
39
	//fetch device id:
40
	int midi_device_id = -1;
41
	
42
	for (int i = 0; i < Pm_CountDevices(); i++) {
43
		const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
44
		if (DEBUG_SHOW_MIDI_DEVICES) printf("%d: %s, %s\n", i, info->interf, info->name);
45
		
46
		if (output){
47
			if (info->output) {
48
				if (strcmp(info->name, name) == 0){
49
					midi_device_id = i;
50
				}
51
			}
52
		}else{
53
			if (info->input) {
54
				if (strcmp(info->name, name) == 0){
55
					midi_device_id = i;
56
				}
57
			}
58
		}
59
	}
60
	
61
	return midi_device_id;
62
}
63

  
64
//! open device
65
//! \return true if device is found, false otherwise
66
bool KorgInput::open_device(){
67
	PmEvent buffer[1];
68
	
69
	//standard is type1:
70
	device_type = NANO_KONTROL;
71

  
72
	int midi_device_id = fetch_device_id("nanoKONTROL MIDI 1");
73
	int midi_device_id_out = fetch_device_id("nanoKONTROL MIDI 1", true);
74
	if (midi_device_id == -1){
75
		device_type = NANO_KONTROL2;
76
		midi_device_id = fetch_device_id("nanoKONTROL2 MIDI 1");
77
		midi_device_id_out = fetch_device_id("nanoKONTROL2 MIDI 1", true);
78
	}
79
	
80
	
81
	if (midi_device_id == -1){
82
		printf("> can not open device (input). Error: device not found\n");
83
		return false;
84
	}
85
	
86
	if (midi_device_id_out == -1){
87
		printf("> can not open output device\n");
88
		return false;
89
	}
90
	
91
	//success, found device
92
	printf("> found korg controller with id %d (%s)\n",midi_device_id,device_type==NANO_KONTROL?"nanoKONTROL":"nanoKONTROL2");
93
	printf("> if setting leds on/off does not work, make sure to set led mode to external with the korg windows software\n");
94
	
95
	//open input
96
	Pm_OpenInput(&midi, midi_device_id, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO);
97
	
98
	//open output
99
	Pm_OpenOutput(&midi_out, midi_device_id_out, DRIVER_INFO, OUTPUT_BUFFER_SIZE, NULL, NULL, 0); 
100
 
101

  
102

  
103

  
104
	//set filter
105
	Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);
106
	Pm_SetFilter(midi_out, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);
107
	
108
	//clear buffer with unfiltered messages
109
	//printf("> clearing buffer\n");
110
	//while (Pm_Poll(midi)) {
111
		//Pm_Read(midi, buffer, 1);
112
	//}
113
	printf("> init done \n");
114
	
115
	//disable all leds:
116
// 	for(unsigned char id = 0; id<127; id++){
117
// 		Pm_WriteShort(midi_out, TIME_PROC(TIME_INFO), Pm_Message(0xB0, id, 0));
118
// 		usleep(10*1000);
119
// 	}
120
	
121
	//fancy animation:
122
	for(unsigned char id = 0; id<80+4; id++){
123
		if (id<127) Pm_WriteShort(midi_out, TIME_PROC(TIME_INFO), Pm_Message(0xB0, id, 127));
124
		if (id>4)   Pm_WriteShort(midi_out, TIME_PROC(TIME_INFO), Pm_Message(0xB0, id-4, 0));
125
		usleep(25*1000);
126
	}
127
	
128
// 	for(unsigned char id = 0; id<127; id++){
129
// 		Pm_WriteShort(midi_out, TIME_PROC(TIME_INFO), Pm_Message(0xB0, id, 0));
130
// 	}
131
// 	
132
	return true;
133
}
134

  
135
//! device opened sucessfully
136
//! \return true if device is open and working
137
bool KorgInput::device_available(){
138
	return device_open;
139
}
140

  
141

  
142
//! fetch new data
143
//! \return int count how many datasets were fetched
144
int KorgInput::fetch_data(){
145
	int new_data_fetched = 0;
146
	//poll all data:
147
	while(Pm_Poll(midi)){
148
		//new data fetch sucessfull? build up dataset:
149
		if (fetch_single()){
150
			new_data_fetched++;
151
		}
152
	}
153

  
154
	if (new_data_fetched > 0){
155
		printf("> fetched %d datasets\n",new_data_fetched);
156
	}
157
	
158
	return new_data_fetched;
159
}
160

  
161
bool KorgInput::fetch_single(){
162
	PmEvent buffer[1];
163
	
164
	//poll data:
165
	PmError status = Pm_Poll(midi);
166
	
167
	if (status) {
168
		int length = Pm_Read(midi,buffer, 1);
169
		if (length > 0) {
170
			//store incoming data:
171
			if (Pm_MessageStatus(buffer[0].message) == 0xb0){
172
				unsigned int idx = Pm_MessageData1(buffer[0].message) & 0xFF;
173
				data[idx] = Pm_MessageData2(buffer[0].message) & 0xFF;
174
				data_new[idx] = true;
175
			}
176
			
177
			if (DEBUG_INCOMING_DATA){
178
				printf("> incoming message: time %ld, %2lx %2lx %2lx\n",
179
					(long) buffer[0].timestamp,
180
					(long) Pm_MessageStatus(buffer[0].message),
181
					(long) Pm_MessageData1(buffer[0].message),
182
					(long) Pm_MessageData2(buffer[0].message));
183
			}
184
			
185
			return true;
186
		} else {
187
			printf("> error, message len <= 0?!\n");
188
			return false;
189
		}
190
	}
191
	
192
}
193

  
194
//! access buffered data
195
//! \param index of data channel to fetch
196
//! \return unsigned char value for data channel <index> (0..127)
197
unsigned char KorgInput::get_buffered_raw_value(unsigned char index){
198
	return data[index];
199
}
200

  
201
//! fetch a value + new flag & clear
202
//! \param idx index
203
//! \param uchar ptr to data
204
//! \return true if new data available
205
bool KorgInput::get_and_reset(unsigned char idx, unsigned char *val){
206
	//fetch state & reset:
207
	bool new_data = data_new[idx];
208
	data_new[idx] = false;
209
	
210
	//override data only if new val arrived:
211
	if (new_data){
212
		*val = get_buffered_raw_value(idx);
213
	}	
214
	
215
	return new_data;
216
}
217

  
218
//! access slider 
219
//! \param slider index 0..8
220
//! \param uchar ptr to value
221
//! \return bool if new value arrived
222
bool KorgInput::get_slider(unsigned char index, unsigned char *val){
223
	assert(index <= 8);
224
	if (device_type == NANO_KONTROL){
225
		switch(index){
226
			default: 
227
				
228
				return get_and_reset(0x02 + index, val);
229
			case(5):
230
			case(6):
231
				return get_and_reset(0x02 + index + 1, val);
232
			case(7):
233
			case(8):
234
				return get_and_reset(0x02 + index + 3, val);
235
		}
236
	}else{
237
		//NANO_KONTROL2
238
		return get_and_reset(index, val);
239
	}
240
}
241

  
242
//! access button 
243
//! \param button index 
244
//! \param uchar ptr to value
245
//! \return bool if new value arrived
246
bool KorgInput::get_button(unsigned char index, unsigned char *val){
247
	assert(index <= 127);
248
	
249
	if (device_type == NANO_KONTROL){
250
		printf("> NANO_KONTROL NOT SUPPORTED, different layout of buttons! exiting\n");
251
		exit(1);
252
		/*if (row == 0){
253
			return get_and_reset(0x17+index, val);
254
		}else if (row == 1){
255
			printf("> NANO_KONTROL does not have center row. ignored\n");
256
			return false;
257
		}else{
258
			return get_and_reset(0x21+index, val);
259
		}*/
260
	}else{
261
		//NANO_KONTROL2 - fetch button value
262
		return get_and_reset(index, val);
263
	}
264
}
265

  
266
//! access pot 
267
//! \param pot index 0..8
268
//! \param unsigned char ptr to value (0..127)
269
//! \param bool true if new data available
270
bool KorgInput::get_pot(unsigned char index, unsigned char *val){
271
	assert(index <= 8);
272
	if (device_type == NANO_KONTROL){
273
		return get_and_reset(0x0E + index, val);
274
	}else{
275
		//NANO_KONTROL2
276
		return get_and_reset(0x10 + index, val);
277
	}
278
}
279

  
280
void  KorgInput::set_led(unsigned char index, bool status){
281
	Pm_WriteShort(midi_out, TIME_PROC(TIME_INFO), Pm_Message(0xB0, index, status?127:0));
282
}
examples/demo_korg_slider/korg_input.h
1
#pragma once
2

  
3
#include <portmidi.h>
4
#include <porttime.h>
5
#include <cstdio>
6
#include <stdio.h>
7
#include <string.h>
8
#include <unistd.h>
9

  
10
class KorgInput{
11
public:
12
	KorgInput();
13
	~KorgInput();
14
	
15
	bool  get_slider(unsigned char index, unsigned char *val);
16
	bool  get_pot(unsigned char index, unsigned char *val);
17
	bool  get_button(unsigned char index, unsigned char *val);
18
	void  set_led(unsigned char index, bool status);
19
	
20
	bool get_and_reset(unsigned char idx, unsigned char *val);
21
	void set_pot(unsigned char index, int value);
22
	
23
	int  fetch_data();
24
	bool device_available();
25
	
26
	
27
private:
28
	int resolve_id();
29
	
30
	unsigned char data[256];
31
	bool data_new[256];
32
	int device_type;
33
	enum DEVICE_TYPE {NANO_KONTROL, NANO_KONTROL2};
34
	bool open_device();
35
	bool fetch_single();
36
	int fetch_device_id(const char*, bool);
37
	unsigned char get_buffered_raw_value(unsigned char index);
38
	
39
	bool device_open;
40
	PmStream * midi;
41
	PmStream * midi_out;
42
};
examples/demo_korg_slider/main.cpp
1
#include <cstdio>
2
#include <stdio.h>
3
#include <string.h>
4

  
5

  
6
#include "korg_input.h"
7
#include "humotion/client/client.h"
8
#include "boost/date_time/posix_time/posix_time.hpp"
9
#include <boost/thread/thread_time.hpp>
10
#include <boost/thread/thread.hpp>
11

  
12
using namespace boost;
13
humotion::GazeState last_awake_state;
14
bool awake_state;
15

  
16
enum JOINT_SLIDER_ID{
17
	MOUTH_POSITION_LEFT=0,
18
	MOUTH_POSITION_CENTER,
19
	MOUTH_POSITION_RIGHT,
20
	PAN,
21
	TILT
22
	//NECK_ROLL,
23
};
24

  
25
enum JOINT_POTI_ID{
26
	MOUTH_OPENING_LEFT=0,
27
	MOUTH_OPENING_CENTER,
28
	MOUTH_OPENING_RIGHT,
29
	EYE_VERGENCE,
30
	EYELID_OPENING_UPPER,
31
	EYELID_OPENING_LOWER,
32
	EYEBROW_RIGHT,
33
	EYEBROW_LEFT
34
};
35

  
36

  
37

  
38
float to_float(unsigned char val){
39
	return ((float)(val))/127.0;
40
}
41

  
42
void slidervalues_to_mouthstate(KorgInput *input, humotion::MouthState *result){
43
	unsigned char tmp;
44
	
45
	//do not handle updates when not awake
46
	if (!awake_state){
47
		return;
48
	}
49
	
50
	if (input->get_slider(MOUTH_POSITION_LEFT,  &tmp))result->position_left   = 0.0 + 40.0 * (1.0-to_float(tmp));
51
	if (input->get_slider(MOUTH_POSITION_CENTER,  &tmp))result->position_center = 0.0 + 40.0 * (1.0-to_float(tmp));
52
	if (input->get_slider(MOUTH_POSITION_RIGHT,  &tmp))result->position_right  = 0.0 + 40.0 * (1.0-to_float(tmp));
53

  
54
	if (input->get_pot(MOUTH_OPENING_LEFT,  &tmp)) result->opening_left   = 40.0 * to_float(tmp);
55
	if (input->get_pot(MOUTH_OPENING_CENTER,  &tmp)) result->opening_center= 40.0 * to_float(tmp);
56
	if (input->get_pot(MOUTH_OPENING_RIGHT,  &tmp)) result->opening_right  = 40.0 * to_float(tmp);
57

  
58
	//printf("OOO %4.2f %4.2f\n",result.opening_center, result.position_center);
59
}
60

  
61
void wake_up(humotion::GazeState *result){
62
	if (awake_state){
63
		//already awake, return
64
		return;
65
	}
66
	
67
	//restore last awake state
68
	*result = last_awake_state;
69
	//force reopening
70
	result->eyeblink_request_left  = 10;
71
	result->eyeblink_request_right = 10;
72
	
73
	awake_state = true;
74
}
75

  
76
void sleep(humotion::GazeState *result){
77
	if (!awake_state){
78
		//already sleeping, return
79
		return;
80
	}
81
	
82
	//store last awake state
83
	last_awake_state = *result;
84
	awake_state = false;
85
	
86
	//override values:
87
	result->pan  = 0.0;
88
	result->tilt = -20.0;
89
	result->roll = 0.0;
90
	
91
	//result->eyelid_opening = 0.0;
92
	result->eyebrow_left  = 0.0;
93
	result->eyebrow_right = 0.0;
94
	
95
	result->eyeblink_request_left = -1;
96
	result->eyeblink_request_right = -1;
97
	
98
	
99
}
100

  
101
void slidervalues_to_gazestate(KorgInput *input, humotion::GazeState *result){
102
	unsigned char tmp;
103
	
104
	//PLAY
105
	if (input->get_button(0x29, &tmp)){
106
		if (tmp != 0){
107
			wake_up(result);
108
		}
109
	}
110
	
111
	//STOP
112
	if (input->get_button(0x2A, &tmp)){
113
		if (tmp != 0){
114
			sleep(result);
115
		}
116
	}
117
	
118
	//do not handle updates when not awake
119
	if (!awake_state){
120
		return;
121
	}
122
	
123
	if (input->get_slider(PAN,  &tmp)) result->pan  = -50.0 + 100.0 * to_float(tmp);
124
	if (input->get_slider(TILT, &tmp)) result->tilt = -40.0 + 80.0 * to_float(tmp);
125
	result->roll = 0.0;
126
	
127
	if (input->get_pot(EYELID_OPENING_UPPER, &tmp)) result->eyelid_opening_upper = 0.0 + 120.0*to_float(tmp);
128
	if (input->get_pot(EYELID_OPENING_LOWER, &tmp)) result->eyelid_opening_lower = 0.0 + 120.0*to_float(tmp);
129

  
130
	
131
	if (input->get_pot(EYEBROW_LEFT,  &tmp)) result->eyebrow_left  = 60.0 - 120.0*to_float(tmp);
132
	if (input->get_pot(EYEBROW_RIGHT,  &tmp)) result->eyebrow_right = 60.0 - 120.0*to_float(tmp);
133
	
134
	if (input->get_pot(EYE_VERGENCE,  &tmp)) result->vergence = -20.0 * to_float(tmp);
135
	
136
	
137
	//check for blink requests: 
138
	if (input->get_button(0x24, &tmp)){
139
		if (tmp != 0){
140
			//blink left
141
			result->eyeblink_request_left = 300;
142
		}
143
	}
144
	if (input->get_button(0x44, &tmp)){
145
		if (tmp != 0){
146
			result->eyeblink_request_right = 300;
147
		}
148
	}
149
	if (input->get_button(0x34, &tmp)){
150
		if (tmp != 0){
151
			//blink both
152
			result->eyeblink_request_right = 150;
153
			result->eyeblink_request_left  = 150;
154
		}
155
	}
156
	
157
	//printf("PTR = %3.1f %3.1f %3.1f\n",result->pan,result->tilt,result->roll);
158
}
159

  
160
int main(int argc, char **argv){
161
	humotion::MouthState mouth_state;
162
	humotion::GazeState gaze_state;
163
	awake_state = true;
164
	
165
	if (argc != 2){
166
		printf("> ERROR: invalid parameter count.\n\nusage: %s <scope>\n       (e.g. %s /flobi)\n\n",argv[0],argv[0]);
167
		exit(EXIT_FAILURE);
168
	}
169

  
170
	printf("> starting korg kontrol demo. please make sure the korg device is connected via usb\n");
171
	
172
	KorgInput *kinput = new KorgInput();
173
	
174
	if (!kinput->device_available()){
175
		printf("> no korg kontrol device found on usb bus... exiting\n");
176
		return 0;
177
	}
178
	
179
	//set led status for blink requests:
180
	kinput->set_led(0x24, true);
181
	kinput->set_led(0x34, true);
182
	kinput->set_led(0x44, true);
183
	
184
	//set led for stop/play
185
	kinput->set_led(0x29, true);
186
	kinput->set_led(0x2A, true);
187
	
188
	
189
	//human motion connection:
190
	humotion::client::Client *client = new humotion::client::Client(argv[1], "ROS");
191
	
192
	//send values to human motion server
193
	float loop_delay = 1000.0 / 50.0; //run with 50Hz
194
	
195
	boost::system_time timeout = get_system_time() + posix_time::milliseconds(loop_delay);
196
	
197
	while(client->ok()){
198
		//allow middleware to process data
199
		client->tick();
200
		
201
		//clear previous eyeblinks
202
		gaze_state.eyeblink_request_left  = 0;
203
		gaze_state.eyeblink_request_right = 0;
204
	
205
		//handle slider data
206
		if (kinput->fetch_data() > 0){
207
			//debug
208
			mouth_state.dump();
209
			gaze_state.dump();
210
			printf("\n");
211

  
212
			//transfer values to robot:
213
			slidervalues_to_mouthstate(kinput, &mouth_state);
214
			slidervalues_to_gazestate(kinput, &gaze_state);
215
		} 
216
		
217
		//printf("BLINK: %d %d\n",gaze_state.eyeblink_request_left, gaze_state.eyeblink_request_right);
218
		
219
		//periodically send mouth & gaze target
220
		client->update_mouth_target(mouth_state);
221
		client->update_gaze_target(gaze_state);
222
		client->send_all();
223
		
224
		thread::sleep(timeout);
225
		timeout = get_system_time() + posix_time::milliseconds(loop_delay);
226

  
227
	}
228
	
229
}
src/server/motion_generator.cpp
76 76
//! was there incoming gaze data the last second?
77 77
//! \return true if there was data incoming in the last second, false otherwise
78 78
bool MotionGenerator::gaze_target_input_active(){
79
    if (last_gaze_target_update + posix_time::milliseconds(1000) > get_system_time() ){
79
    if (last_gaze_target_update  + posix_time::milliseconds(1000) > get_system_time() ){
80 80
        //incoming data -> if gaze is disabled, enable it!
81 81
        joint_interface->enable_gaze_joints();
82 82
        return true;

Also available in: Unified diff