diff --git a/README.md b/README.md index 12a9352c..0e149d09 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ Python 3 教程 ============ + +[Python 3 教程](https://www.liaoxuefeng.com/wiki/1016959663602400) diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 00000000..fac3311c --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +learn-python3.itranswarp.com \ No newline at end of file diff --git a/docs/pyscript_plugin.js b/docs/pyscript_plugin.js new file mode 100644 index 00000000..39e7bae7 --- /dev/null +++ b/docs/pyscript_plugin.js @@ -0,0 +1,31 @@ +export default class LearnPython3Plugin { + afterStartup(runtime) { + console.log('[plugin] pyscript startup.'); + window.__pyscript_ready__ = true; + } + + afterPyScriptExec(opt) { + let + tag = opt.pyScriptTag, + outputId = tag.getAttribute('output'), + $btn = $('button[outputId=' + outputId + ']'), + $i = $btn.find('i'); + $i.removeClass('uk-icon-spinner'); + $i.removeClass('uk-icon-spin'); + $btn.removeAttr('disabled'); + let err = $(tag).find('pre.py-error').html(); + if (err) { + let + $out = $('#' + outputId), + s = $out.html(); + s = s + err.replaceAll(' ', ' '); + $out.html(s); + $out.addClass('uk-alert-danger'); + } + } + + onUserError(err) { + console.log('Error >>>'); + console.error(err); + } +} diff --git a/samples/advance/do_iter.py b/samples/advance/do_iter.py index 99ba3702..0ded6af4 100755 --- a/samples/advance/do_iter.py +++ b/samples/advance/do_iter.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from collections import Iterable, Iterator +from collections.abc import Iterable, Iterator def g(): yield 1 diff --git a/samples/basic/do_match.py b/samples/basic/do_match.py new file mode 100644 index 00000000..b14fe51f --- /dev/null +++ b/samples/basic/do_match.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# 简单匹配: +print('-- simple match --') + +score = 'A' + +match score: + case 'A': + print('score is A.') + case 'B': + print('score is B.') + case 'C': + print('score is C.') + case _: + print('score is ???.') + +# 复杂匹配: +print('-- complex match --') + +age = 15 + +match age: + case x if x < 10: + print('< 10 years old.') + case 10: + print('10 years old.') + case 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18: + print('11~18 years old.') + case 19: + print('19 years old.') + case _: + print('not sure.') + +# 列表匹配: +print('-- match list --') + +args = ['gcc', 'hello.c', 'world.c'] +# args = ['clean'] +# args = ['gcc'] + +match args: + # 如果仅出现gcc,报错: + case ['gcc']: + print('gcc: missing source file(s).') + # 出现gcc,且至少指定了一个文件: + case ['gcc', file1, *files]: + print('gcc compile: ' + file1 + ', ' + ', '.join(files)) + # 仅出现clean: + case ['clean']: + print('clean') + case _: + print('invalid command.') diff --git a/samples/basic/hello.py b/samples/basic/hello/hello.py similarity index 100% rename from samples/basic/hello.py rename to samples/basic/hello/hello.py diff --git a/samples/commonlib/use_chainmap.py b/samples/commonlib/use_chainmap.py new file mode 100755 index 00000000..406e29e0 --- /dev/null +++ b/samples/commonlib/use_chainmap.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +from collections import ChainMap +import os, argparse + +defaults = { + 'color': 'red', + 'user': 'guest' +} + +parser = argparse.ArgumentParser() +parser.add_argument('-u', '--user') +parser.add_argument('-c', '--color') +namespace = parser.parse_args() +command_line_args = { k: v for k, v in vars(namespace).items() if v } + +combined = ChainMap(command_line_args, os.environ, defaults) +print('color=%s' % combined['color']) +print('user=%s' % combined['user']) diff --git a/samples/function/recur.py b/samples/function/recur.py index 18ec40ae..e3f66076 100755 --- a/samples/function/recur.py +++ b/samples/function/recur.py @@ -16,9 +16,9 @@ def fact(n): def move(n, a, b, c): if n == 1: print('move', a, '-->', c) - return - move(n-1, a, c, b) - print('move', a, '-->', c) - move(n-1, b, a, c) + else: + move(n-1, a, c, b) + move(1, a, b, c) + move(n-1, b, a, c) move(4, 'A', 'B', 'C') diff --git a/samples/gui/turtle/rect.py b/samples/gui/turtle/rect.py new file mode 100644 index 00000000..9bd0e801 --- /dev/null +++ b/samples/gui/turtle/rect.py @@ -0,0 +1,26 @@ +# 导入turtle包的所有内容: +from turtle import * + +# 设置笔刷宽度: +width(4) + +# 前进: +forward(200) +# 右转90度: +right(90) + +# 笔刷颜色: +pencolor('red') +forward(100) +right(90) + +pencolor('green') +forward(200) +right(90) + +pencolor('blue') +forward(100) +right(90) + +# 调用done()使得窗口等待被关闭,否则将立刻关闭窗口: +done() diff --git a/samples/gui/turtle/stars.py b/samples/gui/turtle/stars.py new file mode 100644 index 00000000..3a7db272 --- /dev/null +++ b/samples/gui/turtle/stars.py @@ -0,0 +1,16 @@ +from turtle import * + +def drawStar(x, y): + pu() + goto(x, y) + pd() + # set heading: 0 + seth(0) + for i in range(5): + fd(40) + rt(144) + +for x in range(0, 250, 50): + drawStar(x, 0) + +done() diff --git a/samples/gui/turtle/tree.py b/samples/gui/turtle/tree.py new file mode 100644 index 00000000..43670e39 --- /dev/null +++ b/samples/gui/turtle/tree.py @@ -0,0 +1,59 @@ +from turtle import * + +colormode(255) + +lt(90) + +lv = 14 +l = 120 +s = 45 + +width(lv) + +r = 0 +g = 0 +b = 0 +pencolor(r, g, b) + +penup() +bk(l) +pendown() +fd(l) + +def draw_tree(l, level): + global r, g, b + # save the current pen width + w = width() + + # narrow the pen width + width(w * 3.0 / 4.0) + # set color: + r = r + 1 + g = g + 2 + b = b + 3 + pencolor(r % 200, g % 200, b % 200) + + l = 3.0 / 4.0 * l + + lt(s) + fd(l) + + if level < lv: + draw_tree(l, level + 1) + bk(l) + rt(2 * s) + fd(l) + + if level < lv: + draw_tree(l, level + 1) + bk(l) + lt(s) + + # restore the previous pen width + width(w) + +speed("fastest") + +draw_tree(l, 4) + +done() diff --git a/samples/micropython/hellorobot/.vscode/extensions.json b/samples/micropython/hellorobot/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/hellorobot/.vscode/extensions.json @@ -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" + ] +} \ No newline at end of file diff --git a/samples/micropython/hellorobot/.vscode/launch.json b/samples/micropython/hellorobot/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/hellorobot/.vscode/launch.json @@ -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" + } + ] +} diff --git a/samples/micropython/hellorobot/.vscode/settings.json b/samples/micropython/hellorobot/.vscode/settings.json new file mode 100644 index 00000000..37c9a5dd --- /dev/null +++ b/samples/micropython/hellorobot/.vscode/settings.json @@ -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 +} diff --git a/samples/micropython/hellorobot/main.py b/samples/micropython/hellorobot/main.py new file mode 100644 index 00000000..d51e43bd --- /dev/null +++ b/samples/micropython/hellorobot/main.py @@ -0,0 +1,14 @@ +#!/usr/bin/env pybricks-micropython + +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 + +# Write your program here +brick.sound.beep() +# 输出到控制台: +print('Hello, robot!') +# 输出到EV3屏幕: +brick.display.text('Hello, robot!') diff --git a/samples/micropython/rccar/.vscode/extensions.json b/samples/micropython/rccar/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/rccar/.vscode/extensions.json @@ -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" + ] +} \ No newline at end of file diff --git a/samples/micropython/rccar/.vscode/launch.json b/samples/micropython/rccar/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/rccar/.vscode/launch.json @@ -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" + } + ] +} diff --git a/samples/micropython/rccar/.vscode/settings.json b/samples/micropython/rccar/.vscode/settings.json new file mode 100644 index 00000000..37c9a5dd --- /dev/null +++ b/samples/micropython/rccar/.vscode/settings.json @@ -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 +} diff --git a/samples/micropython/rccar/devices.py b/samples/micropython/rccar/devices.py new file mode 100644 index 00000000..0c6c133c --- /dev/null +++ b/samples/micropython/rccar/devices.py @@ -0,0 +1,47 @@ +# list input devices + +class InputDevice(): + def __init__(self): + self.name = '' + self.handler = '' + + def __str__(self): + return '' % (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 diff --git a/samples/micropython/rccar/main.py b/samples/micropython/rccar/main.py new file mode 100644 index 00000000..cf18c927 --- /dev/null +++ b/samples/micropython/rccar/main.py @@ -0,0 +1,100 @@ +#!/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 + +class Robot(): + def __init__(self): + self.motor = Motor(Port.B) + self.ultrasonic = UltrasonicSensor(Port.S4) + self.active = True + self.speed = 0 + self.colors = [None, Color.GREEN, Color.YELLOW, Color.RED] + + def setSpeed(self, acc): + if acc < 0: + self.speed = max(-3, self.speed - 1) + elif acc > 0: + self.speed = min(3, self.speed + 1) + else: + self.speed = 0 + if self.speed != 0: + self.motor.run(self.speed * 90) + else: + self.motor.stop() + brick.light(self.colors[abs(self.speed)]) + + def inactive(self): + self.active = False + self.setSpeed(0) + brick.sound.beep() + +def autoStopLoop(robot): + while robot.active: + if robot.speed > 0 and robot.ultrasonic.distance() < 200: + robot.setSpeed(0) + wait(100) + +def joystickLoop(robot, eventFile): + FORMAT = 'llHHI' + EVENT_SIZE = struct.calcsize(FORMAT) + with open(eventFile, 'rb') as infile: + while True: + event = infile.read(EVENT_SIZE) + _, _, t, c, v = struct.unpack(FORMAT, event) + # button A, B: + if t == 1 and v == 1: + if c == 305: + # press A: + robot.setSpeed(1) + elif c == 304: + # press B: + robot.setSpeed(-1) + elif c == 307: + # press X: + return robot.inactive() + elif t == 3: + if c == 1: + # Left stick & vertical: + speed = 0 + if v < 32768: + # up: + speed = 1 + elif v > 32768: + # down: + speed = -1 + robot.setSpeed(speed) + +def buttonLoop(robot): + while True: + if not any(brick.buttons()): + wait(10) + else: + if Button.LEFT in brick.buttons(): + robot.setSpeed(-1) + elif Button.RIGHT in brick.buttons(): + robot.setSpeed(1) + elif Button.CENTER in brick.buttons(): + robot.setSpeed(0) + elif Button.UP in brick.buttons(): + return robot.inactive() + wait(500) + +def main(): + brick.sound.beep() + joystickEvent = detectJoystick(['Controller']) + robot = Robot() + t = threading.Thread(target=autoStopLoop, args=(robot,)) + t.start() + if joystickEvent: + joystickLoop(robot, joystickEvent) + else: + buttonLoop(robot) + +main() diff --git a/samples/micropython/smallcar/.vscode/extensions.json b/samples/micropython/smallcar/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/smallcar/.vscode/extensions.json @@ -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" + ] +} \ No newline at end of file diff --git a/samples/micropython/smallcar/.vscode/launch.json b/samples/micropython/smallcar/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/smallcar/.vscode/launch.json @@ -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" + } + ] +} diff --git a/samples/micropython/smallcar/.vscode/settings.json b/samples/micropython/smallcar/.vscode/settings.json new file mode 100644 index 00000000..a9e3a557 --- /dev/null +++ b/samples/micropython/smallcar/.vscode/settings.json @@ -0,0 +1,7 @@ +// Place your settings in this file to overwrite default and user settings. +{ + "files.eol": "\n", + "debug.openDebug": "neverOpen", + "python.linting.enabled": false, + "python.formatting.provider": "autopep8" +} diff --git a/samples/micropython/smallcar/main.py b/samples/micropython/smallcar/main.py new file mode 100644 index 00000000..9ddd7aec --- /dev/null +++ b/samples/micropython/smallcar/main.py @@ -0,0 +1,51 @@ +#!/usr/bin/env pybricks-micropython + +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 + +# Write your program here + +motor = Motor(Port.B) +ultrasonic = UltrasonicSensor(Port.S4) + +brick.sound.beep() +brick.light(None) + +speed = 0 +colors = [None, Color.GREEN, Color.YELLOW, Color.RED] + +def setSpeed(acc): + global speed + if acc < 0: + speed = max(0, speed - 1) + elif acc > 0: + speed = min(3, speed + 1) + else: + speed = 0 + if speed > 0: + motor.run(speed * 90) + else: + motor.stop() + brick.light(colors[speed]) + +while True: + if not any(brick.buttons()): + wait(10) + else: + if Button.LEFT in brick.buttons(): + setSpeed(-1) + elif Button.RIGHT in brick.buttons(): + setSpeed(1) + elif Button.CENTER in brick.buttons(): + setSpeed(0) + elif Button.UP in brick.buttons(): + setSpeed(0) + break + wait(500) + if ultrasonic.distance() < 200: + setSpeed(0) + +brick.sound.beep() diff --git a/samples/micropython/tank/.vscode/extensions.json b/samples/micropython/tank/.vscode/extensions.json new file mode 100644 index 00000000..f8f1a440 --- /dev/null +++ b/samples/micropython/tank/.vscode/extensions.json @@ -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" + ] +} \ No newline at end of file diff --git a/samples/micropython/tank/.vscode/launch.json b/samples/micropython/tank/.vscode/launch.json new file mode 100644 index 00000000..af12883d --- /dev/null +++ b/samples/micropython/tank/.vscode/launch.json @@ -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" + } + ] +} diff --git a/samples/micropython/tank/.vscode/settings.json b/samples/micropython/tank/.vscode/settings.json new file mode 100644 index 00000000..37c9a5dd --- /dev/null +++ b/samples/micropython/tank/.vscode/settings.json @@ -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 +} diff --git a/samples/micropython/tank/cannon.wav b/samples/micropython/tank/cannon.wav new file mode 100644 index 00000000..ee0d0102 Binary files /dev/null and b/samples/micropython/tank/cannon.wav differ diff --git a/samples/micropython/tank/devices.py b/samples/micropython/tank/devices.py new file mode 100644 index 00000000..0c6c133c --- /dev/null +++ b/samples/micropython/tank/devices.py @@ -0,0 +1,47 @@ +# list input devices + +class InputDevice(): + def __init__(self): + self.name = '' + self.handler = '' + + def __str__(self): + return '' % (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 diff --git a/samples/micropython/tank/joystick.py b/samples/micropython/tank/joystick.py new file mode 100644 index 00000000..0379051c --- /dev/null +++ b/samples/micropython/tank/joystick.py @@ -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) diff --git a/samples/micropython/tank/main.py b/samples/micropython/tank/main.py new file mode 100644 index 00000000..efb082da --- /dev/null +++ b/samples/micropython/tank/main.py @@ -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() diff --git a/samples/multitask/task_worker.py b/samples/multitask/task_worker.py index a5d0097e..8155a2b6 100755 --- a/samples/multitask/task_worker.py +++ b/samples/multitask/task_worker.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import time, sys, queue +import time, sys from multiprocessing.managers import BaseManager # 创建类似的QueueManager: diff --git a/teach/README.md b/teach/README.md deleted file mode 100644 index d5cb2ae8..00000000 --- a/teach/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# 安装Python学习助手 - -首先确认Python 3.4已安装。 - -# 下载learning.py - -下载地址: - -[https://raw.githubusercontent.com/michaelliao/learn-python3/master/teach/learning.py](https://raw.githubusercontent.com/michaelliao/learn-python3/master/teach/learning.py) - -(右键 - 另存为) - -放到某个目录,例如`C:\Work`下。 - -# 运行命令: - -切换到`learning.py`所在目录,运行: - -``` -C:\Work> python learning.py -``` - -如果看到`Ready for Python code on port 39093...`表示运行成功,不要关闭命令行窗口,最小化放到后台运行即可。 - -![run-learning.py.png](https://raw.githubusercontent.com/michaelliao/learn-python3/master/teach/run-learning.py.png) diff --git a/teach/learning.py b/teach/learning.py deleted file mode 100755 index 7222f3a6..00000000 --- a/teach/learning.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -r''' -learning.py - -A Python 3 tutorial from http://www.liaoxuefeng.com - -Usage: - -python3 learning.py -''' - -import sys - -def check_version(): - v = sys.version_info - if v.major == 3 and v.minor >= 4: - return True - print('Your current python is %d.%d. Please use Python 3.4.' % (v.major, v.minor)) - return False - -if not check_version(): - exit(1) - -import os, io, json, subprocess, tempfile -from urllib import parse -from wsgiref.simple_server import make_server - -EXEC = sys.executable -PORT = 39093 -HOST = 'local.liaoxuefeng.com:%d' % PORT -TEMP = tempfile.mkdtemp(suffix='_py', prefix='learn_python_') -INDEX = 0 - -def main(): - httpd = make_server('127.0.0.1', PORT, application) - print('Ready for Python code on port %d...' % PORT) - httpd.serve_forever() - -def get_name(): - global INDEX - INDEX = INDEX + 1 - return 'test_%d' % INDEX - -def write_py(name, code): - fpath = os.path.join(TEMP, '%s.py' % name) - with open(fpath, 'w', encoding='utf-8') as f: - f.write(code) - print('Code wrote to: %s' % fpath) - return fpath - -def decode(s): - try: - return s.decode('utf-8') - except UnicodeDecodeError: - return s.decode('gbk') - -def application(environ, start_response): - host = environ.get('HTTP_HOST') - method = environ.get('REQUEST_METHOD') - path = environ.get('PATH_INFO') - if method == 'GET' and path == '/': - start_response('200 OK', [('Content-Type', 'text/html')]) - return [b'Learning Python

'] - if method == 'GET' and path == '/env': - start_response('200 OK', [('Content-Type', 'text/html')]) - L = [b'ENV'] - for k, v in environ.items(): - p = '

%s = %s' % (k, str(v)) - L.append(p.encode('utf-8')) - L.append(b'') - return L - if host != HOST or method != 'POST' or path != '/run' or not environ.get('CONTENT_TYPE', '').lower().startswith('application/x-www-form-urlencoded'): - start_response('400 Bad Request', [('Content-Type', 'application/json')]) - return [b'{"error":"bad_request"}'] - s = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) - qs = parse.parse_qs(s.decode('utf-8')) - if not 'code' in qs: - start_response('400 Bad Request', [('Content-Type', 'application/json')]) - return [b'{"error":"invalid_params"}'] - name = qs['name'][0] if 'name' in qs else get_name() - code = qs['code'][0] - headers = [('Content-Type', 'application/json')] - origin = environ.get('HTTP_ORIGIN', '') - if origin.find('.liaoxuefeng.com') == -1: - start_response('400 Bad Request', [('Content-Type', 'application/json')]) - return [b'{"error":"invalid_origin"}'] - headers.append(('Access-Control-Allow-Origin', origin)) - start_response('200 OK', headers) - r = dict() - try: - fpath = write_py(name, code) - print('Execute: %s %s' % (EXEC, fpath)) - r['output'] = decode(subprocess.check_output([EXEC, fpath], stderr=subprocess.STDOUT, timeout=5)) - except subprocess.CalledProcessError as e: - r = dict(error='Exception', output=decode(e.output)) - except subprocess.TimeoutExpired as e: - r = dict(error='Timeout', output='执行超时') - except subprocess.CalledProcessError as e: - r = dict(error='Error', output='执行错误') - print('Execute done.') - return [json.dumps(r).encode('utf-8')] - -if __name__ == '__main__': - main() diff --git a/teach/run-learning.py.png b/teach/run-learning.py.png deleted file mode 100644 index d9491a95..00000000 Binary files a/teach/run-learning.py.png and /dev/null differ