CYDAS Developer's Blog

サイダス技術者ブログ

DeepRacerを走らせる!ー テストドライブ編 ー

f:id:aym413:20190129124352j:plainこんにちは!エンジニアのこぶかた@kobuuukata)です!

前回に引き続きまして、今回はいよいよDeepRacerを走らせます!

DeepRacerのセットアップがまだの方はこちら〜
tech.cydas.com

Step.3 テストドライブ

パワーバンクに接続する

部品の中からパワーバンクの接続ケーブルを取り出して
パワーバンクのUSB-Cポートと車体のUSB-Cポートをつなぎます。
つなぐとこんな感じ↓
f:id:aym413:20190127135402j:plain

パワーバンクの電源を入れる

パワーバンクの電源ボタンを押します。
f:id:aym413:20190127140236j:plain

車体の電源を入れる

車体横の電源ボタンを押します。
f:id:aym413:20190127141921j:plain

しばらくすると電源ボタンのマークが青色に点灯し、Wi-Fiに接続し始めます。

続いて、LEDランプも点灯状態になると、Wi-Fiの接続が完了されました!
f:id:aym413:20190127143021j:plain

車体のスイッチをオンにする

フロントタイヤの左側(車体の電源ボタンがある側)にスイッチがありますので
そのスイッチをONにします。
f:id:aym413:20190128214850j:plain

パカっと開けたココ↓
f:id:aym413:20190128214334j:plain

そのとき、ピピッ、ピーー
短いビープ音2回・長いビープ音が1回鳴ればOKです!

もしビープ音が鳴らなかった場合は、カーバッテリーの充電がないかもしれません。
こちらの手順を参考にカーバッテリーを充電してください↓
docs.aws.amazon.com

カバーをセットする

車体にカバーをかぶせ、ピンで4箇所固定します。
さあ、DeepRacerの準備は整いましたよ〜〜!
f:id:aym413:20190127145804j:plain

DeepRacerを走らせる

セットアップ編でも使用したdevice-status.txtファイル内に
記載されているIPアドレスをブラウザで開きます。

ログイン画面が表示されるので、Passwordを入力して
「Access vehicle」をクリックします。
f:id:aym413:20190125220347p:plain

Passwordは車体の裏側に記載してあります。
f:id:aym413:20190127145315j:plain

f:id:aym413:20190127145419j:plain

アクセスしたら、「Driving Mode」をManualにします。
f:id:aym413:20190128230249j:plain

操作方法は「Click or touch to drive」のところでクリックして
中心円を上下左右に動かすとDeepRacerが走ります。
画面上で操作するのと、DeepRacerが走り出すのに若干のタイムラグがあります。
操作は前と後ろが逆なので慣れないと難しい・・・
f:id:aym413:20190128233756j:plain

私が実際にDeepRacerを走らせてみた動画がこちらです!↓

走らせるスピードの調整がなかなか難しくて、思ったように走ってくれず・・
日本に来るのが待ち遠しいですね!

では!

DeepRacerを走らせる!ー セットアップ編ー

こんにちは!エンジニアのこぶかた@kobuuukata)です!

昨年、re:Invent 2018に参加してきました!
その中でDeepRacerが発表されました!

DeepRacerについての説明はこちら↓ aws.amazon.com

現地でワークショップに参加したところ・・・

DeepRacerゲットしました〜!

ジャジャーーーン♪
f:id:aym413:20190118211215j:plain

早速現地でセットアップからテストドライブまで試してみました!

セットアップの手順はこちらにあります↓
https://d1.awsstatic.com/deepracer/AWS-DeepRacer-Getting-Started-Guide.pdf

Step.1 車を組み立てる

車体についているピンを外す(4箇所)

DeepRacerを箱から取り出して、ピンを外します。
f:id:aym413:20190127131953j:plain

パカっとするとこんな感じ
f:id:aym413:20190118223249j:plain

カーバッテリーのケーブルを接続

部品の中からカーバッテリーを取り出して、
車体についている赤と黒のケーブルとカーバッテリーのケーブルを繋げます。

ここで注意!

ケーブルを繋げる際は、

同じ色同士を接続するようにします!

f:id:aym413:20190125231640j:plain

カーバッテリーを車体に取り付け

車体のベルトを外してカーバッテリーを取り付けます。
f:id:aym413:20190125231950j:plain

車体をピンで固定(4箇所)

ケーブルを車体の中に入れ、ピンで固定します。
f:id:aym413:20190124121103j:plain

パワーバンクの取り付け

部品の中からパワーバンクを取り出して
電源ボタンがある方を車体の後方の向きになるようセットします。

ん?電源ボタン??どこどこ???

しばらく探していると、

あーー!シール貼ってあるじゃん!!
f:id:aym413:20190124121210j:plain

全然気づかなかった、、
剥がしてみると、電源ボタン出現!!

改めてパワーバンクを車体に取り付けます。
ここで注意!

ここではまだパワーバンクの電源は入れないでください。

f:id:aym413:20190127132347j:plain

パワーバンクを充電する

DeepRacerを走らせる際、パワーバンクが充電されている必要がありますので
ここでパワーバンクを充電しておきましょう。
パワーバンクのUSB-Cポートに電源ケーブルを挿して、コンセントにつなぎます。
f:id:aym413:20190128132212j:plain

Step.2 接続する

コンセントに接続する

車体にあるUSB-Cポートに電源ケーブルを挿して、コンセントにつなぎます。

車体の電源を入れる

車体横の電源ボタンを押してください。
パワーバンクの電源ではなく、車体の電源です!
f:id:aym413:20190127142251j:plain

しばらくすると電源ボタンのマークが青色に点灯します。
ピカーーーン!

Wi-Fiを設定する

USBメモリをPCに挿しておきます。

下記からWi-Fi設定用のファイルをダウンロードします。
https://d1.awsstatic.com/deepracer/wifi-creds.txt

ダウンロードしてきたら、ファイルを開いて
Wi-FiのSSIDPasswordを入力します。
f:id:aym413:20190124123237p:plain

入力したらUSBメモリに保存します。
ファイル名は変えずwifi-creds.txtのまま保存してください。
f:id:aym413:20190124123654p:plain

PCからUSBメモリを外し、車体のUSBポートに挿します。
すごく挿しづらいところにある・・
車体の後方、パワーバンクの後ろです。
f:id:aym413:20190125232237j:plain

f:id:aym413:20190124151525j:plain

しばらくすると、Wi-FiのLEDランプが青色に点灯します。
電源ランプとLEDランプが両方点灯していればオッケーです!
f:id:aym413:20190125125712j:plain

もし、LEDランプが赤に点灯していたら
Wi-FiのSSIDかPasswordが間違っていますので
USBメモリを外して再度確認してください!

ソフトウェアのアップデート

Wi-FiのLEDランプが青色になっているのが確認できたら
一度USBメモリを車体から外して、再度USBメモリをPCに挿します。

USBメモリ内にdevice-status.txtという
ファイルが作られているかと思いますのでそちらを開きます。

ファイルの中にIPアドレスが記載されているのでコピーします。
f:id:aym413:20190125130551p:plain

コピーしたIPアドレスをブラウザで開きます。
こんな警告画面出ますが、気にせず!
f:id:aym413:20190125131045p:plain

「詳細設定」 > 「XXXXXにアクセスする(安全ではありません)」をクリックします。
f:id:aym413:20190125131407p:plain

DeepRacerのソフトウェアをアップデートします。
電源がコンセントにささっていることを確認して
「Yes, update vehicle software」をクリックします。
f:id:aym413:20190125214952p:plain

クリック後、アップデートが始まります。
アップデート中はこんな画面↓
f:id:aym413:20190125215504p:plain

3分ほど待つと・・・

車体のLEDランプが点滅→点灯状態に変わったらアップデート完了です!
f:id:aym413:20190127134334j:plain

車体のUSB-Cポートから電源を外します。
車体のLEDランプが消えますが問題ありません!

DeepRacerのセットアップはこれで終わりです!

次はいよいよDeepRacerを走らせますよ〜〜!

Nuxt.jsのinjectを使ってDIする

大阪からこんにちは、福山健@kenfdev)です!

先日「v-kansai Vue.js/Nuxt.js meetup #2」で「Nuxt.jsのinjectでインジェクトしてみる話」という内容で登壇させていただきました。その内容について記事にも残しておこうと思います。

スライドに関しては以下で公開しています。

speakerdeck.com

前提知識

  • 基本的なNuxt.jsの機能
  • Vuexをなんとなく知っている
  • TypeScriptがなんとなく読める

Nuxt.jsの inject

皆さん、Nuxt.jsには inject という機能があるのをご存知でしょうか?意外と知られていないんじゃないかと思うのですが、公式ドキュメントの「統合された注入」にも記載されているNuxt.jsのプラグインの機能です。この inject を使うことで、Nuxt.jsのアプリケーションで、いろいろな場所から共通で利用したい関数や値を(グローバル変数にすることなく)呼び出すことができます。「グローバル変数や、外部モジュールから import で読み込んじゃえばいいんじゃないの?」と思われるかもしれませんが、自分の興味のあるコンテキスト内(例えばある関数Aの中身)に、差し替え可能な状態で関数や値が用意されていると、何かと便利です(特にtestabilityの観点で)。このトピックと関連が深いのが「Dependency Injection(依存性の注入)」です。

Dependency Injection?

Dependency Injectionが何なのか。何がうれしいのか。と思われる方もいると思いますが、それを話し始めるとこの記事が(ただでさえ長いのに)すごく長くなってしまうので、ぜひ「dependency injection 何がうれしい」と ググってみて ください。先人たちの素晴らしい記事が何個も出てくると思います。

Demoアプリ

inject-demo-app
injectを使ったdemoアプリ

inject を実際に小さなアプリで使ったものを上図のようなアーキテクチャで公開しています。

github.com

このアプリはVue.jsとNuxt.jsのGitHubのスター数をGitHubAPIから取得して合算したものを画面に表示するという至ってシンプルなものです。大きな特徴としては「状態管理パターンとはなんですか?」で紹介されているVuexの登場人物に加えて、「Gateway」という存在を追加しています。これはActionsから直接 axios などを使ってリクエストを投げるのではなく、Gatewayさんに依頼して(ワンクッション置いて)リクエストを投げるという意味です。

プラグインの書き方

プラグインの書き方は、次のような記述を plugins/dependencies.ts というファイル(TypeScriptを使用しています)に書きます。

export default (context, inject) => {
  const environment = process.env.environment || 'development';

  let gitGateway: IGitGateway;
  if (environment === 'offline') {
    gitGateway = new FakeGitGateway();
  } else {
    gitGateway = new GitHubGateway(axios);
  }

  const deps: Dependencies = {
    gitGateway,
  };

  inject('deps', deps);
};

inject('deps', deps) としているところがミソで、これでアプリケーションの様々な場所から $deps として呼べるようになります。

$deps の呼び方

上の設定で用意した $deps は大きく3箇所から呼ぶことができます。

  • Nuxt.jsの context
  • Vueのインスタンス
  • VuexのActionの中(store自身)

Nuxt.jsの context

Nuxt.jsの context は様々な場所で参照できますが、例えば pagesfetch の第一引数にも渡されてきます。次のようにアクセスできます:

fetch(context) {
  // context.app.$deps.gitGateway
  // ...
},

Vueのインスタンス

Vueのインスタンスからは、例えば methods 内から呼び出すことができます。インスタンス自身なので this から参照できます。

methods: {
  onLoad() {
    // this.$deps.gitGateway
    // ...
  },
},

VuexのActionの中

今回のパターンで使いたい、Actionから参照する方法です。 store 自身にも $deps が注入されているので、次のように参照できます。

export const actions = {
  async [actionTypes.FETCH_STARS]({ commit }) {
    // this.$deps.gitGateway
    // ...
  },
};

このように、様々な場所から $deps が呼び出せるようになります。

何がうれしいのか?

では、 $deps が呼び出せるようになって何がうれしいかというと、ソフトウェアアーキテクチャを考えると色々と例があると思いますが、以下の2点を紹介したいと思います。

  • Vuex内が要件の変化に強くなる
  • 開発モードみたいな機能を追加できる

Vuex内が要件の変化に強くなる

今回の要件は「リポジトリのスター数をとってきて表示する」というものだったとします。リポジトリがどこにあるかもわからなければ、その数もわからなかったとしましょう。「まだわからないので開発もしない」わけではなく、詳細はともかく、要件は決まっているところから着手していくことができます。

「どうやってスター数をとってくるか」はGatewayさんにおまかせします。それ以上の詳細は今は気にしません。図で表すと次の部分は作ることができるということです。

TypeScriptで表現した場合、Gatewayさんは IGitGateway として例えば次のように interface を定義することができます。

export interface IGitStarsResult {
  count: number;
}

export interface IGitGateway {
  fetchStars(): Promise<IGitStarsResult>; // 「スター数とってきてー」メソッド
}

ということで、VuexのActionは次のような実装で書くことができます。

export const actions: ActionTree<State, State> = {
  async [actionTypes.FETCH_STARS]({ commit }) {
    const { gitGateway } = this.$deps as Dependencies; // $depsからgitGatewayを参照

    commit(mutationTypes.SET_LOADING, true);
    const { count } = await gitGateway.fetchStars(); // スター数とってきてー
    commit(mutationTypes.SET_LOADING, false);

    commit(mutationTypes.SET_COUNT, count); // スター数をストアに保存!
  },
};

TypeScriptを使っていて as を使うのは極力避けたいのですが、今の所 $deps に型情報を簡単に反映させるには as Dependencies が良いと思って使っちゃっています。こうすることで次のように補完も効いてちょっと安心して開発ができます。

code-completion
Action内でのコード補完

では、「どうやってスターをとってくるか」が不明な状態で、実際の gitGateway はどう実装すればいいのでしょう?という疑問がわいてくると思うのですが、わからないうちは次のようにスタブを作っちゃいましょう。 IGitGateway を満たしつつ、1.5秒後に {count: 2} を返す FakeGitGateway を次のように実装できます:

export class FakeGitGateway implements IGitGateway {
  fetchStars(): Promise<IGitStarsResult> {
    return new Promise(resolve => {
      setTimeout(() => {
        resolve({ count: 2 });
      }, 1500);
    });
  }
}

これを plugins/dependencies.ts で差し込むことで、Action内で参照する gitGatewayFakeGitGateway のインスタンスになります。

// plugins/dependencies.ts
export default (context, inject) => {
  const gitGateway = new FakeGitGateway();
  const deps: Dependencies = {
    gitGateway,
  };

  inject('deps', deps);
};

以上で、スター数は2で固定となってしまいますが、Vuexの中身の実装は先行して作り切っちゃうことができます。

後になって「GitHubからスター数をとってきて」という詳細がきまったときに、 GitHubGateway を実装して、 FakeGitGateway と差し替えることで、Vuex内は何も変えずに最終型を作り上げることができます。

// plugins/dependencies.ts
export default (context, inject) => {
  // const gitGateway = new FakeGitGateway();
  const gitGateway = new GitHubGateway();
  const deps: Dependencies = {
    gitGateway,
  };

  inject('deps', deps);
};

GitLabからスター数をとってきたい場合であれば GitLabGateway を実装すればいいですし、GitHubとGitLab両方から取得する場合も、そのようなGatewayを作って差し込めばOKです。

要件の変化に強いVuex

アーキテクチャ寄りな話になってしまいましたが、 inject を使ったメリットの一つとして紹介しました。

開発モードみたいな機能を追加できる

次に、上の差し替えに関連するのですが、Nuxt.jsの 環境変数 と組み合わせることで、 npm run offline のように、インターネットに通信しにいかないモードを作ることもできます。次のように plugins/dependencies.ts を実装することで、実行時のGateway切り替えが可能になります。

// plugins/dependencies.ts
export default (context, inject) => {
  const environment = process.env.environment || 'development';

  let gitGateway: IGitGateway;
  if (environment === 'offline') {
    // offline時はスタブを使う
    gitGateway = new FakeGitGateway();
  } else {
    // それ以外は本物の実装を使う
    gitGateway = new GitHubGateway(axios);
  }

  const deps: Dependencies = {
    gitGateway,
  };

  inject('deps', deps);
};

こういうモードを分けることで、Integration Test時にGatewayを差し替えたり、あるいは「API側がバグっていてフロントの開発ができなくなる」というような状況を回避することもできたりするので、意外とDX(Developer Experience)の向上に貢献するのではと思います。

気になった点

「うれしかった」と感じた点はいったんここまでとして、やってみて「気になった」点について2点ほど共有したいと思います。

Lazy Loadはされるのか?

中規模くらいなアプリケーションであればさほど気にしなくてもいいのかもしれませんが、 現時点でプラグインのLazy LoadというものはNuxt.jsには無いという認識です。なので、 plugins/dependencies.ts が肥大化すると、そこに関連するコードはすべてメインのbundleに含まれることになると思います。アプリケーションが大規模になっていくと、bundleのサイズも無視できなくなってくるので、結構致命的な問題じゃないかな、と思っています。ここらへんは今後Nuxt.js的に改善されていくかもしれないので要チェックです。

$deps はVuexのStoreで参照できれば十分では?

Vuexを使うアプリであれば、ビジネスロジックに関わる部分はAction内にほとんど収まるはずなので、StoreのAction内でだけ this.$deps が参照できたら十分では?と思いました。 injectのコード を見ても、 store$deps を代入してるだけなので、なんら難しいことはしてなさそうです。Vuexのモジュールは 動的に登録 することができるので、Lazy Loadしながら、 store の中に注入していけるのではと思います。

まとめ

最後に inject を使ってのまとめです。

  • 中規模なアプリ(明確な線引はできませんが、パフォーマンスとの兼ね合いでしょうか)であれば inject を使ってのDIは便利に使えそう
  • ↑に関連して、プラグインもLazy Loadできるような仕組みがNuxt.jsにできれば、 plugins/dependencies.ts も複数ファイルに分割して大規模なアプリでも一つのファイルが肥大化しちゃう問題は回避できそう
  • 実は store でしか inject されたものを使わないかもしれないので、 store にさえ自分で入れてしまえば使わなくても良いのかもしれない
  • とは言え、↑でいろいろと言ってますがNuxt.js側でこの inject の仕組みを用意してくれているのはうれしい。今後の改善にも期待したい

という感じです!

ながーい記事になってしまいましたがここまで読んでいただきありがとうございます。

サイダスではこんな感じにDXを追求しながら堅牢なソフトウェアを作っていく方法について語り合える仲間も絶賛募集中です!

www.wantedly.com

ではでは!

技術ブログを公開しました

サイダス吉田真吾@yoshidashingo)です。

このたびコーポレートサイトのリニューアルに合わせて、サイダス社の技術本部のメンバーによるテックブログを公開しました。

サイダス社における技術者の位置付けについて

サイダスは2011年に人材育成・評価分野の有識者が集まって、現在も代表取締役である松田が起業した会社です。2011年からVPS上で、2012年末くらいにAWSに基盤を移行してB2B SaaSを提供しています。

サイダスにおける技術本部の位置付けは、大きく2つあります。1つめは「すべての働く人がよりよい働きがいを得られる製品機能」を「最適なアーキテクチャで素早くデリバリー」し、「安定して心地よく利用していただく」という事業に対する技術的な貢献ですが、2つめには「徹底的に自分の働きかたにこだわる」という側面です。

事業に対する技術的な貢献

現在技術本部のチーム構成は以下のようになっています。

Center of Excellence(CoE)チーム

  • ITアーキテクト

PdMチーム

  • PdMスタッフ (企画)
  • プロダクトデザイナー
  • プロダクトオーナー

開発チーム

スクラム手法によるアジャイル開発チームが複数稼働していますが、昨年までと違い、PdM&デザイン部分も各チームで担う形を模索しています。

SRE/Productivityチーム

人数が少ないため兼任していますが、SREと情シスを担っているチームです。

チーム構成のポイントとしては、何を作るべきか(What)とどう作るか(How)のバランス、また運用保守ではなく永続的に進化していくための仕組みが備わったチーム構成を指向しています。

徹底的に自分の働きかたにこだわる

特に社内で働きかた含めてあらゆる理論の実践における実験場でありたいと考え、OKRによる目標管理、月イチの1on1、リモートワーク、自己組織化などを技術本部のみで実施している施策があります。

OKR

スクラム手法によるアジャイル開発に慣れてくると、PBIをよりよくチームでこなしてソフトウェアをデリバリーするという方向性においてはある程度満足できるのですが、会社や本部で真にフォーカスしたい尖った方向性に対して、企画〜開発でその輪郭を削り出すような力は生まれないんですね。なので大きい方向性に対して尖らす推進力が欲しいなというモチベーションで開始したのがOKRです。ちなみにすべての活動の最上位概念としてOKRを位置付けています。

今のところ、大半の時間は「本当にフォーカスべき目標の決定とKR(主要な結果:数値目標)」の設定と「個人のOKRの達成が組織のOKRの達成になるための合算量的なリバランス、アラインメント調整」です。ここがうまくできないと実際にうまくいきません。また、アンチパターンとして数値で表せない目標しか設定できないといった場面がありえますが、これを承認してKRで期日管理してもおそらく大半うまくいきません。数値目標に徹底的にこだわりましょう。

月イチの1on1

組織がフラットなので技術本部長である私と全員がそれぞれやる形ですが、毎月必ず1回以上開催することを死守しています。アジェンダは決めてあるので、それに沿って毎月各自からトピックを引き出しています。

現在のところ1on1は本当に強力で、自分では取りかかれないけどきっと改善したら嬉しいとみんなが考えている内容や、取り掛かりかたにモヤモヤ迷っていたことについて整理して自走し始めてくれたり、私に言いにくくてわだかまってたことなどを話してカタルシスを得たりなど効果がとても高いです。

毎回30分でやってるのでタイムマネジメントとすべてのトピックの聞き出しが大変なんですが、昔取得した産業カウンセラーとしての能力が役立ってるように感じます。

github.com

上司として1on1をしなければいけなくなった場合は「アジェンダ」を用意し、「タイムボックスを固定(タイムマネジメント)」し、「コーチングやカウンセリングの技術(特に傾聴)を鍛えたうえで」実施するとうまく回るようになるでしょう。

リモートワーク

現在、東京/大阪/沖縄すべての拠点で1/3程度の技術部メンバーがリモートワークしています。子育てなどの家庭事情もあれば、チームのワーキングアグリーメントで働きやすさを重視してということもありますが、特に条件なくやらせています。また先週は別の事業部でインフルエンザが発生していたため、技術部全員リモートワークにしました。

チームメンバーが隣にいたほうが生産性が高い仕事も時にありますが、集中タイムの確保なども考慮すると、SlackとZoomがあればもはや好きな働きかたを選んでもなんの支障もない状況です。

自己組織化

基本的に私が「あなたが担当している分野については業務命令や意思決定はしない(形式的にすることはあるけど)」と宣言しているので、リーダーシップ原則に基づいて主体的に取り組んでもらってます。その代わり「誰かにアドバイスは必ずもらうこと」としています。

意思決定に必要な情報がもっとも集まっている現場において判断したほうがよいという考えと、正しい意思決定を行うために必要な情報が不足している可能性を当事者では気づけない場合があるためアドバイザリプロセスを入れることで情報量や多面性などを確保するためです。

cydas/principles.md at master · yoshidashingo/cydas · GitHub

※自己組織化は正しい呼び方ではないかもしれない

CTOとしての8ヶ月について

就任してから8ヶ月経過してますが、まだまだマーケットにインパクト与える結果を出せてないのが実感なので、とくに私はCTOである前に「取締役」つまり経営者であるので、しっかりと社会にインパクトを与えていけるように頑張りたいと思います。

yoshidashingo.hatenablog.com

そういえばマネージャーのトリセツも公開しています。

cydas/manager-readme.md at master · yoshidashingo/cydas · GitHub

採用について

サイダス技術本部では今年も積極的に採用を行なっていきます。既存の社員の働きがいを高めてリファラルを強化するという点と、イベント登壇やここのような場所での発信を通じて、みなさまがサイダスで働いてみたいなと興味を持ってもらえるように頑張ります。

www.wantedly.com

www.wantedly.com

www.wantedly.com

それでは