Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Creating Crazy Robotic Librarians
Search
Marwan Alsabbagh
May 26, 2019
Programming
190
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Creating Crazy Robotic Librarians
Marwan Alsabbagh
May 26, 2019
More Decks by Marwan Alsabbagh
See All by Marwan Alsabbagh
PyCon India 2018 - Executing scripts in a few milliseconds with MicroPython
marwano
2
190
Snow globe intruder alert system
marwano
0
510
Executing scripts in a few milliseconds with MicroPython
marwano
1
470
Other Decks in Programming
See All in Programming
仕様書を書く前にハーネスを作る - Agent Native開発は「探索を速く、判定を固く」
gotalab555
4
1.6k
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
520
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
320
属人化した知識を、 AIが辿れる地図にする
pkshadeck
PRO
1
160
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
610
React本体のコードリーディング
high_g_engineer
1
140
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
590
20260722_microCMSで考える、AI時代のコンテンツ運用設計
yosh1
0
380
Claude Code全社展開のためにやったことn選~プラグイン302個・コミッター271人を支えるために~
kenchan
5
1.5k
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
360
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
880
数百円から始めるRuby電子工作
tarosay
0
140
Featured
See All Featured
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
330
The Pragmatic Product Professional
lauravandoore
37
7.4k
エンジニアに許された特別な時間の終わり
watany
108
250k
A designer walks into a library…
pauljervisheath
211
24k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.7k
Automating Front-end Workflow
addyosmani
1369
210k
Prompt Engineering for Job Search
mfonobong
0
400
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
380
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
230
Claude Code のすすめ
schroneko
67
230k
Side Projects
sachag
455
43k
Amusing Abliteration
ianozsvald
1
240
Transcript
Creating Crazy Robotic Librarians Marwan AlSabbagh
1. Building 2. Teaching 3. Controlling Robots 4. Pushing Books
Outline
1. Building
Boards Adafruit CRICKIT HAT $35 Raspberry Pi 3 Model B+
$35 AA Battery Holder $3
Robot Chassis Kit Complete Kit $25 (separate DC motors $3
each)
Servo Standard servo - TowerPro SG-5010 $12.00
Exploded View
2. Teaching
Angles
Crickit API >>> from adafruit_crickit import crickit >>> # DC
motor 1 full speed, half speed, off, reverse >>> crickit.dc_motor_1.throttle = 1 >>> crickit.dc_motor_1.throttle = 0.5 >>> crickit.dc_motor_1.throttle = 0 >>> crickit.dc_motor_1.throttle = -1 >>> # servo configure, set angle to 0 and 90 degrees >>> crickit.servo_1.actuation_range = 140 >>> crickit.servo_1.angle = 0 >>> crickit.servo_1.angle = 90 >>> # check state of capacitive touch >>> crickit.touch_1.value False
Teach API >>> from teach import r >>> # DC
motor 1 full speed, half speed, off, reverse >>> r.wheel = 1 >>> r.wheel = 0.5 >>> r.wheel = 0 >>> r.wheel = -1 >>> # servo set angle to 0 and 90 degrees >>> r.arm = 0 >>> r.arm = 90 >>> # check state of capacitive touch >>> r.touch False
Kid’s REPL Session >>> r.wheel =1 >>> r.wheel =0 >>>
1+1 2 >>> 365*7 2555 >>> 365*41 14965 >>> r.arm =0 >>> r.arm =30 >>> r.arm =90 >>> r.arm =140 >>> r.wheel =-1 >>> r.wheel =0.5 >>> r.touch False >>> r.touch True (robo) pi@raspberrypi:~/tmp $ date Fri 17 May 09:20:01 BST 2019 (robo) pi@raspberrypi:~/tmp $ whoami pi (robo) pi@raspberrypi:~/tmp $ poweroff Connection to robopi closed by remote host. Connection to robopi closed.
3. Controlling Robots
Setup • Install Raspbian on Raspberry Pi • Enable ssh
and I2C in Raspbian • pip install adafruit-circuitpython-crickit tornado
Remote Control 1. Forward 2. Backward 3. Stop 4. Right
5. Left 6. Raise Hand 7. Lower Hand
Button Overlay
App Structure ├── conf.py ├── motors.py ├── server.py ├── static
│ ├── main.css │ └── remote.jpg └── templates └── main.html
main.html <!DOCTYPE HTML> <html lang="en"> <head> <title>Robot Remote</title> <link rel="stylesheet"
href="{{ static_url('main.css') }}"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width"> </head> <body> <h1>Robot Remote</h1> <div class="container"> <img src="{{ static_url('remote.jpg') }}" alt="ui"> <form method=post> <input type=submit name=action value=forward> <input type=submit name=action value=right> <input type=submit name=action value=left> <input type=submit name=action value=back> <input type=submit name=action value=stop> <input type=submit name=action value=raise> <input type=submit name=action value=lower> </form> </div> </body> </html>
main.css h1 { margin: 0px; color: white; text-align:center; padding: 20px;
width: 600px; background: linear-gradient(MediumTurquoise, BlueViolet); } .container { position: relative; } input { position: absolute; opacity: 0.0; } input[value="forward"] { left: 240px; top: 0px; width:150px; height:220px; }
conf.py from os.path import dirname import os PORT = 8080
APP_SETTINGS = dict( debug=bool(os.environ.get('APP_DEBUG')), static_path=(dirname(__file__) + '/static'), template_path=(dirname(__file__) + '/templates'), ) SERVO_MAX_ANGLE = 140 DC_SPEED = 1.0 TURN_DURATION = 0.2 DIRECTION = dict( forward=[1, 1], right=[1, 0], left=[0, 1], back=[-1, -1], stop=[0, 0], ) ANGLES = {} ANGLES['raise'] = SERVO_MAX_ANGLE ANGLES['lower'] = SERVO_MAX_ANGLE – 90
server.py from tornado.web import RequestHandler, Application from tornado.ioloop import IOLoop
from tornado.log import enable_pretty_logging from .conf import PORT, APP_SETTINGS from .motors import move, init_servo class MainHandler(RequestHandler): def get(self): self.render('main.html') def post(self): move(self.get_body_argument('action')) self.redirect('/') def main(): init_servo() enable_pretty_logging() app = Application([('/', MainHandler)], **APP_SETTINGS) app.listen(PORT) IOLoop.current().start() if __name__ == "__main__": main()
motors.py from adafruit_crickit import crickit import time from .conf import
SERVO_MAX_ANGLE, DC_SPEED, TURN_DURATION, DIRECTION, ANGLES def move_servo(action): crickit.servo_1.angle = ANGLES[action] def move_dc(action): direction = DIRECTION[action] crickit.dc_motor_1.throttle = direction[0] * DC_SPEED crickit.dc_motor_2.throttle = direction[1] * DC_SPEED if action in ['right', 'left']: time.sleep(TURN_DURATION) crickit.dc_motor_1.throttle = 0 crickit.dc_motor_2.throttle = 0 def move(action): if action in ['raise', 'lower']: move_servo(action) else: move_dc(action) def init_servo(): crickit.servo_1.actuation_range = SERVO_MAX_ANGLE
Robot Challenge
4. Pushing Books
Robotic Librarian 1. Push specific book 2. Push random book
3. Push all books
Wooden Frame
None
App Structure ├── conf.py ├── push.py ├── server.py └── templates
└── main.html
conf.py from os.path import dirname, expanduser import os PORT =
8080 APP_SETTINGS = dict( debug=bool(os.environ.get('APP_DEBUG')), static_path=expanduser('~/bookpusher_images'), template_path=(dirname(__file__) + '/templates'), ) BOOKS = list(range(1, 7)) DC = dict( speed=0.8, step_duration=0.38, forward=1, back=-1, ) SERVO_MAX_ANGLE = 140 HAND = dict( up=SERVO_MAX_ANGLE, down=SERVO_MAX_ANGLE - 90, delay=0.7, )
server.py import random from tornado.web import RequestHandler, Application from tornado.ioloop
import IOLoop from .conf import PORT, APP_SETTINGS, BOOKS from .push import init_servo, push_book, push_all class MainHandler(RequestHandler): def get(self): self.render('main.html', books=BOOKS) def post(self): book = self.get_body_argument('book') if book == 'all': push_all() else: book = random.choice(BOOKS) if book == 'random' else book push_book(int(book)) self.redirect('/') def main(): init_servo() app = Application([('/', MainHandler)], **APP_SETTINGS) app.listen(PORT) IOLoop.current().start()
from adafruit_crickit import crickit import time, random from .conf import
BOOKS, DC, SERVO_MAX_ANGLE, HAND def move_dc(direction, steps): crickit.dc_motor_1.throttle = direction * DC['speed'] crickit.dc_motor_2.throttle = direction * DC['speed'] time.sleep(DC['step_duration'] * steps) crickit.dc_motor_1.throttle = 0 crickit.dc_motor_2.throttle = 0 def swipe_hand(): crickit.servo_1.angle = HAND['down'] time.sleep(HAND['delay']) crickit.servo_1.angle = HAND['up'] time.sleep(HAND['delay']) def push_book(position): if position > 1: move_dc(DC['forward'], position - 1) swipe_hand() move_dc(DC['back'], position) def push_all(): books = list(BOOKS) random.shuffle(books) for book in books: push_book(book) def init_servo(): crickit.servo_1.actuation_range = SERVO_MAX_ANGLE push.py
main.html <!DOCTYPE HTML> <html lang="en"> <head> <title>Robotic Librarian</title> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width"> </head> <body> <h1>Robotic Librarian</h1> <form method=post> <button type=submit name=book value=random>Random</button> <button type=submit name=book value=all>All Books(Crazy Mode)</button><br/><br/> {% for book in books %} <button type=submit name=book value={{ book }}> <img src="{{ static_url('book%s.jpg' % book) }}" alt="book{{ book }}"> </button> {% end %} </form> </body> </html>
None
None
The End https://marwano.com/