Using Pythonista to query an Xbox controller on the iPad

It seems I need to add another category of posts. Programming. Now, you need to take into account the fact that I am a mechanical engineer and have no serious programming experience or education for that matter, and have only done scripting in Python and Arduino code for my electronics projects. Never take anything I write under this category seriously.

Nevertheless, I had the idea of using the iPad as a remote control for a future robotics project. Having Pythonista installed and knowing that the Xbox controller is supported by iOS, I thought I could research if it has been done before, and how.

It seemed it could be done, as outlined in the Pythonista documentation, but there were no examples available and I have trouble reading documentations as I have a very limited OOP backgound and I probably only wrote like two classes in my entire life.

After a couple of days of messing around, I managed to create an extremely simple example that reads the value of each button when its state changes. My example only uses one button (the left trigger) and can be easily extended to all the other buttons.

No matter how much I googled for an example, I couldn’t find one, so I thought I would publish mine here.

from scene import *

class XboxContr(Scene):
	
	def setup(self):
		self.score_label = LabelNode('0', font=('Avenir Next', 40), position=(self.size.w/2, self.size.h-50), parent=self)
		self.controller_val = 0
		self.changed_key = ''
		self.left_bar = SpriteNode('shp:RoundRect')
		self.left_bar.position = 150, 150
		self.left_bar.size = 50, 150
		self.add_child(self.left_bar)
		
	def update(self):
		self.update_text()
		self.update_bar()
	
	def controller_changed(self, controller, key, value):
		self.controller_val = value
		self.changed_key = key
		
	def update_text(self):
		self.score_label.text = self.changed_key + ' ' + str(self.controller_val)
		
	def update_bar(self):
		if self.changed_key == 'trigger_left':
			self.left_bar.size = 50, self.controller_val*1000 + 150
			self.left_bar.position = 150, self.controller_val*500 + 150
				
run(XboxContr())


#Here is a list of all the buttons and their values. This is returned by the get_controllers() method:
#[{'controller_id': '0x282afca80', 'shoulder_left': 0.0, 'shoulder_right': 0.0, 'dpad': Point(0.00, 0.00), 'button_a': 0.0, 'button_b': 0.0, 'button_x': 0.0, 'button_y': 0.0, 'trigger_left': 0.0, 'trigger_right': 0.0, 'thumb_stick_left': Point(0.00, 0.00), 'thumb_stick_right': Point(0.00, 0.00)}]


Here is the interface it generates. The upper text block changes in real time and shows what button is changing and what value it has. The lower left bar increases in height according to how hard you pull on the left trigger.

I would love to see more finalized interfaces from you guys. Also, let me know if I made some dumb-ass mistakes in the code.

Leave a Reply