天天看點

為Scratch3.0設計的插件系統(下篇)設計原則與初衷插件系統功能描述思路架構圖why and why not

原文網址:https://blog.just4fun.site/scratch3-plugin-2.html

Date 一 26 三月 2018 By wuwenjie Category 少兒程式設計. Tags scratch

Imagine, Program, Share

在上篇文章裡,關于Scratch3.0如何與外部硬體(裝置/玩具)通信,我們梳理了社群裡的常見做法

在這篇文章中,準備寫寫我的架構設計,文中會給出架構圖,解釋這樣設計的原因,以及不采用目前主流做法的原因。

設計原則與初衷

程式設計是僞裝成藝術的科學

近來在程式設計方面,對我影響最深的一本書是《ROS機器人程式設計實踐》。在這本書裡,我們看到通過遵循Unix哲學可以建構出何等強大、靈活而簡單的系統(Unix哲學在《Unix程式設計藝術》中被闡述得很精彩)

當然,ROS的

簡單

,是指它在面對所處理的問題時,已盡可能地簡單,這個系統本身還是有一定複雜度的。當我們在說《哲學問題》把哲學闡述如此清晰、簡單時,其中的簡單也是這個意思。你不能指望一本書能把N-S方程的推導過程講解得和天線寶寶的情節一樣簡單。如果有作者聲稱他能,要麼他是騙子,要麼他是瘋子,要麼他是伯特蘭·羅素

Unix哲學裡鼓勵如何建構一個系統呢?

我很喜歡zguide(zguide是ZeroMQ的教材,寫得幾乎和ZeroMQ這個項目一樣出色)中的這個闡述

The physics of software is not algorithms, data structures, languages and abstractions. These are just tools we make, use, throw away. The real physics of software is the physics of people--specifically, our limitations when it comes to complexity, and our desire to work together to solve large problems in pieces. This is the science of programming: make building blocks that people can understand and use easily, and people will work together to solve the very largest problems.

作為社會成員的我們,在遇到一個高度複雜的問題時,我們會群策群力,分工合作,将問題拆分為若幹個部分,一起解決。這裡就展現了程式設計的科學:建立一組小型的構模組化塊,讓人們易于了解和使用,那麼大家就會一起用它來解決問題。

想想你的Unix工具箱中的grep/find/awk/sed組合起來時何等地強大。當一堆的小工具能彼此溝通時,事情就變得有趣了。

和ROS一樣,我們鼓勵社群的參與,我們想設計一個開放的系統,允許更多的插件加入進來,允許你去連接配接更多有趣的裝置,在這個架構中鼓勵人們重用社群的經驗,在别人的基礎上工作,也友善人們将自己的工作分享給社群。

我們不想建構一個封閉、精緻且龐大的系統。

插件系統功能描述

  • 連接配接scratch3.0與來自實體世界的各種硬體及開放系統
  • 可以配合scratch3.0官方網站使用。自行架設的scratch3.0網站如果與官方插件系統相容,那麼你也能直接使用這套插件系統。就是說等scratch3.0釋出之後,任何采用官方擴充機制的網站,都能使用這套插件系統,而無須hack核心源碼
  • 允許你為系統寫擴充插件,将任何你能操控的系統接入Scratch3.0中
  • 當然如果你有興趣,甚至可以把這套系統接入Scratch3.0之外的地方,比如你想把它接入Blockly或者node-red中,插件系統雖然最初是為Scratch3.0而做,但Scratch3.0并不特殊,它僅僅是一個消息訂閱者和釋出者而已

思路

項目的架構思路主要來自ROS(Robot Operating System)。ROS是個複雜系統,當今世上有趣和複雜機器人大多都運作着ROS,從國際空間站的R2機器人到一些路上自動駕駛的汽車。我覺得ROS系統中處理的很多問題,在使用Scratch驅動外部裝置/機器人時也會遇到,尤其當你不甘于隻是簡單地灌入代碼、想做出互動性更好的機器人時(比如Cozmo)。這些問題包括:

  • 傳感器的資料釋出機制;
  • 服務(service)與動作(action)的區分,以及各自處理的問題;
  • 如何重用消息結構,讓一套積木塊能将相同的語義傳遞給不同的硬體,隻需調整最末端的驅動代碼便可控制天上飛的、地上走的、水裡遊的。
  • ...

Cozmo顯然就是利用這些概念建構了令人驚歎的操作體驗

我最近在建構一個叫ROLS(Robot Operating Lite System)的項目,從名字可以看出,這個項目是想做個輕量級的ROS,目前隻開了個坑:ROLS。在github上建立項目的動機常常是,想到了一個好名字,不知道你們有沒有這種情況

ROS的作者也在重寫這個項目,如他自己在ROS2.0的設計文檔中說的其實ROS的核心是一個

匿名的釋出-訂閱中間件系統

本文為Scratch3.0設計的插件系統本質上便是一個匿名的釋出-訂閱中間件系統,元件之間通過消息彼此溝通。系統中所有的節點都對等,即便是Scratch3.0也不特殊。

至于為這個系統提供更多好用的小工具(諸如roscore、rosrun、rostopic等),我會在ROLS中陸續折騰出來它們的輕量級替代品

架構圖

為Scratch3.0設計的插件系統(下篇)設計原則與初衷插件系統功能描述思路架構圖why and why not

我們自上往下看。

首先看Scratch3.0部分。在Scratch3.0中,我們需要寫一個js插件,這個插件就像特洛伊木馬,作為我們的

内應

,之後它将負責與外部溝通。如果你對這部分不熟悉,應該先去看看官方文檔:Scratch 3.0 Extensions Specification

這部分是Scratch3.0的原生擴充機制。目前官方已經完成了好幾個擴充,有興趣的話,可以自行閱讀源碼。其中wedo2的擴充很值得一讀。

你在Scratch3.0中寫js擴充時,除了要定義出積木塊的樣式之外,還需要定義出opcode(語義)和它的具體實作,這部分将在vm中執行,我們參考了wedo2的機制,采用 socketio來傳遞消息(當然你也可以直接使用websocket)。

插件系統中有一個websocket server(這個架構很像jupyter),與vm進行雙向通信。

websocket server采用zeromq來sub/pub消息

而每個硬體被程式代理,代理程式也采用zeromq來sub/pub消息

系統看去有些啰嗦,比如代理程式似乎是不必要的。如果你為scratch3.0寫過插件,你可能會想,我們為何不把websocket server視為vm的延伸,如果vm的概念延伸到實體機器上,不就具備了和硬體互動的能力!(已經從浏覽器蔓延到了系統程序中)那麼為何還需要多一層硬體代理。原因是為了建構一個匿名的釋出-訂閱系統,以便解耦和重用。

具體實作

上圖是一張語言無關的架構圖,你可以用任何你喜歡的語言去實作它,下邊說說我們目前自己的實作(這部分由@izuo和我一起實作):

為Scratch3.0設計的插件系統(下篇)設計原則與初衷插件系統功能描述思路架構圖why and why not

在少兒程式設計領域,microbit,scratch,Cozmo是我最喜歡的三個項目,是以我們第一步先做了microbit的scratch插件 ,下一步計劃是把cozmo也帶入scratch中

相比于js,我更偏好python,是以在具體實作上,我沒有選擇electron,而是使用python來建構,之後使用pyinstaller打包分發到各個平台 (目前我們完成了mac系統和win10系統的打包,更多的環境還在陸續添加,因為scratch3.0正式釋出還遠,是以平台相容這塊,倒也不急,但會考慮服務于國内教育環境(比如對windows 32位系統的相容))

why and why not

原本想回答一些why的問題,這些問題我和@izuo讨論了許多,但一時半會可能也不好說清,天色已晚,今天寫幾個對why not的思考,就該睡了。

why not Web Bluetooth

Web Bluetooth個很棒的方案,我們目前正在這塊做一些實驗,Web Bluetooth讓vm可以直接與硬體互動!

這個方案另一個好處是對移動端友好,安卓中你甚至隻需要浏覽器,就能控制硬體,ios中,浏覽器目前不支援 Web Bluetooth,你需要包裝成app。apple正在成為過去的微軟

不過并非所有人都喜歡藍牙,也不是所有場景都适合藍牙,如果我們想把cozmo和microbit接入scratch,我們就做不到(microbit通過一些方式可能能做到,不過會有一些其他問題)

要把bb8接入,倒是做得到的,bb8支援ble(Web Bluetooth需要ble)

此外值得一提的是,來自國内的mCookie用到了Web Bluetooth的政策.此外有趣的是他們用了NW.js而不是electron

why not chrome serial

這也是個有趣方案,我們也在關注和實驗

這個方案對chrome的版本要求比Web Bluetooth低,對老機器支援比較好,不過需要安裝浏覽器插件

為何不在websocket server中直接操控硬體

除了前頭解釋過的原因之外,還有一個異步執行的問題,這個問題我在jupyter的架構中讨論過,有興趣的話可以翻翻那篇文章。jupyter和我們遇到相似的問題,這部分的架構也基本一樣

采用基于消息的架構,對社群有什麼好處

最壞情況下(比如大家沒有好的協同習慣),社群依然能夠共享大多的經驗,因為架構強行使用消息來通信,你可以看到任何元件是如何收發消息的(通過源碼或是類似rostopic的工具)。而在最好的情況下,如果大家都共用消息結構,引入一個新的硬體,你通常隻需要需要修改最底層驅動的幾行代碼

這種架構的靈活性,ROS已經向我們充分顯示了。當然設計出色且通用的消息體又是另一個話題了

為何要做成一個開放的系統,而不是釋出一個針對某個具體産品的軟體

我不喜歡封閉的系統

我們處在一個封閉、占地為王、屁股決定腦袋的世界。open source、重用、fork...這些概念在軟體行業之外的領域,受到猛烈抨擊。如果你在開源社群之外去做這些事,不隻是政治不正确,你還可能吃官司。關于這些話題,到處都是屁股決定腦袋的言論

我們喜歡scratch社群的口号:

Imagine, Program, Share

繼續閱讀