Upgrade to Pro — share decks privately, control downloads, hide ads and more …

FlutterとRobotics(ロボティクス)のわくわく同居生活篇 @FlutterKaigi2022

JaiChangPark
November 17, 2022

FlutterとRobotics(ロボティクス)のわくわく同居生活篇 @FlutterKaigi2022

https://flutterkaigi.jp/2022/

https://fortee.jp/flutterkaigi-2022/proposal/b8eb708d-fc3f-408f-af81-7a9686fed698

1. abstract
以前までは、Flutterがロボティクスまで活用されて使用することは想像できませんでした。最近、ロボットは生活周辺のどこでも探すことができるようになりました。ロボットは主にROS/ROS2ミドルウェアを使用し、ユーザーアプリは主にコンピュータ、Web、モバイル(スマホ)まで、様々なプラットフォームで提供されています。従来使用されていたクロスプラットフォームは生産性が低く、不便な点がたくさんあります。
今回の発表では、既存のロボットアプリケーション開発においてFlutterを適用した経験を共有し、どのような不便な点を克服したのか、そして軽い例を通して使い方を紹介していきたいと思います。

2. 対象者

ロボットに興味がある方
Flutterアプリ開発経験のある方
ソケット通信やgrpcなどのネットワーク通信に興味のある方

3. 注意
まったく難しくありません。発表を聞いた後、Flutterの生産性にもう一度驚くかもしれません。

JaiChangPark

November 17, 2022
Tweet

More Decks by JaiChangPark

Other Decks in Programming

Transcript

  1. 2 自己紹介 • Park. Jai-Chang (パク ジェチャン) • @Dreamwalker •

    現 | Dreamus Company • 前 | Angel Robotics • Flutter Seoul - Organizer JAICHANGPARK アンニョンハセヨ 30分間よろしくお願い します。
  2. 発表で触れること、触れないこと
 触れること 1. Flutterをロボットに活用す る方法 2. ROSとのコミュニケーション 方法 
 触れないこと

    1. Flutter 3の詳しい内容 2. ロボティクスの深い話 a. 理論 b. Kinematics c. Dynamics d. 2 link manipulator e. Jacobian & Cartesian f. など。 4
  3. 登場人物
 7 Flutter くん 画家Sky家門 特徴 
 1. 絵を描くのが上手です。 •

    FlutterはUI ToolKitである。 2. Dart語がペラペラです。 • FlutterはDart語を使います。 3. どこでも絵をうまく描けます。 • FlutterはMulti-Platformとして、Single Code Baseで モバイル、ウェブ、デスクトップ、Embedded イラストソース : いらすとや https://www.irasutoya.com/
  4. 登場人物
 8 ROSさん ROSジュニア2世 ROS2さん ロボット家門 特徴 1. C++やPython語がペラペラです。 •

    ROSはC++やPythonを使って開発します。 2. Linux家門のUbnutuと仲良し 3. ほぼ全てのロボットはROSさんとROS2さんを知っ てます。 イラストソース : いらすとや https://www.irasutoya.com/
  5. ROSってなんでしょう 11 ROSさん Robot Operating System イラストソース : いらすとや https://www.irasutoya.com/

    https://en.wikipedia.org/wiki/Pepper_(ro bot) https://www.universal-robots.com/ https://discourse.ros.org/t/ros-news-for-the-week-of-2-8-2021/1 8929 https://www.wired.com/story/spot-the-robot-dog-trot s-into-the-big-bad-world/
  6. ROSってなんでしょう
 12 ROS(Robot Operating System) 1. ROSはROSとROS2 2つのバージョンがあります。 2. ロボット開発に役立つ1つのミドルウェア

    3. Ubuntuオペレーティングシステムに基づいて主に使用されます。 4. 役割が定義されたノード(Node)があり、ノードとノード間の通信を行います。 5. ノードとノード間の通信には、ROSのみの標準化されたメッセージがあります。 • https://docs.ros.org/en/foxy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Nodes/U nderstanding-ROS2-Nodes.html • http://wiki.ros.org/
  7. Protocol Buffers
 14 message Person { optional string name =

    1; optional int32 id = 2; optional string email = 3; } https://developers.google.com/protocol-buffers
  8. ROS Msg 16 Msg sensor_msgs/BatteryState Message # Power supply technology

    (chemistry) constants uint8 POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0 uint8 POWER_SUPPLY_TECHNOLOGY_NIMH = 1 uint8 POWER_SUPPLY_TECHNOLOGY_LION = 2 uint8 POWER_SUPPLY_TECHNOLOGY_LIPO = 3 Header header float32 voltage # Voltage in Volts (Mandatory) float32 current # Negative when discharging (A) (If unmeasured NaN) float32 charge # Current charge in Ah (If unmeasured NaN) float32 capacity # Capacity in Ah (last full capacity) (If unmeasured NaN) float32 design_capacity # Capacity in Ah (design capacity) (If unmeasured NaN) float32 percentage # Charge percentage on 0 to 1 range (If unmeasured NaN) uint8 power_supply_status # The charging status as reported. Values defined above uint8 power_supply_health # The battery health metric. Values defined above uint8 power_supply_technology # The battery chemistry. Values defined above bool present # True if the battery is present float32[] cell_voltage # An array of individual cell voltages for each cell in the pack # If individual voltages unknown but number of cells known set each to NaN string location # The location into which the battery is inserted. (slot number or plug) string serial_number # The best approximation of the battery serial number http://docs.ros.org/en/melodic/api/sensor_msgs/html/index-msg.html http://docs.ros.org/en/melodic/api/sensor_msgs/html/msg/BatteryState.html
  9. ROS Msg 17 Srv - Service message (Custom) int64 a

    int64 b int64 c --- int64 sum Request Response https://docs.ros.org/en/humble/Tutorials/Beginner-Client-Libraries/Custom-ROS2-Interfaces.html
  10. 1. まずは、出会いから
 18 ROSさん Robot Operating System 早くアプリ出して AndroidもiOSもアプリ欲しい ウェブはデスクトップので

    もアプリ使いたい イラストソース : いらすとや https://www.irasutoya.com/ https://newatlas.com/robotics/ford-spot-robotic-do gs-laser-scan-retooling/ https://support.bostondynamics.com/s/article/Spot-controller
  11. 1. まずは、出会いから
 19 ROS2さん 合コンして 相手あってみたらどう? ユーザーアプリの開発に生産性が高く、 コストが低いプラットフォームは? • アプリ開発者は1人ですがどうする?

    • モバイルだけでなくWeb、デスクトップも可能なはずなのに? • 組み込みシステム(Embedded System)でも実行できなければならない。 イラストソース : いらすとや https://www.irasutoya.com/
  12. 1. まずは、出会いから
 20 ROS2さん Flutterさん iOSさん Android さん Qtさん RNさん

    🤔 時間があまりない QtやAndroidアプリだけを開発してみたが… イラストソース : いらすとや https://www.irasutoya.com/
  13. 2. 付き合い&告白 23 なぜ Flutterだったのか? 1. Android開発者はいましたが、iOS開発者はいませんでした。 2. AndroidアプリでROSを連動してデータ通信する作業が思ったより難しく時間がかかります (ros2-javaはあるが安定したros2-kotlinがない)

    3. 時間投資ほど結局iOSアプリも開発をしなければならない状況 4. 既存Android開発者にも開発が可能なFlutterを選定 ROS2さん Flutterさん 告白って握手 これあってます か? イラストソース : いらすとや https://www.irasutoya.com/
  14. 2. 付き合い&告白 24 なぜ Flutterだったのか? 5. 3-4ヶ月という時間内に結果が出なければならなかった 。 (モバイルアプリ、Web、ロボット自体でデバッグが可能なアプリなど )

    6. ネイティブのハードウェア機能が利用可能 (Platform Channelを使用したBLE、TCP / IP、WebSocketなど) 7. DX の方も良かった。 8. Legacyアプリじゃなく、新しいアプリを開発できる時期 ROS2さん Flutterさん 告白って握手 これあってます か? イラストソース : いらすとや https://www.irasutoya.com/
  15. 3. お部屋探し
 26 そろそろ、 一緒に住んでみま せんか? 同居生活.. 今家賃高いし、部屋狭 いし一緒に探してみま しょう

    じゃあ。 探してみます。 後は任せて イラストソース : いらすとや https://www.irasutoya.com/
  16. 4. 家もしくは部屋のインテリア
 簡単な1-2ページアプリなら 1. MVC(Model - View - Controller) 2.

    MVP(Model - View - Presenter) 3. MVVM(Model - View - ViewModel) MV-Whatever 35
  17. 5. 互いにコミュニケーションをとる
 37 人間関係や開発にて、コミュニケーションは最も重要な要素の 1つです。
 
 
 Q. ROSとFlutterは異なるプラットフォームですが、どのように通信する必要 がありますか?
 


    Flutterは、データを受信する受信者として (1つのクライアントとして )動作する 必要があります。
 ROSは、データを送信するサーバーと同じ役割を果たす必要があります。 
 
 
 👽👾👽 👾🛸👽 👾👽 イラストソース : いらすとや https://www.irasutoya.com/
  18. 38 Flutter ROS2 Foxy Ros Node Flutter App 通信 どうする?

    BLE? Wi-Fi? 1. 組み込み(Embedded)やデスクトップ環境 • Flutter アプリが組み込まれて使用される場合 2. Flutter アプリがモバイルアプリで提供される場合 • ネットワーク使用, Wi-Fi, LTE, 5G など 3. モバイル&タブレットアプリでインターネットに接続できない環境 5. 互いにコミュニケーションをとる
  19. 39 Flutter ROS2 Foxy Ros Node Flutter App 1. 組み込み(Embedded)やデスクトップ環境(Flutter

    アプリが組み込まれて使用される場合) • ローカルホストで127.0.0.1で相互通信が可能 • ネットワークレス環境でROSとフラッター間で通信可能 • ただし、クラウドと通信が必要な場合はネットワーク接続が必要です。 ◦ または別々の周波数を持つ通信を使用する(LoRaなど) 5. 互いにコミュニケーションをとる
 Ubuntu(Linux) OS 写真は例です。

  20. 40 Flutter ROS2 Foxy 2. Flutter アプリがモバイルアプリで提供される場合 • TCP/IP ソケット通信を使用する。

    (データ規格は主にJSON) • gRPC(データ仕様はプロトコルバッファ) • ケーブルによる有線通信 Ros Node Flutter App 5. 互いにコミュニケーションをとる
 Ubuntu(Linux) OS Android & IOS Hardware Platform Channel
 BLE, Wi-Fi etc
 Network イラストソース : いらすとや https://www.irasutoya.com/
  21. 41 Flutter ROS2 Foxy 3. モバイル&タブレットアプリでインターネットに接続できない環境 • Wi-Fi p2p (Direct)

    ◦ TCP/IP Socket通信を使用する。(JSONデータ) ◦ WebSocket (JSONデータ) ◦ gRPC (プロトコルバッファ) • ケーブルによる有線通信(Uartなど) • BLE Ros Node Flutter App 5. 互いにコミュニケーションをとる
 Ubuntu(Linux) OS Android Hardware Platform Channel
 BLE, Wi-Fi Direct etc
 Flutter Flutter App iOS Hardware Platform Channel
 BLE
 BLE
 ALL
 イラストソース : いらすとや https://www.irasutoya.com/
  22. 5. 互いにコミュニケーションをとる
 42 Q. では、TCP/IP Socket と Websocket の Bandwidth

    は確かに違うのに速度差はなかったのでしょうか? A. 体感されるほどの違いはありませんでした。
  23. 5. 互いにコミュニケーションをとる
 43 Q. なぜBLE通信を使用しなかったのですか? A. BLE Bandwidth 1Mbps or

    2Mbps Wi-Fi Direct(p2p) 250Mbps Wi-Fi DirectはAndroidでのみ利用可能です。 iOSの場合は、BLEを使用してください。
  24. 5. 互いにコミュニケーションをとる
 44 最初はどのようにコミュニケーションを取ったのでしょうか? 
 
 UbuntuコンピュータでROS アプリを実行しました。 
 しかし、Flutterアプリとデータ通信できるものはありませんでした。

    
 
 したがって、TCP/IP Socket 通信を利用する
 そして、どのクライアントでも同じように使用できるように gRPCを使用しました。
 Flutter ROS2 Foxy Ros Node Topic Flutter App Subscription 通信のため 何かが必要
  25. 45 Ubuntu 20.04 Flutter ROS2 Foxy Ros Node Flutter App

    Publisher Ros Node Subscriber Msg Converter Msg Converter Msg(Data) Protocol Buffers Builder gRPC Client gRPC Server Python & Go gRPC Server gRPC Process A
 Process B
 Process C or third-party
 Msg Decode Thread 1
 Thread 0

  26. 46 Ubuntu 20.04 Flutter ROS2 Foxy Ros Node A Flutter

    App roslibdart publisher Ros Node rosbridge _server Websocket Server WebSocket Client Ros Node B publisher Topic :9090 JSON 
 
 5. 互いにコミュニケーションをとる
  27. 5. 互いにコミュニケーションをとる
 48 rosbridge v2.0 Protocol Specification
 https://github.com/RobotWebTools/rosbridge_suite/blob/ros2/ROSBRIDGE_PROTOCOL.md https://github.com/RobotWebTools/rosbridge_suite The

    message transport of rosbridge is JSON objects. The only required field is the 'op' field, which specifies the operation of that message. Each 'op' then specifies its own message semantics. イラストソース : いらすとや https://www.irasutoya.com/
  28. # install using apt-get sudo apt-get install ros-foxy-rosbridge-server # or

    you can clone from github cd ros_ws/src git clone https://github.com/RobotWebTools/rosbridge_suite cd .. colcon build 5. 互いにコミュニケーションをとる
 50 rosbridge_suite INSTALLATION https://github.com/RobotWebTools/rosbridge_suite イラストソース : いらすとや https://www.irasutoya.com/
  29. # install using apt-get sudo apt-get install ros-foxy-rosbridge-server # or

    you can clone from github cd ros_ws/src git clone https://github.com/RobotWebTools/rosbridge_suite cd .. colcon build 5. 互いにコミュニケーションをとる
 51 rosbridge_suite humble & distro イラストソース : いらすとや https://www.irasutoya.com/
  30. # install using apt-get sudo apt-get install ros-foxy-rosbridge-server # or

    you can clone from github cd ros_ws/src git clone https://github.com/RobotWebTools/rosbridge_suite cd .. colcon build 5. 互いにコミュニケーションをとる
 52 rosbridge_suite https://github.com/RobotWebTools/rosbridge_suite ws または ros_ws をワークスペースフォルダー名として主に使用します。 
 イラストソース : いらすとや https://www.irasutoya.com/
  31. 5. 互いにコミュニケーションをとる
 53 rosbridge_suite > rosbridge_serverの実行 Websocket ポート9090を使用してクライアントと通信可能 setup.bash cd

    ros_ws source install/local_setup.bash ros2 launch rosbridge_server rosbridge_websocket_launch.xml イラストソース : いらすとや https://www.irasutoya.com/
  32. 5. 互いにコミュニケーションをとる
 54 roslibdart ros = Ros(url: 'ws://127.0.0.1:9090'); chatter =

    Topic(ros: ros, name: '/topic', type: "std_msgs/String", reconnectOnClose: true, queueLength: 10, queueSize: 10); ros.connect(); await chatter.subscribe(subscribeHandler); Future<void> subscribeHandler(Map<String, dynamic> msg) async { msgReceived = json.encode(msg); setState(() {}); } イラストソース : いらすとや https://www.irasutoya.com/
  33. 5. 互いにコミュニケーションをとる
 55 roslibdart ros = Ros(url: 'ws://127.0.0.1:9090'); chatter =

    Topic(ros: ros, name: '/topic', type: "std_msgs/String", reconnectOnClose: true, queueLength: 10, queueSize: 10); ros.connect(); await chatter.subscribe(subscribeHandler); Future<void> subscribeHandler(Map<String, dynamic> msg) async { msgReceived = json.encode(msg); setState(() {}); } Websocket localhost 9090
 Ros Class イラストソース : いらすとや https://www.irasutoya.com/
  34. 5. 互いにコミュニケーションをとる
 56 roslibdart class Ros { Ros({this.url}) { _statusController

    = StreamController<Status>.broadcast(); } Ros Class イラストソース : いらすとや https://www.irasutoya.com/
  35. 5. 互いにコミュニケーションをとる
 57 roslibdart /// The websocket connection to communicate

    with the ROS node. late WebSocketChannel _channel; /// Subscription to the websocket stream. late StreamSubscription _channelListener; /// JSON broadcast websocket stream. late Stream<Map<String, dynamic>> stream; Ros Class イラストソース : いらすとや https://www.irasutoya.com/
  36. 5. 互いにコミュニケーションをとる
 58 FlutterでRoslibdartを使用してtopiclメッセージを購読(Sub)する方法 ros = Ros(url: 'ws://127.0.0.1:9090'); chatter =

    Topic(ros: ros, name: '/topic', type: "std_msgs/String", reconnectOnClose: true, queueLength: 10, queueSize: 10); ros.connect(); await chatter.subscribe(subscribeHandler); Future<void> subscribeHandler(Map<String, dynamic> msg) async { msgReceived = json.encode(msg); setState(() {}); } Topic Class イラストソース : いらすとや https://www.irasutoya.com/
  37. 5. 互いにコミュニケーションをとる
 59 FlutterでRoslibdartを使用してtopiclメッセージを購読(Sub)する方法 class Topic { Topic({ required this.ros,

    required this.name, required this.type, this.compression = 'none', this.throttleRate = 0, this.latch = false, this.queueSize = 100, this.queueLength = 0, this.reconnectOnClose = true, }) : assert(['png', 'cbor', 'none'].contains(compression)), assert(throttleRate >= 0); Topic Class イラストソース : いらすとや https://www.irasutoya.com/
  38. 5. 互いにコミュニケーションをとる
 60 FlutterでRoslibdartを使用してtopiclメッセージを購読(Sub)する方法 Ros connect ros = Ros(url: 'ws://127.0.0.1:9090');

    chatter = Topic(ros: ros, name: '/topic', type: "std_msgs/String", reconnectOnClose: true, queueLength: 10, queueSize: 10); ros.connect(); await chatter.subscribe(subscribeHandler); Future<void> subscribeHandler(Map<String, dynamic> msg) async { msgReceived = json.encode(msg); setState(() {}); } イラストソース : いらすとや https://www.irasutoya.com/
  39. 5. 互いにコミュニケーションをとる
 61 FlutterでRoslibdartを使用してtopiclメッセージを購読(Sub)する方法 Ros connect _channel = initializeWebSocketChannel(url); stream

    = _channel.stream.asBroadcastStream().map((raw) => json.decode(raw)); IOWebSocketChannel.connect(url); イラストソース : いらすとや https://www.irasutoya.com/
  40. 5. 互いにコミュニケーションをとる
 62 roslibdart ros = Ros(url: 'ws://127.0.0.1:9090'); chatter =

    Topic(ros: ros, name: '/topic', type: "std_msgs/String", reconnectOnClose: true, queueLength: 10, queueSize: 10); ros.connect(); await chatter.subscribe(subscribeHandler); Future<void> subscribeHandler(Map<String, dynamic> msg) async { msgReceived = json.encode(msg); setState(() {}); } Topic Subcri be イラストソース : いらすとや https://www.irasutoya.com/
  41. 5. 互いにコミュニケーションをとる
 63 roslibdart Future<void> subscribe(SubscribeHandler subscribeHandler) async { subscription

    = ros.stream; subscribeId = ros.requestSubscriber(name); await safeSend(Request( op: 'subscribe', id: subscribeId, type: type, topic: name, compression: compression, throttleRate: throttleRate, queueLength: queueLength, )); } Topic Class Requestはデータモデルです
 JSON DECODE、ENCODE処理が可 能です。
 
 イラストソース : いらすとや https://www.irasutoya.com/
  42. 5. 互いにコミュニケーションをとる
 64 roslibdart Future<void> subscribe(SubscribeHandler subscribeHandler) async { subscription!.listen((Map<String,

    dynamic> message) async { if (message['topic'] != name) { return; } await subscribeHandler(message['msg']); }); } Topic Class イラストソース : いらすとや https://www.irasutoya.com/
  43. 5. 互いにコミュニケーションをとる
 65 データ
 麺=
 Json
 WebSocket & Stream
 竹=通信媒体


    お水
 Serialization
 @freezed 
 @json_serialization
 StreamSubscription 好みで
 データ処理
 Model または
 json デコード
 data発生 Listen イラストソース : いらすとや https://www.irasutoya.com/
  44. 5. 互いにコミュニケーションをとる
 67 roslibdart Future<void> subscribe(SubscribeHandler subscribeHandler) async { subscription!.listen((Map<String,

    dynamic> message) async { if (message['topic'] != name) { return; } await subscribeHandler(message['msg']); }); } Topic Class イラストソース : いらすとや https://www.irasutoya.com/
  45. 5. 互いにコミュニケーションをとる
 68 roslibdart // Receiver function to handle requests

    when the service is advertising. typedef SubscribeHandler = Future<void> Function(Map<String, dynamic> args); Topic Class イラストソース : いらすとや https://www.irasutoya.com/
  46. 5. 互いにコミュニケーションをとる
 69 roslibdart ros = Ros(url: 'ws://127.0.0.1:9090'); chatter =

    Topic(ros: ros, name: '/topic', type: "std_msgs/String", reconnectOnClose: true, queueLength: 10, queueSize: 10); ros.connect(); await chatter.subscribe(subscribeHandler); Future<void> subscribeHandler(Map<String, dynamic> msg) async { msgReceived = json.encode(msg); setState(() {}); } イラストソース : いらすとや https://www.irasutoya.com/
  47. まとめ 71 1. ロボティクスの開発には ROS(Robot Operating System)を使っています。 ◦ ロボット開発にROS2を使いました。ROS2はUbnutuOS環境で設定して開発しました。 2.

    ロボットのユーザー向けのアプリで Flutterを選んで開発し、その結果最高でした。 ◦ その結果生産性が上がり、コストは下がりました。 ◦ Platform Channel&Method Channelを使って通信に対していろんな問題を解決しました。 (BLE, TCP/IP) 3. Architectureと状態管理(State Management) ◦ どんどん機能が増えて MVVM(AS-IS)からClean Architecture(TO-BE)に変更しました。 ◦ Provider(AS-IS)からRiverpod(TO-BE)に変更。 4. ROSとFlutterアプリと通信方法 ◦ (AS-IS) 最初はgRPCを使ってお互い通信しました。 (Protocol Buffers) ◦ (TO-BE) roslibdartとrosbridge_serverを使うことに変更しました。 (JSON)