自習室

こもります

「採用基準」のリーダーシップ論を、メーカー企業の活動に援用する

「採用基準」という本を読んだ。 大きな方向性として学ぶところが多く刺激を受けたのと同時に、この考え方・エッセンスを自分の務める会社(日本の電機メーカー)で意味あるものに落とし込むにはどうすればよいか、自分の日常の活動にどう活かしていくか、、などについて考えを巡らせている。

メーカーでの「役職的」リーダーシップ

「採用条件」で想定されているコンサル的なリーダシップが、それ単独で、ものづくり活動を劇的にクリエイティブにしたり加速したりするわけではなさそう。(※ものづくり企業の経営を改善することはできるのかもしれない)

メーカーのものづくりにおいては、ハードのチーム、ソフトのチーム…など「チームごとの活動」がある。チームごとのリソース配分や工程分解、その優先度付け、品質向上などなど…の活動のリーディングは、たしかに誰かによって行われている。チームリーダーとか言われている人は、そのチームの範囲内においてリーダーシップを発揮しているはずだ。現存するリーダーシップを差し置いてコンサル的なそれで現場をどうにかしようというのはさすがに無理がある。

だが、ここに大きな問題があるように最近感じることが多い(だからこの本を読んだ)。それはものづくりの会社において、役職や「チーム」、あるいは「専門性」といった概念の呪縛が非常に強いことが引き起こしているように思う。

チームのリーダーが、自分のチーム内に限定したリーダーになってしまう…すなわち、上から来たお題をチーム内でうまく解くことというただ一つの目的のためのリーダーになってしまう。そして自分のチーム以外にはあまり口出しをしない。またあるいは、従来技術の延長線に乗った目標設定をし、それはたしかに専門的には唯一無二の素晴らしい進歩なのかもしれないが、対外的に日の目を見ないものになってしまったりする。

これはまさしく、伊賀氏がこの本の中で言っている「役職的な思考」によるものだ。

これはプロが互いにリスペクトし合う、ということの現れだったりもする。わかりやすいところでいうと、ハードを作ろうとすると、ソフトだけのプロダクトの場合と比べて活動の素早さや調達・品質安全に関する考え方が大きく変わる。専門家であるほど「わからないこと」についてもよく分かる。だからお互いの考え・活動のスタイルを尊重する。これは素晴らしいことなのだけが、互いへのリスペクトそのものが、リーダーシップの欠如の原因となっているようであり、どうしたものか、、と考えさせられている。

グループの中で比較的リーダーっぽい人がリーダーをする、という慣習

自分のチーム内に限定したリーダーを生み出してしまう要因一つとして、ある専門チームの中で、ある程度経験を積み「そのグループの中で比較的リーダーっぽい人」がリーダーをせざるを得ない、という慣習・流れがあると私は見ている。

エンジニアとして率いられる立場の気持ちを考えると、そのチームの活動・専門領域について熟知したシニアな専門家が、自分の上司であってほしいと考えるのは非常に自然である。無論、専門家として秀でている人が、リーダーとしても力強ければ、それに勝ることはない。もしいま時点出そうじゃなかったとしても、まずリーダーにしてしまって育てば良いという考え方もある。しかしそれらがうまく行かなかった場合に、シニアなエンジニアをリーダーに据えることには大きなリスクが伴う。

当人が「採用基準」で言うところのリーダーシップを理解していない場合:

言うまでもなく、チーム内に限定したリーダー(あるいはチームマネージャ)と化す。下手するとセクショナリズムが発動し、チーム内の局所便益(楽・安定など…)に最適化した行動を始め、プロジェクトとしての成功やアウトカムの最大化と対立すらする。

「専門性を買われて」チームのリーダーに抜擢された人は、専門性の高さ故に「出世した」と考えるため、専門性側でより頑張ろうとしてしまうというのもあると思う。これもセクショナリズムの原因の一つ。

そもそも当人がリーダーをしたくない・適性がない場合:

伊賀さんの言うところのリーダー以前に、チームのリーダーとしても辛い感じになり、チームも、当人も疲弊する(←よく見る)

(勇気を出して)専門性とリーダーシップを分けてみる

上のような弊害を起こさないために、エンジニアリング的専門性と、ものづくり組織でのリーダーシップを別々に育てる必要があると私は考えている。そして、両方持ち合わせる人材を育てる。これがものづくり企業の生き残る道である(そして、ものづくり企業だからこそ生まれ得る独自の強い人材の輩出の仕方でもある)

  • A「専門家としての職能が高い結果としてリーダーになった(抜擢された)」
  • B「専門家としての職能も高く、かつリーダーとしても強い」

この2つは全く異なる状態だ。日本的なものづくり組織は、Bの登場を夢見て大量のAを生み出し、たくさんの不幸を生んでいる。

リーダーシップはある程度、その人の性格やセンス、これまでの体験に依拠するところが多い成分だと思う。地頭の良さやエンジニアリング的スキルとは別で考えよう。ただし、これも伊賀さんが書籍の中で書いてあるとおり、リーダシップは別に天才的な才能とかではなくて、育成しうるもののはず。エンジニアリングのキャリアとパラレルにリーダーシップ育成が進むような組織構造・プロジェクト体制を作ることが重要だろう。

組織的ものづくり活動にとっての「プロダクトマネージャ」という概念の重要性

ところで、最近 Google なんかを筆頭として Product Manager/Lead という概念が生まれ、日本(のIT系企業?)にも少しずつ根を下ろし始めている。ざっくりいうと、作り・届けるもの・サービスがどんなものであるか、の全てについて一貫してデザインし責任を持つ人である。

日本では略語で混同されがちな Project Manager/Lead は、Product Lead の存在を定義した場合には、Product (/のあるフェーズ・機能)を作る~などの「活動 = Project」を引っ張る人のこと。大事なのはユーザに触れてもらう成果物である Product の責任者と、(作る)活動である Project の責任者を分離していることだ。

この2つのPMは、しょっちゅう対立するはずである。対立するのが正しい。無限のリソースを使ってでも理想的な Product を長期的なVisionに沿って描き、こだわり続ける Product Managerと、活動のコスト・期間・品質を考えて作る、という活動を達成するProject Managerが、互いに妥協せずに高いレベルで調和してこそ、良いものを良いタイミングで作り出すことができる。対立はするかもしれないが、いいものを作りたい、という思いは共有できていなくてはならない。

日本ではこれらがざっくりと「リーダー」としてひとまとめにされていることが多いように思う。これはちょうど前に、「グループの中で比較的リーダーっぽい人がリーダーをする」と書いたことと対応している。

リーダーがプロジェクト志向過ぎると「お決まりの承認プロセスとスケジュールに載せてきっちり出しました」という感じで本当に世に出す必要があるのか疑問な製品が世に出されたりする。逆にプロダクト志向過ぎると、時間をかけ・メンバーを無限に疲労させながらオーバースペックで顧客に求められない・ビジネスとして成立しないものを生み出したり(あるいは出せなかったり)する。

もちろん、中には、プロダクトリードとプロジェクトリードの両方のスキル・才能・コミュ力を兼ね備えたスーパーマンみたいな人がいたからこそ出来てしまった素晴らしい商品もあったのだろう。だが、そういうものづくりは属人性が高く、継続したり、後進を教育したり、同じスキームを他に転用できなかったりする。なので、うまく仕組み化していく必要がある。

ものづくり活動におけるリーダシップの仕組み化

この Product Manager と Project Manager は、ともに従来リーダーと言われている人を、スキルや性格・センスの特性に基づき分割し、それによって属人的だったリーダーシップを、ものづくり活動に適した形で構造化しようとしているものだと私は捉えている。

Google はアソシエイトプロダクトマネージャー(APM)つまり、、PM見習いの制度を持ち、組織的にプロダクトマネージャを定義・育成しようとしている。Google の場合、APMになるような若者は、エンジニアリングチームとの円滑なコミュニケーションのために開発のスキルも持ち合わせていることが期待され、コンピュータサイエンス(…平たく言えばプログラミング)を理解している人が多いと思われる。

しかしPMとしては「ソフトスキル」や戦略的思考、そしてもちろん最高のユーザー体験を提供することへのこだわり、などが求められ、これは開発者としての専門性とは別物だ。

Google の PM 像や「ソフトスキル」についてはこの記事が詳しい。 www.axion.zone

そしてこのプロダクトマネージャに必要とされる能力セット・性格・センスの特性は、「採用基準」でいうところのリーダーシップの、ものづくり活動版であると私は考えている。「プロダクトマネジメントのすべて」では、PMのことをこのように評している。

プロダクトを成功に導くためにプロダクトマネージャーが幅広い役割と責任範囲をもつことから、「ミニCEO」とよばれることがある。(中略)求められるのは、プロダクトの成功のために必要なこと全てに目を配り、こだわり抜くことである。

このようなリーダーシップを組織として育て、専門家のリーダーにも(その本来の専門性とは別に)身につけてもらい、伊賀さんの言うように「リーダシップの総量」を増やしていくのが、ものづくり企業に必要とされていることだと強く感じる。時勢を読んでお金等資本を転がして利益を出すようなビジネスではなく、ゼロから価値を生み出すことのできる = ものづくりができるプロが、リーダーシップも兼ね備えるのが最強なはずだし、人類社会への強烈な貢献となるはずだ。

トヨタでは「主査/チーフエンジニア」という呼称で、ほぼプロダクトマネージャに相当する職能が定義されているらしい。歴史の長い重層的な企業でどのように活躍されているのか・どのような人がなるのか・実際うまく回っているのか?なんかは大変興味があります。 https://dl1.dl.multidevice-disc.com/dl/24320-78bc54a79944978ab3077f83ae9ba39f

Zoom や Teams にマイクミュートのまま音声で合いの手をいれたい(on Windows)

背景

言わずもがなの Web 会議まつり。 私の所属企業はテックメーカーで音響系もやっておりますので、参加するメンバーのネット環境やマイク環境が比較的まともなのは助かります。

しかし、顔出しがあまり好まれないのといわゆる「ミュートお作法」で、どうも虚空に向かって声を投げ込んでいるような感覚になりがち。

Cluster という VR カンファレンスサービスには、ボタン一発で拍手とかをする機能があるのですが、それがとても良い。とても気軽にリアクションができます。話している側として嬉しいのはもちろんのこと、聴講者として入っている場合も参加感が高まるので good. 好き。

clusterhelp.zendesk.com

関連

このネタでひと記事書こうと思っていたら、かねてより尊敬している深津さんがジャストな記事を書かれていた。さすが。まさしくです。「Web会議盛り上げたい」じゃなくて「拡張現実は音声からはじまる…」で導入されてるあたりも最高。

note.com

ちなみに東大の稲見センセイは、 Comment Screen という、ニコニコのコメントシステムの汎用版みたいなやつを紹介されてて、これもとても良さそう。

note.com

深津さんの記事は Mac が前提になっていたので、この記事では深津さんの記事でされていることを、Windows(そこそこ)手軽に、無料で実現する方法を考えてみました。

手法

VoiceMeeter (Banana)

Web会議に流し込むマイク音声と合いの手SEをミックスして、さらにWeb会議に流し込めるようにしてくれる(仮想マイク化する)ミキサーと言うか音声ルーティングソフトが必要です。

Windows でフリーで使える高機能な音声ミキサーといえば VoiceMeeter (Banana) *1。ただ、Windows のオーディオ設定とセットでいじらなければならないので若干わかりにくい。けどネットにはたくさんいい記事がありますのでそのへんを参考に使えるようにします。

この記事は、双方向の通話ありの場合のルーティングについて詳細に書いてくれているので、これがわかれば VoiceMeeter マスター。

ch.nicovideo.jp

他にも、WOWの鹿野さんがより簡潔に使い方をまとめてくださっています。

kano-lab.org

ちなみに VoiceMeeter は DonationWare なのですが、私は5億年ほど前から利用させていただいているので、$30 お支払いしました。

サンプラー

次に、合いの手SEを鳴らすソフトが必要です。要件は以下の3点

  • VoiceMeeter の Input のひとつとして食わせたいので、突然 OSのシステムで鳴らさないことが選べる = サウンドバイスを選べる音楽プレイヤーが望ましいです。
  • また、パッド付きのサンプラーのような、音を登録して、押せば即鳴る、のが、合いの手SEを鳴らすインタフェースとしては良いでしょう。
  • Windows で動いて、無料。
と、その前に、PC 外で音を鳴らして Hardware Input する場合

フリーで手に入る音を鳴らす windows ソフトで、オーディオデバイスを選択できるものって案外ありません。たいていシステム音声として鳴らすことしかできないです。

一方、PCとは別の機材で鳴らして、USBオーディオデバイス(たとえばこれ)などを使ってPC に入力すれば、 VoiceMeeter が hardware input の一つとしてハンドルできるようになります。例えば、 iOS/Android 問わずフリーで使えるサンプラーアプリはたくさんあるので、適当に見繕って使えば良いと思います。

Windows 内で完結してやりたい場合(まだベストなものが見つかっていない暫定版)

上記要件を満たすものを小一時間探してみたのですが案外無くて、暫定ですが VLC media player に行き着きました。

VLC メディアプレイヤーは、サンプラーとしての要件を満たしていません。以下の点は改善の余地があります

  • パッド状のUIがなくてダブルクリックが必要
  • 複数音鳴らすこともできない
  • 音の素材ごとにボリュームの調整ができない(音素材ごとのボリューム調整は多分結構だいじ)

Windows で使える、フリーの、オーディオデバイスが選べる、パッド上のUIを持つ、いわゆるサンプラーアプリをご存じの方がいたら教えていただきたいです。

VLC media player を SE プレイヤーとして利用するためのセッティング

  • Tools > Preferences > Audio Settings から Device で VoiceMeeter Aux Input を選択。これで、 VLC で再生した音が、 VoiceMeeter に単独で拾われるようになります。

f:id:AMANE:20200516135652p:plain

  • Tools > Preferences で Show Settings All にチェックをすると詳細設定が出てくるので、
  • Playlist > Play and Stop にチェック。 これで、プレイリスト中の曲が次々再生されず、一曲再生されるごとに止まるようになります。

f:id:AMANE:20200516140028p:plain

  • 合いの手SEとして使いたい音声データを Playlist に突っ込んで、鳴らしたいときにタイトルをダブルクリックして再生します。このプレイリストは保存して繰り返し使えるようにしておくと良いでしょう。

f:id:AMANE:20200516140514p:plain

ルーティングと利用法

VoiceMeeter をマイク音声と上記SEプレイヤーをミックスして仮想マイクとして出力する際のルーティングは以下のようになります。

まず概念としてはこんな感じ

f:id:AMANE:20200516145819p:plain

次に、実際のUI上の設定としてはこんな感じ。

f:id:AMANE:20200516145451j:plain

Virtual Input1 (OSが鳴らす音)について、聴講者として合いの手を入れる側ではなく、プレゼンターとしてプレゼン中に動画を流したりしたい場合は B1 へのルーティングを ON にすると良いでしょう。ただし、 Zoom などのシステム側でサポートしてたりもするので、場合によっては混乱するかも。このへんはこの記事では割愛。

利用法

Zoom や Teams 上では常にマイクミュートを解除しておく

通常は、 VoiceMeeter 上で Hardware Input 1 (MIC) を Mute しておいて、話したいときだけ Mute を解除して使う。

Virtual Input 2 (Aux) の Gain は賑やかしとして適切なボリュームになるよう、適宜調整した上で、有効にしっぱなしにしておく。

その上で、ナイスなタイミングで適切な賑やかしを VLC で再生、再生、再生!

以上!

さいごに

という感じで、Web会議の沈黙を破り、にぎやかしを入れるシステムが出来ました (on Windows)

これを使って、会社の会議を盛り上げていきたいです。

*1:無印と Banana は使える IN/OUT 数の違い。ここでは Banana をつかいます

Visual c++ の同一ソリューション内ライブラリ参照と、ライブラリプロジェクトへの静的リンクライブラリのリンクの仕方。

概要

Visual Studio はエディターとして超優秀だけど、ビルド時の「追加の依存ファイル(静的リンクライブラリなど)」の指定や、インクルードパスの指定をする「プロジェクトプロパティ」がとてもわかりにくいし、それをわかりやすくしようとした結果生まれた .props ファイルによるプロジェクトプロパティのファイル定義がまたややこしいってんで、なにかちょっと不慣れなことをしようとしたり、古いOSSを新しいVSで使おうとすると痛い目に遭いがち。

今回はそれげな話の一つとして、実務で遭遇した以下の2件についてメモを残しておきます。

  1. スタティックリンクライブラリを作るプロジェクト(PrjS1)と、それを使って動く .exe を作るプロジェクト(PrjE)、の2プロジェクトを持つVisual Studio の一つのソリューション(Sln1)において、PrjEがPrjS1.libを使うケース
  2. 単独のスタティックリンクライブラリを作るプロジェクト(Sln2/PrjS2) を用意し、PrjS1.libが PrjS2.lib を使うケース

図にまとめるとこんな感じ

f:id:AMANE:20190606222454p:plain

それそれどのように "参照" やリンクを行うのか、についてまとめておこうと思います。

前提知識

私も記憶喪失になりがちなので、大事な前提知識として、DLLやLIBってなんやねん?を詳細に説明して下さっている記事へのリンクを貼らせていただきます。

kamino.hatenablog.com

(1) ソリューション内の参照

ソリューション内のプロジェクト参照とは何か。

こちらに記載があります。

プロジェクト内の参照の管理 - Visual Studio | Microsoft Docs

Visual Studio は、プロジェクトへのパスが指定されると、アセンブリを見つけることができます。

とありますが、.lib ファイルをビルドするプロジェクトを参照した場合は、結果の .lib ファイルを見つけることが出来る、と言う意味ですね。

ソリューション内の別のプロジェクトへの参照の仕方

  • プロジェクトを右クリック → 追加 → 参照 → ソリューション内の .lib ファイルを作るプロジェクト名にチェック
    • 参照右クリック→参照の追加、でも同じ

f:id:AMANE:20190606224220p:plain

似たような項目で、プロジェクトの依存関係というのがあります。

  • ソリューションを右クリック → プロパティ → 共通プロパティ → プロジェクトの依存関係

f:id:AMANE:20190606224330p:plain

こちらは、同一ソリューション内のプロジェクト間のビルド順を定義するための設定です。試しに PrjEPrjS1 に依存するよう指定すると、ビルド順こそ最適化されますが、 PrjS1 中のコードの header を持ってきて使おうとすると、 未解決の外部シンボルが参照されました のようなエラーが出ます。これは無論、 PrjS1.lib がリンクできていないからです。

方法: プロジェクトの依存関係を作成および削除する - Visual Studio | Microsoft Docs

逆に、先にPrjEからPrjS1を参照すると、自動的に PrjEPrjS1を依存することもプロパティに追記されます。

ソリューションの構成とプラットフォームの自動反映

このようにプロジェクト参照で引いている .lib は、構成(Debug/Release)やプラットフォーム(x86/x64) をソリューション全体で変えたとしても、利用する側の PrjE に対し、適切な構成・プラットフォームで作られた PrjS1.lib を渡してくれます。

それを確認するために、以下の手順で意地悪をしてみます。

  • 一旦ソリューションをクリーン
  • Debug/x86PrjS1 をプロジェクトのみビルド
  • Debug/x86PrjE をプロジェクトのみビルド → 正しくビルドされる( PrjS1.libデバッグビルド物を引けている)
  • Release/x86PrjE を再度プロジェクトのみビルド → ビルド完了出来ない(この時点ではPrjS1.lib** のリリースビルドが存在しないため)
  • Release/x86PrjS1.lib をプロジェクトのみビルド、Debug/x86 でビルドした PrjS1.lib を削除
  • Release/x86PrjE を再度プロジェクトのみビルド → 正しくビルドされる

その間、プロジェクトプロパティ類は一切編集しませんでしたがこのように、適切な .lib ファイルを引いてくれることがわかります。

ちなみに細かい話ですが、ソリューションエクスプローラ上で PrjE / 参照 / PrjS1 を選択してプロパティウィンドウを見ると、構成が Debug の時に Release\PrjS1.lib が完全パスとして指定されていたり、その逆だったりすることがあります。これはおそらく Visual Studio の表示上のバグで、実際、Visual Studio を再起動すると、正しい .lib ファイルのパスが記載されています。

f:id:AMANE:20190606224523p:plain

(2) ソリューション外のビルド物である .lib ファイルを、自分のライブラリ(.libを出力する)プロジェクトに追加する

他所のリリース物を自分のプロジェクトに取り込んで使う場合、こちらの方が良くあると思います。特に、 PrjE(.exeを作るプロジェクト)PrjS2(.lib) をリンクする場合は、 プロジェクトプロパティ / リンカー / 追加のライブラリディレクトリ入力 / 追加の依存ファイル(.libファイル) を指定する、という「VSおきまりの」手続になります。

qiita.com

今回やりたいのは、静的リンクライブラリを出力するプロジェクトに外部の静的リンクライブラリをリンクする、ことです。基本的には上記と同じなのですが、 .exe を出力するプロジェクトと .lib を出力するプロジェクトで、若干プロジェクトプロパティの構成が異なっています。 .h ファイルのインクルードに関しては、 .exe のプロジェクトの場合と同様に、 C/C++ / 全般 / 追加のインクルードディレクトリ に使いたい .h ファイルのあるディレクトリを指定します。

ライブラリファイルの指定は、ライブラリアン / 全般 タブ中の 追加の依存ファイル追加のライブラリディレクトリ を、それぞれ構成・プラットフォーム毎に正しく設定する必要があります。これにより、構成・プラットフォームを変えても、PrjS1 はそれ毎に正しい .lib ファイルをビルドしてくれ、最終的に PrjE は正しくビルドされることになります。

f:id:AMANE:20190606231518p:plain

所感

昔ながらの静的リンクライブラリのロードの仕方として、 #pragma comment(lib, "filename.lib") 式もありますが、その他の dll ファイルの置き場などすべてプロジェクトのプロパティから指定しているので、.lib` ファイルもプロジェクトプロパティの指定でやりきりたいなぁと私は考えています。コード中に書く方がマルチプラットフォーム開発では良いことも多いかも知れませんが、それはそのときに。

[VC++] リンクするライブラリファイルをソースコード内に記述する | あみだがみねのもろもろ備忘録

これまでかなり適当にやって、何となくビルドできればおっけーって感じで通ってきてた内容を一通り整理できて良かったです。

大学の研究室で、ラボ全体で使うつもりで有料のウェブサービスを契約するのがなかなか難しい

序文

とあるラボの立ち上げ期にがっつりかかわらせていただき、ちょっとしたシステムアドミンみたいなことをずーっとやっています。

とても特殊な経験をたくさんさせてもらったので、誰の役に立つかはわからないけど気が向いたときにメモとして残しておきたいと思っています。

  • G Suite for Education はラボ単位でも申し込めて、とてもとても良いよ、って話
  • GitHub Education もラボ単位で申し込めて、とてもても良いよ、って話
  • Slack はすげー学割が利くし、最近検索が少しずつ改善してきているので、有料プラン申し込もうぜって話(今日の話と少し関わりがある)
  • esa.io教育機関で申請すると無料で使えるぞ、って話
  • 大学が包括契約している様々なソフトを見逃すな!って話(c.f. UTokyo MATLAB Campus-Wide License)

などなど。けど、良い話より難しい話の方が、結論にたどり着くまでのいろいろが「知見」って感じなので、今回はその中から一つ、どうしてもWikiを無料にしたかった話をメモしておきたいと思います。

本文

何の話?→ ラボ Wiki の話。

研究室生活と研究活動に関するノウハウを集めるナレッジベースを作ろうと、1年半あまり試行錯誤をして、結局今は esa.io にたどり着いています。そこまでは…

と、主に3ステップを経て、いや、これじゃいかんと思っていわゆる普通に使える wiki 的な物を探して (とても色んな判断があって) esa.io を使っています。使い始めてから半年ほど経っていますが、学生さん他ちょいちょい記事を足したり修正してくれていて回っている気がします。

これは話の結論でもあるのですが、無料であること と、自サバ管理をしないこと が最優先事項でした。この記事はもしかすると esa の中の人にも読まれてしまうかも知れないので若干心苦しいのですが、無料であることがとてもとてもとても大事だったのです。それ以外の純粋な「研究室ナレッジベースのサービス選択」については、ここでは割愛します。本記事の趣旨は「大学でサブスクリプションの有料プラン契約厳しぃ…」ってことです。

自サバ管理をしないこと

理系の研究室には、1人や2人たとえその研究室がそっち系では無かったとしても、ウェブサービスの構築に詳しい人が居たりします。私は社会人博士としてラボに来ていて、業務で GitLab を立てたり、プロジェクト用に Wiki を運用したりしてたので少々出来るようになってしまっていたのですが、そのときの経験から、ラボでは自サバでのサービス運用はしたくないと決めていました。理由は以下の通り

  1. 大学研究室での活動の本分は研究である
  2. 大学研究室の構成員は会社とは比べものにならないくらい高速に入れ替わる
  3. 大学研究室のハードウェアは、本当に予想外の理由で止められたり壊れたりする

もちろん一番の理由は1ですが、2と3については、ラボに来てからそれはもう思い知らされました。(この記事では割愛)

また、3だけはハードウェア的な意味でもオンプレミスを意味していますが、たとえAWSとかさくらのVPSでやろうとも、1, 2に関しては変わりません。

無料であること

私個人としては、良いもの、クリエイティビティや品質、生活の質の向上をもたらすサービスには対価を支払っていきたいと考えています。(大事)

しかし、大学の経費精算の融通の利かなさ と、人の出入の不確定さ がここに立ちはだかります。

年度末にクレカは使えない件

ウェブサービスの多くはクレジットカード払いだと思います。それ自体は問題無いです。大学は「見積・納品・請求」書3点セットで公費による「後払い」が基本なのですが、(昔はどうだったかわかりませんが少なくとも私の居る研究室では)教授名義のコーポレートカードで研究にかかわる買い物をさせていただくことがあります。

問題は、年度末にクレジットカードを使うことを極端に嫌がられると言うか、実質禁止であることです。公費のほとんどは年度毎にしめますので、「使ったのが3月だけどカードの引き落としは4月」みたいなのは許されないわけです。ウェブサービスが、利用状況で変動して毎月引き落としをするスタイルだと、これが問題になります。3月だけ支払えなくなってしまうのです。

人の出入が不確定な件

これはもしかすると弊研究室固有の問題かも知れませんが、インターンやアルバイト・客員の研究員を多数・随時受け入れているため、 いつからいつまで、ラボのメンバーが何人居る というのが確定せず常に変動します。 たとえば、いまわれわれのラボの Slack には 60余名のメンバーがいますが(強制参加のチャネルのメンバー数)、正式に所属のある人は、先生達 + いつもいる研究員+ 事務系職員 + 学生 で 40名程度のはずです。 Slack は非アクティブなユーザには課金されませんが、すべてのサービスでそうと言う訳ではありません。

大学の経費生産的には、極力「これにいくらかかる」というのが前もってわかっているのが望ましいです。

さてここで、Slackは変動するのに有料でやってるんでしょ?という件が出てきます。これについては答えは明確で、Slackくらい利用者側(我々)が価値を明確にわかっているならゴリ押す です。Slackはそれに加えて、学割が強力に効いて、案外めちゃくちゃ高くはならないことと、年払いに対応していること、が敷居を下げてくれています。

我々は、どのWikiが良いのか探索し、ラボとの相性が良いのかも模索しつつ、ソフトランディングさせていく必要がありました。ラボに合わないと感じたら途中で切り替える可能性もあったので、突然大きな支払をするのも気が引けました。

有料だと、んー、この人はもう不要かな?などと管理者が気を利かせてメンバー管理する必要が出てきます。管理者がラボの構成員全体に確実に目が行き届いているとは限りませんので、これは結構な負担となります。無料だと、とりあえず使いそうな人全員ユーザとしてぶち込んでおく、が可能なので、この辺の負担が減ります(その代わりセキュリティ面のリスクはあがるのですが…)

無料だとすべてが解決する(残念なことに!)

というわけで、非常に心苦しいのですが、無料であることは(その導入の手続や、支払の手間なども総合的に見ると)極めて重要ということになります。

Qiita Team と Notion は傍から見ていてとても良さそうでしたが、無料で導入できるサービスと比較すると、二の足を踏んでしまいました。

ここまで書いておいて改めて強調しますが、良いものにはお金を払うべきだし、大学の研究室もそれが完全に不可能なわけではありません。(大学の会計に詳しい人は、上の記事を見て2,3個抜け道を思いついたかと思います)しかし、導入と維持の楽さ を考えて、無料の物をえらんで「しまって」います。そしてこの選択の最大の問題は、 esa.io さんも別に慈善事業として通常無料でやっているわけでは無く、アカデミックプランとして特別に割引をしてくださっている状態なので、経営には少なからず影響を与えているでしょうし、いつまでこの状態が続くかも我々はわかりません。

結文

冒頭にも書きましたが、 esa.io は充分に使いやすいナレッジベースで、ラボでしっかり使われています。大変助かっています。大学の会計の融通のきかなさは「なんとも言えないけどつれぇ」って感じです。メモは以上です。

SkyWay JS SDK の TypeScript 型定義ファイルを DefinitelyTyped にコミットした話

この記事は SkyWay Advent Calendar 2018 の13日目の記事です。

経緯

f:id:AMANE:20181213093355p:plain

研究室で作っているシステムで WebRTC/SkyWay を活用させて頂いたのですが、気が向いてすべて TypeScript にしてしまいました。

開発開始当初は、その当時の DefinitelyTyped にあがっていた Toshiya Nakakura さんの型定義を使っていたのですが、あちこち細かい部分がメンテされていなかったので、トランスパイル時に結構エラーがはかれていました。SkyWay JS SDK に対する単純な型定義不足に加えて、 TypeScript 3.0 前後から WebRTC とその周辺に関する DOM の定義が徐々に TypeScript の標準に組み込まれて、 /// <reference types="webrtc" /> としている部分が多重定義になっているものもあったりしたのが原因です。

そこで、思い切って自分で型定義ファイルをつくってみて、Pull Request を出して、無事(*)マージしてもらえました

コード

リポジトリはこちらです

DefinitelyTyped/types/skyway at master · DefinitelyTyped/DefinitelyTyped · GitHub

これまでも何度か型定義ファイルをコミットしてきた(余談)のですが、勉強不足でよくわかってないことも多い気がします。が、以下の方針で書いてみました。

html 中で CDN から最新の skyway-latest.js をロードして利用する。

モジュール周りは最新の仕様に私がついて行けてなかったり、さまざまなパタンに対応しなければならないので考えないことにしました。ある意味最も「べた」な手法として皆が納得して(諦めて)くれるだろう手法にとりあえず対応しておく、という考え方です。異論は大いに認めますので、どなたか改善策を教えて下さい。。。

@types/webrtc を捨てる = TypeScript 3.0 利用とする

以前の型定義には /// <reference types="webrtc" /> と言う記述がありました。これは、かつての typescript には、 RTCほげほげ のような WebRTC 関連の型定義がほとんど無かったため、それを補うための型定義群を読み込む物でした。(参照→ DefinitelyTyped/types/webrtc at master · DefinitelyTyped/DefinitelyTyped · GitHub)これらは今(ちゃんと確かめてないけどたぶん TypeScript 3.0 あたり)では ts 公式の lib.dom.d.ts にきれいに定義されていて不要になりました。

もちろん、 SkyWay のドキュメントを読むと、あちこちに RTCほげほげ が出てきます。これが、 TypeScript の lib.dom.d.ts の記述と矛盾が無い様に書いていきます。

不安点

自分の不勉強が原因ですが、今回 namespace 等を利用していません。型定義を書いたのがちょっと前のことなので詳細な理由を失念してしまったのですが、はじめそうしようと思っていたのに上手く出来なくてやめました。

これのせいで、万が一他のライブラリとクラス名等かぶってしまうと大問題です。これについては どなたか助けてください(懇願)

手続

ここからは、本家にマージされるまでの手続について書いていきます。

制作

  • ドキュメントコードをみながら、自分の手元で skyway/index.d.ts を書く
  • 自分のプロジェクトで使い続けて、問題が無いことを日々確認し続ける (トテモダイジ)
  • DefinitelyTyped が最新になるよう pull してきて、上記 skyway/index.d.ts を突っ込む。
  • 自分の変更内容を既存の test.ts にも反映させる。
  • 僭越ながら、skyway/index.d.ts のヘッダ部に、自分に関する記名をさせて頂く

テスト

  • DefinitelyTyped プロジェクト内で npm i して、テスト等に必要なパッケージを取得
  • npm test (このコマンドを叩きなさい、というのは DefinitelyTyped リポジトリの READMEには書いて無くて、後で出てくる PR のコメントにはしろ、と書いてある)
  • あらためて npm test
  • npm run lint skyway して、テストコードをチェック。(これは、DefinitelyTyped の README 中に説明がある)
    • ERROR: 31:44 no-angle-bracket-type-assertion Type assertion using the '<>' syntax is forbidden. Use the 'as' syntax instead. と言うのが出るので修正。

Pull Request

  • コードを自分のリモートにプッシュ。
  • Pull Request してみる
  • コメント欄がテンプレートで自動生成されるので,チェックボックスを埋めたりしてPR→参照
  • Travis CI が走ったりして問題ことを確認(基本は、上でやったテストと同じことをしている模様)
  • メンテナーのチェック待ち状態になる

Merged

  • typescript-bot くんが @nakakura さんに review 依頼をする
  • 1週間音沙汰が無いので、 maintainer におはちが回ってくる。
  • そこから二日でマージされる

という感じ。自分でもずっと使っているコードなので嬉しかったです。

最後に

冒頭に紹介したものと、もう一つ別のプロジェクトでもこの型定義ファイルは使っているので、そこそこ大丈夫だとは思うのですが、特に名前衝突問題とか、改善点があったら是非 DefinitelyTyped に突っ込んでみてください。あるいは私に直接指摘して下さっても結構です。みなさんにとってより使いやすい物となりますように!

余談

TypeScript に関して過去に書いた記事のご紹介

izmiz.hateblo.jp

github.com

RealSense SDK 2.0 を自力でビルドして、C++やUnityで使う@Windows

基本的な導入に関してやったことのメモ。

これを試したかったので、最新の development ブランチをビルドすることを目的とします。 unagi (@UnagiHuman) | Twitter さんありがとうございます!

筆者利用環境

Quick Start

まずは自分でビルドせず、動作確認をします。Windows Distribution に従う。

  • GitHub Releases から最新の Intel.RealSense.SDK.exe をインストール。
    • これでカメラ精度を見る Depth.Quality.Tool.exe も、 可視化ツール Intel.RealSense.Viewer.exe もインストールされます
    • ちなみに、Releases にある Source code (zip) は、リリース時点のコードをまとめた物。
  • Intel.RealSense.SDK.exe のインストールでドライバもインストールされるので、D415/D435 を刺してWindowsが認識することを確認。
  • Intel.RealSense.Viewer.exe を起動
    • 2D でカラー・デプス・IRなどが表示されることを確認
    • 3D でポイントクラウドが表示できることを確認
  • サンプルのプロジェクトをビルドしてみる

C++ で開発する

コードを clone してきたら development ブランチに切り替えておく。

自分で realsense2.dll をビルドする

今回の記事には二つ dll が登場します。

  • realsense2.dll は、D415/D435 などを使う為のダイナミックリンクライブラリ。 c++ でも C# でも使います
  • LibrealsenseWrapper.dll というのもあとから出てきます。こちらは Unity で使えるようにする為の、Managed のプラグイン。 Unity および C# (Windowsプログラミングとか) でRealSenseを使う時に使います。

ここは realsense2.dll の話。ここに書いてあるのをやる→ Windows 8.1 & Windows 10 Installation

注:BUILD_CV_EXAMPLE などのビルドオプションが正直よくわかってないのですが、問題なく使えています

  • CMake は利用環境向けのソリューションファイルを生成するだけなので、その後各環境でビルドして始めて dll なりが作成されます
  • Example や Tools も一緒にビルドするので、その中で realsense-viewer.exe 等が動く事を確認する。

改めてC++のサンプルを読んで、ビルドしてみる

(例)上記でビルドした結果のディレクトリの中の examples ディレクトリ中の ReleaseExamples.sln を起動して、 rs-pointcloud プロジェクト等を単体でビルド、実行。など。

Unity で開発する

ここに書いてあることをやります→ Unity Wrapper for RealSense SDK 2.0

ビルド済のUnity用のdllを使う場合は、初めにインストールした C:\Program Files (x86)\Intel RealSense SDK 2.0\bin\x64 あたりから取ってくる

LibrealsenseWrapper.dll をビルドする

今回はここが目的。 Unity ラッパー用の dll を最新の development ブランチのコードでビルドする。

VS2017でビルドする場合、.NET Core 2.x SDK のインストールを事前にお忘れ無く

VS2017 でビルドすると .net2.0 向け、 .Net3.5 向け、.Net 4.6.1 向け~みたいな感じで複数の .dll が作成されますが、現状のUnityは 3.5 だった気がするので net35 のフォルダから dll を持ってきて使います。

Unity のサンプルを動かす

以上

これで C++ と Unity で開発できることが確認出来ました。おしまい。

Kinect v2 のデプス画像をそのままの解像度で点群としてUnityで表示する

f:id:AMANE:20171227222450p:plain

できあがった物がこちら

youtu.be

はじめに

遙か遠い昔(3年前) Kinect v2 のデプス情報を Unity で描画するシリーズをやっていました

前者では、単純に画像を表示しただけでした。後者ではポイントクラウド風の描画にチャレンジしていますが、当時はUnityの仕様的に、またマシンスペック的に点数を間引かざるを得ませんでした。

2017.3 の新機能「32 bit Mesh index buffers」

この新機能の登場で、65536点以上のメッシュを一つのオブジェクトとして利用出来るようになりました。

先に keijiro さんがこの機能を利用して、PCLのデータをインポートするエディタ拡張を作られていて、これが出来るなら Kinect V2 のデプスデータも似たような感じで扱えるのではと思い、今回のネタに着手しました。

github.com

大まかな方策

以下の作戦で行けると踏んで作業を始めました。結果、おおよそ行けました。

  • Kinect v2のデプスデータは画像の形式で得られる。各ピクセル輝度値(= 奥行き)に基づいてVertex Shader で点を動かす
  • Kinect v2 は 512x424 = 217088 点のデータなので、32bit のインデックスに収まる。これを一つのメッシュとして描画する

イメージは下の図のような感じです。大きな値ほど、遠くに頂点が移動します。

f:id:AMANE:20171226210541p:plain

実装 - C#の部分

作成したプロジェクトを公開しています。

github.com

ビルド・実行

ビルド・実行の仕方については、上記リポジトリの Readme.md に記載しています

512x424 頂点のメッシュを用意する

f:id:AMANE:20171226214001j:plain

初めBlender でそのようなデータを用意しようかと思ったのですが、柔軟で良いし勉強になると思いコードで作ることにしました。こちらの記事を参考にさせて頂きました。

上を参考に書いたコードはこちらになります

詳細はコードを読んでいただきたいのですが、ポイントだけ整理しておきます。

32 bit Mesh index buffers を有効にする

2017.3 から追加された 32 bit Mesh index buffers を有効にするために、以下の指定を行います。これで、頂点数が32bit… 4,294,967,296 まで拡張されます。

mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
テクスチャ座標を 0~1 ではなく、半ピクセル分シフトさせる。

これにより、すべての頂点とすべてのデプス画像の画素を1対1で対応づけます。

Vector2[] uv = new Vector2[w * h];
for (var y = 0; y < h; y++)
{
  for (var x = 0; x < w; x++)
  {
    uv[y * w + x] = new Vector2(((float)x + 0.5f) / (float)w, ((float)y + 0.5f) / (float)h);
  }
}
mesh.uv = uv;

ただしこの工夫、やらなくてもぱっと見差がありません。シフトをやらない方の関数も一応用意しました Mesh MeshGenerateNormal(int w, int h, float pitch)

頂点のみ描画する(ポイント指定)

こちらの記事を参考にさせて頂きました。 この記事のスクリプトを、メッシュを含む GameObject に貼り付けるだけです

Kinect v2 のデプス画像データを、16bit の画像として上記メッシュに貼る

f:id:AMANE:20171226214142p:plain

デプスのデータを取ってくる部分は、 Kinect for Windows SDK 2.0 Unity Pro Add-in のサンプルままですので説明は割愛します。できあがりのコードを見つつポイントだけ説明します。

ushort 配列としてデプス画像を取得する

デプス画像は ushort の値を1ピクセルとして、512x424 要素の配列で表現されます。ushort は 2byte = 16bit です。

// L29
_Data = new ushort[frameDesc.LengthInPixels];

// L53
frame.CopyFrameDataToArray(_Data);
Unity のテクスチャデータにする

Unity には GRAY 1ch 16bit 深度のテクスチャとして TextureFormat.R16 があるので、これを使います。

// L30
_RawData = new byte[frameDesc.LengthInPixels * 2]; // ushort 配列を byte 配列として扱う
_Texture = new Texture2D(frameDesc.Width, frameDesc.Height, TextureFormat.R16, false); // R16 の形式でテクスチャを用意する
// L58
Buffer.BlockCopy(_Data, 0, _RawData, 0, _Data.Length * 2); // ushort 配列をそのまままるっと byte 配列にはめ込む
// L62
_Texture.LoadRawTextureData(_RawData); // 毎フレーム、byte配列を元にテクスチャを更新する
_Texture.Apply();

実装 - Shaderの部分

これで、メッシュを動かすのに必要な情報は、シェーダ側に渡されました。ここからはシェーダでの記述になります。できあがりのコードは以下です。

このシェーダでは、メッシュの頂点数とテクスチャの画素数が一致していることを前提として、その画素数 = 頂点数分だけ vertex shader がまわり、各頂点を画素のデータに基づき奥に動かす、と言うことをしていきます。ここも重要な箇所だけ見ていきます。

奥行きデータを再構成する

_Displacement は奥行き感を調整するための係数です。用意したメッシュのサイズなどと照らし合わせて適宜調整して下さい。(実際はMaterialの inspector から調整出来ます)

// KinectDepthBasic.shader L72
float d = col.x * 4000 * _Displacement;

4000 という定数がありますが、これは今回他のテクスチャの使い方も試したときの名残ですのであまり気にしないでください

デプス画像座標系から、空間に展開する

CoordinateMapper.MapDepthFrameToCameraSpace が使えない件

本来 Kinect v2 SDK には、 CoordinateMapper.MapDepthFrameToCameraSpace という関数があり、これを使うことでカメラの正確な諸元によって深度画像を3次元上の点に変換出来ます。(以前書いた記事ではそれを使いました

しかし今回は、1ch 16bit テクスチャとしてシェーダに送り込みたいので、事前に変換してしまうと、以下の様な問題が起きます

  • 1点につき xyz それぞれ float の値として表現されてしまう
    • これはデータをchar形式とかに圧縮させることで回避可能だが…
  • CoordinateMapper.MapDepthFrameToCameraSpace の結果はそもそも、 CameraSpacePoint という実質 Vector3 形式の配列で与えられるため、圧縮作業を行うためには要素数だけ for 文を回す必要がある。for文を回した時点で、高速化は見込めない。

というわけで、今回は C# …というかSDKの層での3次元展開は諦めます。

Vertex Shader で模擬して展開する

正確では無いかも知れませんが、「それっぽく見せたい」程度で良ければ、自力で変換してしまえば良いです。図を見ながら説明します。

f:id:AMANE:20171226223839p:plain

水平面でまず考えますが、垂直面も同じです。 Kinect V2 のデプス画像の水平視野角は 70deg なので、画像の左端のx座標を 256 (=デプス画像横幅512の半分) と置いたとき、デプス画像は D= 365.6 の高さの四角錐の底面に投影されている、と表現できます。

各画素について、Kinect v2 から得られるデータとして、画像上でのX軸の座標を x , 奥行きを d とすると、実際のX軸座標は x' = x * d / D で表すことが出来ます。

これをy座標についても行います。実際のシェーダの記述は以下の様になります

// KinectDepthBasic.shader L57
v.vertex.x = v.vertex.x * d / 3.656;
v.vertex.y = v.vertex.y * d / 3.656;
v.vertex.z = d;

(おまけ)奥行きに合わせてHueを回して着色する

f:id:AMANE:20171227212959p:plain

このままだとすべての点が単色で表示されます。空間中に点があるのでこれでもわかりますが、せっかくなのでより奥行きがわかりやすくしてみます。

hsv 表色系の hue の値を奥行きに連動させるようにします。 0~1 でhue が虹色のように一周し元の色に戻ってきます。

// L25 vertex shader で位置情報をもとに色を計算して、fragment shaderに渡せるよう構造体に color の情報を加える
struct v2f
{
  float2 uv : TEXCOORD0;
  float4 vertex : SV_POSITION;
  float4 col : COLOR;
};

// 中略

// L40 HSV から RGB に変換する関数
// 参照→ http://www.chilliant.com/rgb2hsv.html

float3 HUEtoRGB(in float  H)
{
  float R = abs(H * 6 - 3) - 1;
  float G = 2 - abs(H * 6 - 2);
  float B = 2 - abs(H * 6 - 4);
  return saturate(float3(R, G, B));
}

float3 HSVtoRGB(in float3 HSV)
{
  float3 RGB = HUEtoRGB(HSV.x);
  return ((RGB - 1) * HSV.y + 1) * HSV.z;
}

// 中略
// L86 
// 距離に応じた色をつけてあげる
float3 hsv = float3(1, 1, 1);
hsv.x = v.vertex.z % 1.0;
float3 rgb = HSVtoRGB(hsv);
o.col = float4(rgb.xyz, 1);

実装は以上です。

最後に

制約

今回の実装にはいくつか制約がありますので、ご注意下さい。

  • Kinect SDK の公式な Coordinate mapping をしていないので、点群の位置が不正確
  • Color 情報と点群のマッピングもしたいけど、それができる設計になっていない(自力でシェーダ内で実装できるか?)

感想

しかし、結果としては高速に大量の点を描くことが出来るようになったので満足です。メディアアート的なアプリにはもってこいなのではないでしょうか。

上記制約を解消したり、実装面でイケてない所とか見つけた人、これを使ってなにかおもしろいことをやった人がいたらぜひおしえてください〜