Skip to content

Commit

Permalink
add tank
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelliao committed May 7, 2020
1 parent 7827c77 commit 9abe177
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 0 deletions.
13 changes: 13 additions & 0 deletions samples/micropython/tank/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp

// List of extensions which should be recommended for users of this workspace.
"recommendations": [
"lego-education.ev3-micropython"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [
"ms-python.python"
]
}
14 changes: 14 additions & 0 deletions samples/micropython/tank/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Download and Run",
"type": "ev3devBrowser",
"request": "launch",
"program": "/home/robot/${workspaceRootFolderName}/main.py"
}
]
}
6 changes: 6 additions & 0 deletions samples/micropython/tank/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.eol": "\n",
"debug.openDebug": "neverOpen",
"python.linting.enabled": false
}
Binary file added samples/micropython/tank/cannon.wav
Binary file not shown.
47 changes: 47 additions & 0 deletions samples/micropython/tank/devices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# list input devices

class InputDevice():
def __init__(self):
self.name = ''
self.handler = ''

def __str__(self):
return '<Input Device: name=%s, handler=%s>' % (self.name, self.handler)

def setName(self, name):
if len(name) >= 2 and name.startswith('"') and name.endswith('"'):
name = name[1:len(name)-1]
self.name = name

def setHandler(self, handlers):
for handler in handlers.split(' '):
if handler.startswith('event'):
self.handler = handler

def listDevices():
devices = []
with open('/proc/bus/input/devices', 'r') as f:
device = None
while True:
s = f.readline()
if s == '':
break
s = s.strip()
if s == '':
devices.append(device)
device = None
else:
if device is None:
device = InputDevice()
if s.startswith('N: Name='):
device.setName(s[8:])
elif s.startswith('H: Handlers='):
device.setHandler(s[12:])
return devices

def detectJoystick(joystickNames):
for device in listDevices():
for joystickName in joystickNames:
if joystickName in device.name:
return '/dev/input/%s' % device.handler
return None
61 changes: 61 additions & 0 deletions samples/micropython/tank/joystick.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# joystick control:

import struct

# define button code:

BUTTON_A = 305
BUTTON_B = 304
BUTTON_X = 307
BUTTON_Y = 306
BUTTON_PLUS = 313
BUTTON_MINUS = 312
BUTTON_START = 317
BUTTON_HOME = 316

class JoyStick():
def __init__(self, eventFile):
self.eventFile = eventFile
self.buttonHandler = None
self.joyLeftHandler = None
self.joyRightHandler = None

def setButtonHandler(self, buttonHandler):
self.buttonHandler = buttonHandler

def setJoyLeftHandler(self, joyLeftHandler):
self.joyLeftHandler = joyLeftHandler

def setJoyRightHandler(self, joyRightHandler):
self.joyRightHandler = joyRightHandler

def startLoop(self):
FORMAT = 'llHHI'
EVENT_SIZE = struct.calcsize(FORMAT)
with open(self.eventFile, 'rb') as infile:
lx, ly, rx, ry = 0, 0, 0, 0
while True:
event = infile.read(EVENT_SIZE)
_, _, t, c, v = struct.unpack(FORMAT, event)
if t == 1 and v == 1:
# button pressed:
if self.buttonHandler:
if not self.buttonHandler(c):
return
if t == 3:
if c == 0 and self.joyLeftHandler:
# left stick & horizontal:
lx = v - 32768
self.joyLeftHandler(lx, ly)
elif c == 1 and self.joyLeftHandler:
# left stick & vertical:
ly = v - 32768
self.joyLeftHandler(lx, ly)
elif c == 3 and self.joyRightHandler:
# right stick & horizontal:
rx = v - 32768
self.joyRightHandler(rx, ry)
elif c == 4 and self.joyRightHandler:
# right stick & vertical:
ry = v - 32768
self.joyRightHandler(rx, ry)
103 changes: 103 additions & 0 deletions samples/micropython/tank/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/usr/bin/env pybricks-micropython

import struct, threading

from pybricks import ev3brick as brick
from pybricks.ev3devices import (Motor, TouchSensor, ColorSensor, InfraredSensor, UltrasonicSensor, GyroSensor)
from pybricks.parameters import (Port, Stop, Direction, Button, Color, SoundFile, ImageFile, Align)
from pybricks.tools import print, wait, StopWatch
from pybricks.robotics import DriveBase

from devices import detectJoystick
from joystick import JoyStick, BUTTON_A, BUTTON_X

SPEED = 100
STEERING = 90

STATUS_STOPPED = 0
STATUS_FORWARD = 1
STATUS_BACKWARD = 2
STATUS_STEERING = 3

COLORS = (None, Color.GREEN, Color.RED, Color.YELLOW)

class Driver():
def __init__(self, leftMotor, rightMotor, diameter, axle):
self.driver = DriveBase(leftMotor, rightMotor, diameter, axle)
self.x = 0
self.y = 0
self.speed = 0
self.steering = 0

def drive(self, speed, steering):
self.speed = speed
self.steering = steering
if self.speed == 0:
self.driver.stop()
else:
self.driver.drive(self.speed, self.steering)

class Robot():
def __init__(self, leftMotor, rightMotor, topMotor, diameter, axle, maxSpeed=300, maxSteering=180, port=Port.S4):
self.driver = Driver(leftMotor, rightMotor, diameter, axle)
self.cannon = topMotor
self.ultrasonic = UltrasonicSensor(port)
self.speedStep = 32767 // maxSpeed
self.steeringStep = 32767 // maxSteering
self.active = True

def drive(self, x, y):
# map y (-32768 ~ +32767) to speed (+maxSpeed ~ -maxSpeed):
speed = -y // self.speedStep
# map x (-32768 ~ +32767) to steering (-maxSteering ~ +maxSteering):
steering = x // self.steeringStep
self.driver.drive(speed, steering)

def target(self, x):
self.cannon.run(-x // 327)

def fire(self):
brick.sound.file('cannon.wav')

def inactive(self):
self.active = False
self.drive(0, 0)
brick.sound.beep()

def autoStopLoop(robot):
while robot.active:
if robot.ultrasonic.distance() < 200:
robot.drive(0, 0)
wait(100)

def main():
brick.sound.beep()
joystickEvent = detectJoystick(['Controller'])
if joystickEvent:
robot = Robot(Motor(Port.D), Motor(Port.A), Motor(Port.B), 55, 200)
t = threading.Thread(target=autoStopLoop, args=(robot,))
t.start()

def onButtonPressed(code):
if code == BUTTON_X:
robot.inactive()
return False
if code == BUTTON_A:
robot.fire()
return True

def onLeftJoyChanged(x, y):
robot.drive(x, y)

def onRightJoyChanged(x, y):
robot.target(x)

joystick = JoyStick(joystickEvent)
joystick.setButtonHandler(onButtonPressed)
joystick.setJoyLeftHandler(onLeftJoyChanged)
joystick.setJoyRightHandler(onRightJoyChanged)
joystick.startLoop()
else:
brick.sound.beep()

main()

0 comments on commit 9abe177

Please sign in to comment.