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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Marwan Alsabbagh
May 26, 2019
Programming
180
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
ECSアプリログをFireLensでコスト削減しようとしたけど諦めた話 in Fargate×Node.js
akihisaikeda
2
4.3k
Embedded SREと共に達成した会員管理システムのAWS移行 - SRE NEXT 2026 ランチスポンサーセッション
niftycorp
PRO
1
2.4k
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
110
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
140
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
140
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
14
6.8k
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
170
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
460
Prismを使った型安全な暗号化_関数型まつり2026
_fhhmm
0
120
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.4k
使用 Meilisearch 建立新聞搜尋工具
johnroyer
0
140
Featured
See All Featured
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
180
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Ethics towards AI in product and experience design
skipperchong
2
330
The Curse of the Amulet
leimatthew05
2
13k
ラッコキーワード サービス紹介資料
rakko
1
3.9M
The agentic SEO stack - context over prompts
schlessera
0
840
svc-hook: hooking system calls on ARM64 by binary rewriting
retrage
2
330
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
260
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.6k
Skip the Path - Find Your Career Trail
mkilby
1
170
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/