Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 import rospy
00009 import rospkg
00010 import rosparam
00011
00012 import pygame
00013 import pygame.midi
00014
00015 from sensor_msgs.msg import Joy
00016
00017
00018 class KorgNanoKontrol(object):
00019
00020 ''' Class to connect to and publish the Korg NanoKontrol midi device
00021 as a ros joystick
00022 '''
00023
00024 def __init__(self):
00025 ''' connect to midi device and set up ros
00026 '''
00027 pygame.midi.init()
00028 devices = pygame.midi.get_count()
00029 if devices < 1:
00030 rospy.logerr("No MIDI devices detected")
00031 exit(-1)
00032 rospy.loginfo("Found %d MIDI devices" % devices)
00033
00034 input_dev = int(rospy.get_param("~input_dev",
00035 pygame.midi.get_default_input_id))
00036
00037 rospy.loginfo("Using input device %d" % input_dev)
00038
00039 self.controller = pygame.midi.Input(input_dev)
00040
00041
00042 if not rospy.has_param('~modes'):
00043 rospack = rospkg.RosPack()
00044 paramlist = rosparam.load_file(rospack.get_path('korg_nanokontrol') +
00045 '/config/nanokontrol_config.yaml')
00046 for params, ns in paramlist:
00047 rosparam.upload_params(ns, params)
00048
00049 self.modes = rospy.get_param('~modes')
00050
00051
00052 self.center_axis = rospy.get_param('~center_axis', True)
00053
00054 self.msg = Joy()
00055 self.mode = None
00056
00057 self.pub = rospy.Publisher('joy', Joy, queue_size=10, latch=True)
00058
00059 def finish(self):
00060 del self.controller
00061 pygame.midi.quit()
00062
00063 def update(self):
00064 ''' run the update hook (poll the midi controller, publish the message)
00065 '''
00066 while self.controller.poll():
00067 data = self.controller.read(1)
00068 if self.mode == None:
00069 self.set_mode(self.guess_mode(data))
00070 else:
00071 self.pub_data(data)
00072
00073 def set_mode(self, mode):
00074 ''' Set up the message for the correct mode
00075 '''
00076 if not mode == None:
00077 self.mode = mode
00078 self.msg.axes = [0]*len(self.modes[mode]['control_axis'])
00079 self.msg.buttons = [0]*len(self.modes[mode]['control_buttons'])
00080 self.msg.buttons.append(mode)
00081
00082 def guess_mode(self, data):
00083 ''' Given data, try to guess the mode we are in
00084 '''
00085 for event in data:
00086 control = event[0]
00087
00088
00089 if (control[0] & 0xF0) == 176:
00090 control_id = control[1] | ((control[0] & 0x0F) << 8)
00091
00092
00093 candidate = None
00094 for index, control_mode in enumerate(self.modes):
00095 if control_id in control_mode['control_axis']:
00096 if candidate is not None:
00097 candidate = None
00098 break
00099 candidate = index
00100
00101 if control_id in control_mode['control_buttons']:
00102 if candidate is not None:
00103 candidate = None
00104 break
00105 candidate = index
00106 if not candidate:
00107 rospy.loginfo("determining mode..")
00108 return candidate
00109
00110 def clip(self, min, max, val):
00111 if val < min:
00112 val = min
00113 if val > max:
00114 val = max
00115 return val
00116
00117 def pub_data(self, data):
00118 ''' Given data, interpret into Joy message and publish
00119 '''
00120 do_publish = False
00121 self.msg.header.stamp = rospy.Time.now()
00122 for event in data:
00123 control = event[0]
00124
00125
00126
00127
00128 if (control[0] & 0xF0) == 176:
00129 control_id = control[1] | ((control[0] & 0x0F) << 8)
00130
00131 control_axis = self.modes[self.mode]['control_axis']
00132 control_buttons = self.modes[self.mode]['control_buttons']
00133
00134 if control_id in control_axis:
00135 if self.center_axis:
00136 control_val = self.clip(-1.0, 1.0,
00137 float(control[2] - 63) / 63.0)
00138 else:
00139 control_val = self.clip(0.0, 1.0,
00140 float(control[2]) / 127)
00141
00142 axis = control_axis.index(control_id)
00143 self.msg.axes[axis] = control_val
00144 do_publish = True
00145
00146 if control_id in control_buttons:
00147 button = control_buttons.index(control_id)
00148 if control[2] != 0:
00149 self.msg.buttons[button] = 1
00150 else:
00151 self.msg.buttons[button] = 0
00152 do_publish = True
00153
00154
00155 elif control[0] == 79:
00156 self.set_mode(control[1])
00157 do_publish = True
00158
00159 if do_publish:
00160 self.pub.publish(self.msg)