HHKB Hybridを買った

ついに世代交代。

実のところ、HHKB Pro2でも全く問題なく使えていたものの、クラムシェルモード(と巷では言うらしい)でMacBook Pro 16inchを使うケースがふえてきた(Flutter開発時にiOS端末にデプロイしたりすることを考えるとMacも使いたい)ために、いちいちケーブル引っこ抜いてDIPスイッチパチパチ切り替えて別のマシンにケーブルをつなぐのも結構面倒だし、とはいえキーボードを机の上に2台以上置きたくないし……という葛藤の末、MNGしてしまったのでした。

USB接続のWindows機を使いたいときはFn+Ctrl+0で接続先をUSBにした後、Fn+Ctrl+WでWindowsモードにモードを変更しなければならず、その際うっかり誤爆するとブラウザのタブが閉じられてしまうことがある以外は特に不満なし。 MacにつなぐときもFn+Ctrl+1でBT接続先その1のMacにつないで、Fn+Ctrl+MでMac向けのキー配置に切り替えることによって快適に使うことができた。

ツイートの写真にもあるように、謎に調子に乗ってカラーキートップを一緒に買ってしまったので、EscとCtrlそれぞれを新旧二台のHHKBに取り付けてみた。キャラ性が付加された感じがしてこれはこれでなかなか楽しいかもしれない。

しかし、余ったHHKB Pro2どうしよう……バリバリ現役で使えるのでもったいないが、似たような経緯でRealforceテンキーレスとMajestouch黒軸テンキーレスが転がってるので同じような運命をたどってしまいそうで悩み中……

一度死んだVRCSDK2のワールド(と、それを使うイベント)をVRCSDK3でゴリ押し再構築した話

この記事は「VRChat Advent Calendar 2020 (https://adventar.org/calendars/5102)」19日目の記事です。 お久しぶりです(?)はるです。

私は以前VRChat上でVRC-LT(https://vrc-lt.github.io/)というLT会を開催していたのですが、この会は今年半ばごろにSDK2の同期関連の挙動が変わってワールドが動作しなくなってしまったのが原因で、しばらく無期限延期状態になっていました。

流石にワールドのロジックを記述するのにSDK2のTriggerベースではこの先メンテしきれないし、SDK3にはVRC_Panoramaのような画像を取得してきて表示するような機能を持ったComponentは存在しないし、どうしよう……と思っていたのですが、先日変なやる気を起こしてゴニョゴニョしていたら案外できるのでは?という気持ちになってきたので、その話を書きたいと思います。

この記事に関連するリポジトリhttps://github.com/vrc-lt にあります。

全体的に突貫工事でガバガバなのはゆるして。

もともとのワールド

在りし日のVRC-LT on VRCSDK2の様子は以下のWebページに動画やスライドへのリンクとしてアーカイブされていますので、そこを見てもらえると手っ取り早いです。スライド画像のページめくりが同期しており、スライドを逐次読み込んだり、発表順に合わせてWeb管理画面から並び替えることができました。

https://vrc-lt.github.io/past-events.html

これらはVRChat Build 820くらいからまともに動かなくなってしまったので、SDK3で組み直せるようになるまでは一旦置いておこう……となってしまいました。

動画をコマ送りする

ときは流れてSDK3のワールドも一般的になり、C#ライクなUdonSharpが開発され、そしてSDK3にも動画プレイヤーが実装されました。

しかしVRC_Panoramaのような静止画を取得できるコンポーネントはいつまで待っても追加されないので、今あるものでどうにかならんかなーとぼんやり考えるようになりました。[*1]

スライドを外部から取得してきて表示すること自体は、とても単純なアイデアで実現できそうに感じました。一定の時間で画面が切り替わる動画を再生させて、動画プレイヤーとしては常に一時停止の状態のまま再生位置を変化させれば良いからです。

このやり方は実際に機能しました。

(ワールド自体も新たに作り直したので、ProBuilderを使ってみてうれしくなっている図)

VRCSDK3を触るのはこれが初めてだったので、同期などのUdonやUdonSharpに特有の概念がどんなものなのかを探るのが最も手間がかかるポイントでした。具体的には以下のようなポイントでつまづきました。

  • [UdonSynced] がついた変数の扱い方
    • 変数に値を代入する事ができるClientをOwnerのみに限って、それ以外のClientは原則更新しない
  • OnDeserialization() の動作
    • UdonSyncedな変数が更新されたら呼ばれる(どれが更新されたかはわからない)
      • ローカルにUdonSyncedな値と対応する変数を持っておいて、それと比較して変更を検知する
      • 変更が検知されたらローカルの値を更新するとともに必要ならローカルのComponentを更新する

UdonSharpでは変数を定義する際に、[UdonSynced] をつけることによって、値が同期されるようになります。Syncedな変数の場合、値が代入されると他のクライアントでも値が新しいものに更新され、更新されたことを通知するためにOnDeserialization()というメソッドが呼ばれます。

Syncedな変数にすべてのクライアントが値を代入するような形を取るとこの動作が何度も起きてしまって収拾がつかなくなりそうだったので、Owner以外のクライアントでは値を更新せず、他のクライアントは値の更新を受けてそれぞれのクライアント内での状態をそれに合わせて更新するというやり方が広く使われているようです。

スライド用プレイヤーを実装するときに参考にしていたUSharpVideoPlayerでもこの方法で再生開始位置等を同期していたのでこれが一般的なのかなと思っていますが、他にもカスタムイベントを送るなどの方法を用いて他のClientと通信することができるようです。

実際、この方法でトラブルが多い状態ではありつつも昨日のVRC-LT #8-alphaを一応開催できたので、今のところはこれが一番やりやすい方法なのかなーと思っています。

再生用にスライドを動画に変換する

あとは、スライドのPDF等を動画に変換してYoutube等にアップロードしてもらうだけです。

動画への変換自体はffmpegなどで行うことができますが、発表者に逐一ffmpegのインストールや使い方の確認をお願いするのも申し訳ないので、そのような準備をせずに変換できる方法が必要でした。

VRC-LTでは、発表者に専用Discordサーバーに参加してもらっており、そこで連絡をとっています。

そこで、PDFが添付されたMentionを受け取ると動画に変換するDiscord Botを用意して運用することにしました。 f:id:haru2036:20201214211523p:plain

Discord Bot向けのライブラリがあって、以前から興味のあった言語であるRustを使用して書いてみました(内部的にはxpdfとffmpegを呼んでるだけなのでRustっぽさはあまりない気もします……)。それをDockerイメージに固めて適当にデプロイしています。

Discordでやり取りをしているという前提がある現在のVRC-LTでは、こうした方法で動画の変換を行うことができるので発表者側から見てもとそこまで煩雑ではなく、動画さえ用意できれば飛び入り参加も可能なので、一応やってやれないことはないかなーと思っています。

開催する

各発表者のアバターのサイズによってスライドの操作系が使いづらくなっちゃったりとか、人数が集まるとまともにページが送れなくなるみたいな実際やらないとわからないような修正ポイントが山程見つかったので、Alpha版としての開催は正解だったなーと思っています。ひとまずトラブルも有りつつすべての発表者が発表を終えることができたので、次までに今回引っかかったところを治せるだけ直してBeta版をやろうかと思っています……(意識が低い)

おわりに

ふたたびVRChat上でLT会を行えるような状態にはなったと思うので、これからまたイベントを開催できるといいなと思っています。もしよろしければご参加ください。

https://vrc-lt.github.io/

*1: Cannyでリクエストしたときは、「Dynamic Imageという名前でもっと一般化した方法を用意するよ!お楽しみに!(意訳)」というコメントとともにチケットがクローズされているので、そのうちできるようになると思います

お家くらうど kubernetes編

突然お家にkubernetesクラスタが欲しくなったのでやってみたメモ(怪文書)

やったこと

  • ubuntuVMをいくつか立てる
  • kubeadmを入れる
  • masterのVMでkubeadm init
  • それ以外のVMで紐付けるやつ(忘れた)する
  • ホスト名変え忘れてたので変える
  • kubeadm resetしてinitからやりなおし
  • 適当にビルドしたイメージを適当に立てたコンテナレジストリにpush
  • podの設定でそれを参照
  • kubectl create
  • リブートしたらswapがまたonになっててkubeletがコケてたので直した

きょうはここまで

• 雑にkubeadmを使い雑にk8sが立った • swap入ってるとコケる • コンテナイメージはまだちゃんとおける場所がない • Volumeの扱い方は要検討 • Haskell stackのイメージはでかすぎる • ローカルで使うだけならEndpointの定義で一応外に行ける

来週つづきできるかなあ……

ベースステーションを支える技術

ノリと勢いで我が家のHTC Vive ベースステーションの固定方法を紹介 ふと思い立ったので自宅のHTC Viveベースステーションの固定方法をメモっておくことにしたので書きます。 一応全く壁に穴開けたりせず、三脚とか使ったりもせずに固定できているので、結構うまくいってるんじゃないかなーと我ながら思ってたり。

TL;DR

  • もとの部屋の環境をうまく使おうず
  • 長方形の部屋なら長辺をうまく使って正方形のスペースを確保しようず

カーテンレール

ちょうどいい場所にカーテンレールがあったので、カーテンレールの上にベースステーション付属の壁用金具を載せて結束バンドでくくりつけました。かなり安定しているのでカーテンレールがいい感じの場所にあったら第一候補になりそう。

突っ張りメタルラック

収納がなかったので突っ張りメタルラックを買いました。そのときに模様替えをしたのでカーテンレールに付けたベースステーションの対角線上にメタルラックの足が来るようにして設置し、天井付近にベースステーションの金具をくくりつけてます。

少しスペースに余裕があって、部屋の長辺に余ったスペースがある場合、この手はかなり有効だと思います。

レイアウト

長方形の6帖の部屋に机など諸々を置き、残ったスペースが正方形になるようにしています。 これによってSteamVRの設定画面によれば2.0m*2.0mのスペースが確保できているようです。

三脚を使ったりすると三脚の足のぶんだけ使えないスペースが出てきてしまいますが、カーテンレールや突っ張りによる設置だとスペースをフルに使うことができるので良いと思います。

ただ、結束バンドだけで固定してるとベースステーションの起動時にビビりが発生することがあるのでうまい具合に防振ゴムなどを挟む必要はありそうです。

引っ越したい、もののまだイケてる間取りの部屋が見つからず……

お手軽に出来合いのものを組み合わせて赤外線リモコン操作する(Google Homeもあるよ!)

この記事はCPS Lab Advent Calenderの18日目の記事です。 17日目は「ゲームパッドをMIDIコントローラーとして使おうとした」でした。

こんにちは、赤外線リモコンの機器ってなかなか多いですよね。こっちはHTC Viveを設置してしまったものだからベースステーションから出る赤外線で家中のリモコンの危機です。

さて、赤外線リモコンで操作できる機器は例えばどんなものがあるでしょう。まずエアコン、ちょっと高いPCのディスプレイ、LEDシーリングライト……

色々あるのですが、今回はLEDシーリングライトを操作できるようにしました。しかも強い先人たちの築き上げたリソースをフル活用したら、殆どコードを書かずに実現できてしまいました。(しかしお手軽ではあるものの微妙な点もたくさん有りますのであしからず)

使ったもの

ESP8266-HTTP-IR-Blaster

実際の赤外線を発光する部分はESP-WROOM-02に接続した赤外線LEDから行います。 雑にユニバーサル基板上に実装しました。汚すぎてお見せできません…… まず最初の先人の成果物をまるっと利用させて頂くポイントがこちら

github.com

このスケッチでは赤外線受光素子からの赤外線パターンの記録と指定したパターンの発光を無線LAN経由から行うことができます。

ここまでcloneしてきて書き込むだけ。LAN内からは自由自在に赤外線リモコンとして操作できるようになりました。さて、次はどうしましょう?

timer(systemd)

最初に一番やりたかったことである決まった時間に照明をつけたり消したりをできるようにしました。 無駄に大掛かりだと自分でもおもっているのですが、自宅で動いているサーバのtimerタスクでESP-WROOM-02に決まった時間にHTTPリクエストを送るようにしました。 これによって、朝目が覚める時には明るい部屋になっている上に、そろそろ寝ないといけない時間帯には強制的に照明が消えます。 悩みの種であった睡眠リズムが若干改善するかもしれません。

Google Home

さて、その後Google Homeを購入したので、こいつからも操作できたら楽しいよねと思うようになりました。 しかし、Google Home経由で操作するにはDialogFlowにしろIFTTTにしろいっぺん外に出てから戻ってくるような通信経路になります。 今回はお手軽に何も考えず適当にやりたいことを実現するのが趣旨なので、もっといい方法あるんじゃないかとか思いつつ自宅IPにDDNSのアドレスを設定し自宅鯖にnginxを立ててLet's Encryptで証明書を取得して、nginxで外からの通信を受けることにしました。

とりあえずSSLBASIC認証を設定して(IFTTTだとBASIC認証しか使えなかった気が)、IFTTTのWebHookでそのまま自宅に返ってくるような感じにしました。

反応しない

冒頭でも挙げたのですが、HTC Viveが起動している間はベースステーションが部屋中に赤外線を照射するため、赤外線リモコンが一切使えなくなります。 何度もこれで照明のコントロールができずあれーおかしいなーとか言いながら数分間立ち尽くしてました。終了すれば普通に使えるし諦めました。

まとめ

とりあえずお手軽に照明をコントロールしてみましたが、ぶっちゃけ融通が聞かないと感じることも多くこの用途ならラズパイかなんかで自前実装するほうが色々コンパクトにできて楽かもしれません。

何も考えずにググるだけでやるとこうなるよ、という例ということで見ていただけると幸いです。でも何気に実用的に仕上がったのでやって見る価値はあると思いました。

Android Design Support LibraryのSnackbarはユーザ補助機能が有効だとアニメーションしない

個人的にはあのアニメーション大好きなのですが……

Snackbarを使ったアプリケーションをデバッグ中、あのおしゃれな表示・非表示時アニメーションがバッサリなくなっていることに気づきました。

原因はアクセシビリティ設定が有効になっていることで、今回はLastPassが提供する自動入力用のサービスだったのでそれを切ればすんなりアニメーションが再生されてます。

正直LastPassは使ってるしちょっと変わったことをするアプリだと思ううえにアクセシビリティサービスでアニメーションを無効にする理由もわからなくないのですが、Snackbarだけアニメーション無効化されるのもなんだかなあという気持ちです。

ちなみに、普段からLastpass有効で使ってる→Snackbar実装→アニメーションしないことに気づく→ググるという手順を経て以下の記事に気がついたことによってこの問題の存在を知りました……

stackoverflow.com

PostmanでCookieを使いたいときはPostman Interceptorを有効にしないといけない

ただのメモ。結構ハマったので書いときます f:id:haru2036:20170611185948p:plain Interceptorをここで有効にするのを知らなくてずっと悩んでました