ラズパイ3 と Wii リモコンをつなげる

台風が近くまで接近しているので、非常に眠いので眠気覚ましに。

世の中は任天堂スイッチの世界なので、Joy-Con で操作することが多いと思うのですが、Joy-Con はちょっと高い。正規版だと 8,000円位しますね。互換機?(バイブレータがないらしい)の場合だと、もうちょっと安いみたいなのですが、まあ、手元に Wii コントローラがあるし、試しにつなげてみようというところです。

以前、ラズパイに Wii コントローラをつなげようとしたとき、古い Wii リモコンだとうまくいくのですが、新しめの Wii リモコンプラスだとペアリングがうまくいきません。Bluetooth 側のプログラムを改変すれば、接続はできるのですが、それがいいのかどうか不明だったので放置状態でした。

bluetoothctl と xwiimote を使う

ラズパイ3 に xwiimote を入れて使います。
ラズパイ3 の Raspbian には既に bluetooth に接続するための bluetoothctl があります。



sudo apt install bluez

した後で



bluetoothctl

を実行します。プロンプトが出るので、



power on scan on

で接続先の Bluetooth 機器を探します。

このときに、Wii リモコンの裏側の赤いボタンを押して、接続待ち状態にしておくと、Nintendo RVL-CNT-01-TR のデバイス名が出てきます。ここに出てくる ID を使って、



pair 9C:E6:35:04:51:4A connect 9C:E6:35:04:51:4A trust 9C:E6:35:04:51:4A

して接続をします。

これで、Bluetooth 接続状態にしておいて、xwiishow コマンドを使います。



sudo apt install xwiimote

してインストールした後に、



xwiishow 1

で Wii リモートの操作画面を表示させます。

A,Bボタンの操作や、加速度センサー、IRセンサーの値が表示されています。

詳しい使い方は、下記を参照

XWiimote – ArchWiki

どうやって Wii リモコンの処理ををするのか?

Linux なのでデバイスはファイルとして開かれるので、/sys/bus/hid/devices で調べられるそうです。



pi@raspi3:~ $ ls /sys/bus/hid/devices 0005:057E:0330.0002 pi@raspi3:~ $

たぶん、xwiishow のあたりから API が出てると思うのだけど、これは後で。

コードがここで公開されています。
GitHub – dvdhrm/xwiimote: Open Source Nintendo Wii Remote Linux Device Driver https://github.com/dvdhrm/xwiimote

PC の場合は、WiimoteLib というライブラリがあるそうです。

Siv3DでWiiリモコンを使う – Qiita

カテゴリー: 開発 | ラズパイ3 と Wii リモコンをつなげる はコメントを受け付けていません

ラズパイ以外でもROS2してみよう(PINE A64編)

去年の年末 年末なので ROS を調べてちらほらと | Moonmile Solutions Blog 以来さわっていない、ROS2 なのだが、通信まわりだけでも再構築しておこうと思った記録を残しておきます。

ROS2 のインストールに関しては WEB で色々調べると出てくるのだけど、ROS(いわゆるver.1)と、新しい ROS2 が混在してしまって、ややこしいことになっている。インストールと最初の諸々に関しては、次の本を買ったほうが時間の節約になります。

ROS2ではじめよう 次世代ロボットプログラミング
https://www.amazon.co.jp/dp/4297107422

Kindle 版だと3,000円ちょっとだし、半日時間をつぶしてあれこれ調べるよりも(実際に潰してしまった…)、この本を買ったほうが早いでしょう。

とは言え、最初のインストール部分だけ抜き出せば、Raspberry Pi 3にROS2をインストール – RT Robot Shop Blog にある通り、


export CHOOSE_ROS_DISTRO=dashing sudo apt install curl curl http://repo.ros2.org/repos.key | sudo apt-key add - sudo sh -c 'echo "deb [arch=amd64,arm64] http://repo.ros2.org/ubuntu/main `lsb_release -cs` main" > /etc/apt/sources.list.d/ros2-latest.list' export CHOOSE_ROS_DISTRO=dashing sudo apt update sudo apt install ros-$CHOOSE_ROS_DISTRO-ros-base sudo apt install python3-argcomplete sudo apt install python3-colcon-common-extensions

で、最初のインストールまでは完了です。これで、ラズパイ3と Windows 10 上の Ubuntu(WSL:Windows Subsystem for Linux) の両方でインストールができます。

公式は ROS Index: Installation になるので、何か困ったことが起こったら、ここを見るとよい。英語だが、コマンドが羅列されているだけなので、なんとかなるでしょう。

あと、ラズパイ3 への Ubuntu は 64bit 版が必要なので、http://cdimage.ubuntu.com/ubuntu/releases/bionic/release/ubuntu-18.04.2-preinstalled-server-arm64+raspi3.img.xz を使うことになります。

通信だけ試してみる

ROS2 には、ロボットアームのエミュレーションとか各種センサーのコンポーネント化とか、GUI も含めてロボット開発には必要な機能が満載なのですが、私の場合、通信部分だけが使いたいので、通信だけやっていきます。
最終的にはロボットアームの制御と、3Dプリンタ、PLAN2 の ROS2 化までやりたいのだけど、(何度も失敗しているので)小さく始めるということで。

ROS2 は、Publisher/Subscriber方式で通信をしていて、日本語で言えば「出版-購読者」のパターンです。GoF で言えば「Subject/Observer」だったりしますね。ROS1 のときは仲介サーバーが必要だった(ハズ)のですが、ROS2 は P2P で繋がるようになっていてシンプルになっています。

ROS2 をインストールして最初にやることは、ターミナルを2つ開いて、

Publisher側


ros2 topic pub /chatter std_msgs/String "{data: Hello world.}"

Subscriber側


ros2 topic echo /chatter

で動かすことです。

※ 実際は、環境変数の設定があるので、以下を動かしてパスを通す。あとデモ用のパッケージをインストールする


echo "source /opt/ros/$CHOOSE_ROS_DISTRO/setup.bash" >> ~/.bashrc source ~/.bashrc
  • Windows 上の ROS2(実際は WSL上の ROS2)
  • PINE A64 上の ROS2

とで通信ができることが分かる。この2つは同じネットワーク上で使われていて、それぞれの IP は「どこにも設定していない」のがミソで、仲介役があって何か IP とかを送っているわけではない。これはかなり便利。

PINE A64 の Ubunut で試す

PINE A64 ってのは、ラズパイ3のようなマイコンボードで、ちょっと大きめの中華ボード。秋月で 3,000円位で買える

ボード自体が大きいのと、USBが2個しかないのが難点なのだけど、

  • ラズパイよりも価格が安い
  • ラズパイ3よりも性能がいい(らしい)

ところがある。まあ、Android を動かしたかったので、PINE A64 を購入したのだけど、今となっては Android のバージョンが古くなってしまったので、ちょっと放置状態。

PINE A64 も armbian に Linux OS がある。

Pine64 – Armbian

これは、最初から 64bit 対応になっているので、64bit が必須となる ROS2 がそのまま使える。と言う訳で、Ubuntu 環境で arm64 を用意すれば、

  • ROS2 が使える
  • .NET Core 3 が使える

という形になっている。たしか、React Native も 64bit 環境が必須だったと思うので、PINE A64 や ラズパイの Ubuntu 環境でも動くでしょう。

お次は、C++ で ROS2 のパッケージを作って動かしてみましょう…ってのは後日。

カテゴリー: 開発, ROS | ラズパイ以外でもROS2してみよう(PINE A64編) はコメントを受け付けていません

リモートデスクトップでラズパイに接続する

Windows からラズパイにリモート接続する方法はいくつかあって、

  • VNC を使う
  • Xming を使う
  • リモートデスクトップを使う

という方法があります。昔から、定番は VNC でラズパイ側に VNC サーバーを起動させておいて、Windows で VNC Viewer を使うという方法ですね。

比較的安定しているし、LAN 内でも結構遅くて苦痛なのですが、画面全体を操作する場合は仕方がないということで使っています。

Xming のほうは、Windows 版の X サーバーを入れて操作する方法で、Xming X Server for Windows 日本語情報トップページ – OSDN かなりバイナリが古いのですが、Windows 10 上でも軽快に動きます。xterm だとか、X Window に対応しているソフトをラズパイ側に入れておくと動きます。

で、実は、昔から Windows のリモートデスクトップを使う方法があったのですが、結構遅いし、日本語入力が打てないとかいう問題がありました(ラズパイ側に wnn とか入れればいい?)。ですが、今だと軽快なスピードで動きます!何が変わったのか?単に CPU スピードが速くなったのか?
少なくとも VNC Viewer だと遅くて辛いのですが、リモートデスクトップだと全然問題ありません。

インストールは簡単で、ラズパイ側に xrdp を入れるだけです。


sudo apt install xrdp

Windows からリモートデスクトップで接続すると、xrdp のログイン画面が出ます。

session は X.org のままにしておいて、ログインすれば ok です。

画面はちょっともたつきますが、設定とか Scratch ぐらいならば全然 ok ですね。ssh でつなげてコンソールで設定するのもいいんですが、GUI があると楽です。

特にラズパイの場合は、HDMI 接続せずに LAN ケーブルつけて放置(あるいは WiFi 接続のみ)することが多いので、ちょっとした GUI の設定が必要なときに便利です。

ちなみに、Ubuntu にも xrdp を入れると普通に接続できます。

Ubuntu(うちのは 18.04)に xrdp を入れるだけでリモート接続できるのでお手軽です。Ubuntu のほうは日本語入力が使えます。VSCode も軽快に動きます。

カテゴリー: 開発 | リモートデスクトップでラズパイに接続する はコメントを受け付けていません

俺のOrange Pi One に .NET が(以下略

Raspberry Pi 3 で .NET Core 3 が動くならば、ラズパイ互換の Orange Pi でも動くだろう、と思って確認してみたのがこれです。

結論から言えば、前回 と同じように、.NET Core 3 preview をインストールすると、ラズパイと同じようにビルド&実行ができるようになります。

Orange Pi One とは何か?

Orange Pi One ってのは、こんな感じのラズパイ互換機です。

ラズパイ3だと、USBコネクタが4つあったり、BluetoothやWiFiが乗っていたりするのですが、Ornage Pi One は、USB コネクタが1個だけなのと、BluetoothやWiFiがありません。ちっとばかし不便な気もするのですが、ラズパイ3が5,000円強かかるのに対して、Orange Pi One は1,000円位で済みます。

orange pi one – Orangepi

Orange Pi One H3 512MB Quad core Support ubuntu linux and android mini PC-in Demo Board from Computer & Office on Aliexpress.com | Alibaba Group

以前は、公式?な販売サイトが Ornage Pi のサイト内にあったのですが、今は Aliexpress の中にあります。正規がここらしいので、郵送諸々は問題ありません。中国の深圳から中国郵便で送られくるので、約1週間位で届きます。長くても2週間弱ですね。

OS は Armbian を使う

Orange Pi シリーズはラズパイよりも多種多様なものがあって、用途によって性能が低くても安いのから、ちょっと性能が高くて高めのものまで様々です。OS は、Linux 系のものが動くのですが、公式からダウンロードするとバージョンによって起動しなかったり、そもそもダウンロードができなかったり(リンク先が切れている場合がある)するので、Armbian のものを使います。
Armbian は、ARM 系のマイコンボードに OS をビルドしてくれている有志の集団です。いわゆる、ラズパイ互換の中華ボードは、大抵揃っているので Armbian からダウンロードして使うとよいです。

Orange Pi One だと以下からダウンロードができます。

Orange Pi One – Armbian

最近は Ubuntu と Debian を利用できるようになっています。

この armbian で配布しているディストリビューションは、自前でビルドすることもできて、手順などが Building Armbian – Armbian Documentation に書かれています。ビルドしたことはないんですが…いずれ。

.NET Core 3

.NET Core 3 preview 版を入れて、dotnet new mvc -n web で作成して dotnet run したところまで。


見るとわかるのですが、Orange Pi One のメモリは 512MB しか(?)ありません。まあ、昔の Linux に比べれば断然大きいのですが、動画のエンコードとか機械学習の用途には無理ですね。さて、これは何に使うか。

カテゴリー: 開発, NET Core | 俺のOrange Pi One に .NET が(以下略 はコメントを受け付けていません

俺のラズパイ3で.NET Core 3.0 preview が動くまで

俺のラズパイ2で.NET Core 2.0が動くまで | Moonmile Solutions Blog

前回、ラズパイで .NET Core 2.0 が動いたのだが、セルフビルドができない(後から見れば .NET Core 2.1 で ARM32 対応になっているのだけど)と思ってみたものの、.NET Core 3 ならば大丈夫、という訳でメモ的に。

現時点の v3.0.0-preview8 を使うと Raspberry Pi 3 上で .NET Core でビルドができます。今まで、ラズパイ上でできなくても PC でクロスビルドしてから転送すればよかったので、動くと言えば動くのですが、やっぱり dotnet build ができないと「手軽」とは言えませんよね。手軽じゃなかったら、nodejs を使うか、python を使うか、PHP で Laravel か React を使ったほうが便利なわけですが、ひとまず、.NET Core 3 になるとビルドができます。

ダウンロードしてインストールする

Download .NET Core 3.0 (Linux, macOS, and Windows) https://dotnet.microsoft.com/download/dotnet-core/3.0

ここから SDK の Linux の「ARM32」をダウンロードします。

ラズパイへ WinSCP などで転送できたら、tar で展開します。



mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-3.0.100-preview8-013656-linux-arm.tar.gz -C $HOME/dotnet export DOTNET_ROOT=$HOME/dotnet export PATH=$PATH:$HOME/dotnet

export のところは、~/.bashrc に書いて、常にパスを通しておきます。

dotnet new mvc する

ラズパイで .net core を使って HTTP サーバーを動かすパターン



$ dotnet new mvc -n web

すると動きます。.NET Core な読み込みにひどく時間がかかる(1分以上?)のですが、まあ、立ち上がれば何とか。


blazor する

.NET Core 3 の目玉機能である Blazor も動きます。Blazor は WebAssembly 上に .NET Core を乗って動かす SPA です。


laravel する

ついでに、PHP を入れて laravel してみます。


Laravel と Vue.js の相性は良いので、これも nodejs を使って SPA を作れます。

wpf や winforms してみるが駄目

もうひとつの .NET Core 3 の目玉機能として、Linux の環境で WPF や WinForms が動くという(噂?)があります。


一応、テンプレートはあるしプロジェクトは作れるのですが、Windows 上でしか動きません。これだと、Windows 上で .NET Framework を使う場合と同じじゃないか?と思うかもしれませんが、どうなんでしょう?

まあ、.NET Core と .NET Framework は、来年の秋頃に統合されて .NET 5 になるそうなので。

Introducing .NET 5 | .NET Blog

というわけで、まだラズパイ4は手に入れていないので、ラズパイ3での動作確認を。

カテゴリー: 開発, NET Core | 俺のラズパイ3で.NET Core 3.0 preview が動くまで はコメントを受け付けていません

Windows Update のない世界 Linux へ(サーバーだけ)移行しよう

うちの仕事の環境は、基本 Windows で揃えているのですが、一番の難点は Windows Update です。別口で Windows Server を使えばいいのでしょうが、これは私にはオーバースペックだし、そもそも別口でサーバーを揃える位ならば、Linux を使える環境を用意したほうがよかろう、ってのが主旨で、

サブ開発環境を Ubuntu 18.04 で準備する | Moonmile Solutions Blog

去年の夏に Linux 環境を整えました。仕事柄 Visual Studio が必須なのと、仮想環境がワンセットになっていないと辛い(Windows 7 とか、別の Linux 環境とか)ので、メモリを増加させて相乗りをさえていた訳ですが、月1に訪れる「Windows Updateによる再起動」が辛い。

会社で使う業務PCならば、帰宅時に電源を落とすというのが普通なのでしょうが、

  • 機械学習させているときに、数日間廻しっぱなしにする必要がある
  • バックグラウンドで仮想環境(VMWare)が常に起動している
  • バックグラウンドで Docker が常に起動している

ということになると、不意にやってくる Windows Update による再起動は結構な痛手です。暫くはタイミングを見て手動で再起動(VMWareも手作業でスリープさせる)というのを繰り返していたのですが、去年の春あたりから「勝手に再起動」が頻発してしまって、あまりに耐えかねて Linux マシンを用意しました、ってのが去年の夏です。

構成などは、さきのブログを見て貰うということで、1年間 Linux サーバーとして動作させた感想をメモしておきます。

なんといっても再起動しないのが良い

目的が「再起動させない」なので、Linux マシンは24時間運用です。電力的にどうか?という話しもありますが、私の場合は仕事場が自宅なので、利用時間はこれで良いのです。
単純な NAS や自宅 WEB サーバーならば、Raspberry Pi でも良いのですが(あるいは Orange Pi などの互換機でもOK.),仮想環境として VMWare を動かすのが前提だってので、通常の PC を用意します。メモリはそれなりに潤沢に置いて、CPU はそこそこ、直接画面を見ることはないのでグラフィック関係はオンボードのものを利用しています。

Linux サーバーには普段はモニタはつけていなくて、VNC で接続します。実は VNC での画面更新は非常に遅いので、VSCode などを使った編集が難しいのがデメリットなのですが、そこは Telnet でつなげて vi なり emacs を使います。

業務上、常に VMWare 上で Windows 7 が動作しています。裏で見えているのが保守しているシステム(旧顧客環境のため Windows 7 が稼働している)、手前にあるのが VSCode ですね。絵文字もカラーで綺麗にでます。ただし、VNC 経由だとキーボードの反応とかが極めて遅いので、基本は、

  • telnet で vi を使ってコードを書く
  • WinSCP を使ってファイル転送
  • samba を使って Windows とファイル共有

ってことをやります。VMWare 上で動いている Windows 7 は、そのままリモートデスクトップで接続ができるので、VNC を介在せずに、業務 Windows 10 – Windows 7 間で動かせるので、通常の PC のように動かせて便利です。

Linux マシンは不意に再起動しないので、仮想環境がいきなり倒れたり、機械学習用のプロセスが倒れてたりすることはありません。まあ、実際のとこれは適度に apt upgrade するのですが、面倒?なのもあって、ここ半年ぐらいはそのままです。旧来の意味でのサーバーとしての利用ですね。

インストールするソフトウェアは最小限に

この Linux サーバーは外部に公開している訳ではないので、セキュリティリスクが低いのですが、一応、インストールするソフトウェアは最小限にしています。
最小限とはいっても、適当に動かしたいものを入れるので、

  • mysql
  • PHP
  • apache
  • java
  • dotnet

あたりが入っています。あまりたくさん入れると、再構築が面倒なのと、バージョン違いのあれこれで悩むことになるので、少な目にしておきます。
実際の業務サーバーになると、メールなりFWなりの設定が出てくるわけですが、社内(個人内)で使うものなので、ややこしい設定は入っていません。その分、再構築は楽なのです。

逆に、なんらかのテストをしたいときは、VMWare か Docker に押し込めます。VMWare にしても本格的な運用ではなく、実験的に使うことが多いので既存のものをクローンして使うだけで済みます。HDD の容量を見て、適当なタイミングで仮想環境は消してしまいます。

Ubuntu なので snap が使えるのですが、あまり使っていません。仕事柄ソフトウェアのバージョン違い、OS のバージョン違いを確認することが多いので、snap を使うよりも、VMWare で用意してしまったほうが楽なのです。

なお、仮想環境は HDD の容量を気にしてあれこれと消したりするよりも、2T HDD を買ってしまって、さっくりと増量してしまったほうがベターです。メモリも仮想環境用に 32GB まで増量させています。本当は 64GB に上げたかったのですが、結構な値段になってしまったのでランクを落としました。それでも大丈夫なのは、

  • 業務用 PC で Windows 10 で 32GB
  • Linux で Ubuntu 18.04 で 32GB

に分けられたからですね。業務用 PC のほうでは仮想環境を動かすことがなくなった(実際は、アズールレーンが BlueStacksで動いていますがw)ので、32GB でも十分になりました。

クラウド環境でもいいのでは?

自宅 Linux を作るよりクラウド環境を要したほうがいいのではないか?と思うこともあります。実際、VPS を借りたとしても、年間2万円弱でそれなりの Linux サーバーを借りられます。手元の Linux サーバーは 13万円 + 電気代がかかっているわけで、実は外部で借りたほうがランニングコストは安くなるでしょう。おそらく、VMWare 等を使って仮想環境を作らないのであれば、クラウド上に Linux や Windows を入れてしまったほうが手軽です。問題は、回線スピードなのですが、今となっては光回線が普通になってきているので、Windows 10 からリモートデスクトップで繋げても、そこそこの画面更新スピードで動くでしょう。

なので、最近となっては全面的にクラウドに持って行ってもよいのですが、クラウド環境を使う最大のデメリットは、

  • ビックデータや画像データなどの大量のデータを送り出すのに時間が掛かること

です。光回線の場合、下りのスピードは早いのですが、上りのスピードが遅いことが多々あります。なので、検索のためのデータとか、何か加工するためのデータをクラウド上にアップロードするときにかなりの時間が掛かります。転送量の価格もあるのですが、時間が掛かるのが大問題です。

手もとの Linux サーバーだと、HDD を USB でつなげるとか、社内ネットワーク越しにコピーするとかで相当にスピードでコピーができます。一番早いのは、micro SD カードか外付けの SSD にコピーして USB 3.0 経由ですね。
なので、業務的にデータの秘匿性が高くはなくても、オンプレミスで Linux サーバーを運用させるメリットはそれなりにあるわけです。まあ、オンプレミスの場合には、SE 役が必須なわけですが…ひとまず、自宅 Linux の場合は自分な訳だし。

カテゴリー: 開発 | Windows Update のない世界 Linux へ(サーバーだけ)移行しよう はコメントを受け付けていません

クソコードとマイナス生産性の関係

定期的に発生する「クソコード」発言問題だけど、新人の未熟なコードよりも(自称)熟練者のクソコードのほうが害が大きいので、さりげなく「クソコード」というようにしている。例えば、

  • こんなクソみたいなコードを残してしまうと、未来に禍根を残すし
  • 使う身になってみれば、クソみたいなAPIを公開されても誰も使わないし
  • こんなクソみたいなUIは誰も使わなくなるから、削ったほうがコストが安くなりますよ

とかとか。以前は汚物用語は使わないようにしていたのだけど、なぜかインパクトが薄く(自称)熟練者には届かないようなので、時に散弾銃のように混ぜるようにしている。ちなみに、さりげなく「クソ」を混ぜると、当たらない人には当たらずにスルーされる。本人だけには分かるようなので、顔が少し赤くなるので判別がつく。
また、「クソコード」を言うときは、本人に対して言うのではなく、

  • ディスプレイのコードを示しながら、「ここのクソコードなんですけどね」とか
  • 印刷したコードにアンダーラインっぽい「削除ライン」を引きながら「ここのコードなんですけどね」

とやる。コードを書いた本人が悪いのではなく、悪いコードを修正しない当人が悪いという示唆である。プログラマは職人的な能力が問われるので、日々進化する。だから、数日前に書いたコードは、自分が未熟だったゆえに(ものを知らなかったゆえに)書かれたコードであれるのだから、数日後にものを知ったあとで直せばいいのだ。
だから、直せばOK. 直さないのは何かが「クソ」なのだから。

何を参考書にする?

コードレビューに関しては、この2冊があれば十分である。

「ソフトウェア インスペクション」は、IBMで育ったレビュー方式で、厳密にレビューの仕方が規定されている。ざっくりと集まって、ざっくりと(自称)熟練者が新人に対して評価を下すのではなく、レビューを行う品質管理担当がいて厳密に手順を決めておく。きっちりと行うには、IBM ぐらい大きな組織でないと難しいのだが、レビューする日を別に定めて、レビューを記録しながらやると同じような効果が得られる。
最大のポイントは、レビューをするものが事前にレビューをしておくことだ。レビューをするために長い時間取られるが、それだけの効果があるし、なによりも面と向かって言うのではなく、あらかじめ紙面に書いておくことで感情的にならずに済む。また、面と向かったときには「何を基準にして駄目なのか」を明確に言えるようにしておく必要がある。

「ピアレビュー」は、インスペクションよりも緩く、一般的なレビューよりも丁寧なものを示している。コードを前にしてピンポイントで進んでいくのではなく、頭から最後まで通してコードを読み進め、レビューをしていく。このローラー作戦を遂行することで、コードの品質が「標準的」になるのが、ピアレビューの特徴である。コードが標準的になると、他の人から読みやすくなるし、保守もしやすくなる。改修コードを入れるときにも、既にあるコードになじむように「補修」あるいは「補完」することによって、全体の質を同じに揃えることができる。

マイナス生産者を排除するためレビューを行え

一般的に、コードレビューは

  • コードの品質を上げる
  • 新人が作ったコードの間違いを直す

という目的で行うことが多いのだが、最近の新人プログラマはそれなりにプログラムコードを勉強しているし、30年前とは違ってプログラム言語も豊富になってきたので、極端に不味いコードが出てくることは少なくなっている…と思う。会社に属さなくなって10年以上経つので、ほんとうのところはどうなのか分からないのだが(いやいや、頭でっかちな新人っぽい人はちらほら見るので、それなりの「ぴよぴよコード」はあるとおもうのだけど C#のぴよぴよコードをなんとか使える形にするための2つの方法 | Moonmile Solutions Blog)。
と、その前に(自称)熟練プログラマが陥りがちな「クソコード」のほうが有害である。どんなところが有害かというと、

  • 「クソコード」を書いた人にしか分からない、クソ理論でコーディングされて、誰も理解できない。
  • 「クソコード」を書くために、クソみたいなライブラリを付随されていて保守性が悪い
  • 業務システムの場合、テスト費用、保守費用が別途かかってくるので、それを増大させるのは全て「クソコード」である。

という点があげられる。個人開発をしていたり、ずっとその会社でライブラリを作り続けていたりするのならばいいのだが、ある程度の大き目の業務システムになると、複数名が関わらざるを得ない。なので、良かれと思ってコードを改修していていても、それは「クソコード」になり得るし、実際に「クソコード」となってしまう。
よって、クソコードは「レガシーコード」よりも低位にある。逆に、先に書いた通り、クソコードは直せばふつうのコードになる。だから、「直さないクソ」な人がクソコードを生み出す≒マイナス生産者である、という話になるのだ。

「ピープルウェア」にある通り、マイナス生産者は清く排除するのがよろしい。あるいは隔離だ。その方法いくつか逆引きにも書いたし、どこかで検索すれば出てくるだろう。

自称熟練者のクソコードの例

自分の過去のコードを見れば、いくらでもクソコードが出てくる。なので、私の書いたクソコードを紹介しておこう。



static int hxx_number = 0; ... int HXX_get_NUMBER() { return hxx_number ; }

その昔、UnixにC++がなくてC言語しか使えなかったとき(まだg++はなかった)に、オブジェクト指向風にメソッドぽいものを作ったクソコード。呼び出し側は、HXX_get_NUMBER 関数で値を取るわけだが、いやいや面倒くさいし、中身が何か分からない。中規模程度であれば、hxx_number を直接参照したほうが可読性がよいだろう。
可読性がわるくなるので、コードを引き継いだ人が迷惑するクソコードだ。



struct DATA data ; for ( int i=0; i<2; i++ ) { ... data.array[i] = 0 ; }

構造体のデータを0で初期化する例だが、for文で2つまでか使わないのは無駄だ。arrayが可変ならば必要かもしれないけど、そもそも「2」を即値で置いているのが駄目だろう。素直に、array[0] = 0; array[1] = 0 ; で十分だし、C言語だから memset( &data, 0, sizeof(data)) と memset を使ってゼロリセットするほうがよい。



$h = $this->params['data']['Reservation']['CompletionTime']['hour']; $m = $this->params['data']['Reservation']['CompletionTime']['min']; if ( $this->params['data']['Reservation']['CompletionTime']['meridian'] == 'pm' ) { $h += 12 ; if ( $h == 24 ) { $h = 12; } } $CompletionTime = "$h:$m"; $h = $this->params['data']['Reservation']['StartTime']['hour']; $m = $this->params['data']['Reservation']['StartTime']['min']; if ( $this->params['data']['Reservation']['StartTime']['meridian'] == 'pm' ) { $h += 12 ; if ( $h == 24 ) { $h = 12; } } // 入庫時刻の補正 if ( $h == 12 && $m == 1 ) { $h = 0; } $StartTime = "$h:$m"; $CustomerBilling = $this->params['data']['Reservation']['CustomerBilling']; $y = $this->params['data']['Reservation']['AcceptanceDate']['year']; $m = $this->params['data']['Reservation']['AcceptanceDate']['month']; $d = $this->params['data']['Reservation']['AcceptanceDate']['day']; $AcceptanceDate = "$y-$m-$d"; $Remarks = $this->params['data']['Reservation']['Remarks']; $Scene = $this->params['data']['Reservation']['Scene'];

これは、PHPをよく知らないときに作ったコードなのだが、日時変換が駄目過ぎて泣けてくる。いわゆる「自称熟練者」がプログラム言語の流儀をよく調べずに、ひとつだけの金づちでなんとかしようとした悪い例である。WEB APIのGET呼び出しなので、今ならばJSON形式のGMT表記で一発で変換できるパターンである。実際、ここは結合テストをすり抜けてしまって運用時にバグが発覚したものである。つまり、クソコードが被害を出してしまった好例?だ。

個人開発や少人数開発であれば、どんなトリッキーなコードを書いてもいいけど(自分がわかるならば)、小規模であっても製品にする場合や複数名でコードを弄るときには、できるだけ「平坦なコード」を書くのがよい。それはコードの標準化とか、共通ライブラリの利用とかいう上辺の話だけではなくて、コードの質を揃えて資産化するという意味でだ。本格的にはMDAとかもうちょっと模索が必要なところだけど。

カテゴリー: 開発 | クソコードとマイナス生産性の関係 はコメントを受け付けていません

ASP.NET MVC から Redmine+MySQL を操作する

以前 独自にポートフォワード作成し、ラズパイの MySQL へ LINQ で接続する で SSH ポートフォワードを使って MySQL に接続したのだが、これをもうちょっと活用すると、.NET Core で作成した ASP.NET MVC から Redmine の MySQL を閲覧できるようになる。

主な手順

  1. Redmine テーブルの EF を用意する
  2. ASP.NET MVC のひな形を .NET Core で作る
  3. ASP.NET MVC に EF をコピーする
  4. ASP.NET MVC のスキャフォード機能を使って、Controller と 各種の View を自動生成する。
  5. 動作時は、SSH ポートフォワードで、実運用の Redmine + MySQL に接続させる

ASP.NET MVC で利用する EF は直接 MySQL から作成してもよいのだけど、何かと面倒なので手作業で作るか、あらかじめ SQL Server で作ったものを用意する。

EF のモデルクラスを作成する

Visual Studio から EF を作成するほうが楽なので、”ADO.NET Entity Data Model” を追加して、SQL Server 上に作成した Redmine のテーブルから、モデルクラスを作成する。

必要なのは、RedmineModel.tt 配下にある *.cs のクラスで、たとえばチケットを管理している issues クラスはこんな感じになる。




public partial class issues { public int id { get; set; } public int tracker_id { get; set; } public int project_id { get; set; } public string subject { get; set; } public string description { get; set; } public Nullable<System.DateTime> due_date { get; set; } public Nullable<int> category_id { get; set; } public int status_id { get; set; } public Nullable<int> assigned_to_id { get; set; } public int priority_id { get; set; } public Nullable<int> fixed_version_id { get; set; } public int author_id { get; set; } public int lock_version { get; set; } public Nullable<System.DateTime> created_on { get; set; } public Nullable<System.DateTime> updated_on { get; set; } public Nullable<System.DateTime> start_date { get; set; } public int done_ratio { get; set; } public Nullable<double> estimated_hours { get; set; } public Nullable<int> parent_id { get; set; } public Nullable<int> root_id { get; set; } public Nullable<int> lft { get; set; } public Nullable<int> rgt { get; set; } public bool is_private { get; set; } public Nullable<System.DateTime> closed_on { get; set; } }

ASP.NET MVC Core のひな形を作る

コマンドラインから、以下のように作成する。




dotnet new mvc -n redmine.web

VSCode を使ってもよいのだけど、スキャフォード機能を使う場合、Visual Studio 2019 を使ったほうがよいので、*.sln ファイルも作っておく。

EF のモデルクラスをコピーする

先のプロジェクトで作成したモデルクラスを ASP.NET MVC の Models フォルダーにコピーする。

注意しないといけないのは、Redmine では tinyint(1) をフラグ代わりに使っているので、これを bool 型で扱うか? int 型で扱うかという問題がある。本来はチェックボックスにしたいので bool 型にしたいところなのだが、ひとまず int 型にしておく。




public partial class issues { public int id { get; set; } public int tracker_id { get; set; } public int project_id { get; set; } public string subject { get; set; } public string description { get; set; } public Nullable<System.DateTime> due_date { get; set; } public Nullable<int> category_id { get; set; } public int status_id { get; set; } public Nullable<int> assigned_to_id { get; set; } public int priority_id { get; set; } public Nullable<int> fixed_version_id { get; set; } public int author_id { get; set; } public int lock_version { get; set; } public Nullable<System.DateTime> created_on { get; set; } public Nullable<System.DateTime> updated_on { get; set; } public Nullable<System.DateTime> start_date { get; set; } public int done_ratio { get; set; } public Nullable<double> estimated_hours { get; set; } public Nullable<int> parent_id { get; set; } public Nullable<int> root_id { get; set; } public Nullable<int> lft { get; set; } public Nullable<int> rgt { get; set; } public int is_private { get; set; } public Nullable<System.DateTime> closed_on { get; set; } }

データベースの接続情報やデータアクセスを LINQ で使えるようにするため、DbContext を継承した RedmineContext クラスを作る。




namespace redmine.web.Data { public class RedmineContext : DbContext { public RedmineContext(DbContextOptions<RedmineContext> options) : base(options) { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); } } }

NuGetで MySql.Data.EntityFrameworkCore を入れた後、
Startup.cs を開いて、MySQL への接続文字列を ConfigureServices メソッド内に書く。




public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddDbContext<redmine.web.Data.RedmineContext>(options => options.UseMySQL(@"server=localhost;user id=redmine;password=redmine;database=redmine;port=3306;sslmode=None"); }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }

スキャフォード機能で Controller と View を作る

ひとまずローカルの MySQLに接続して確認する

Visual Studio からデバッグ実行すると、デバッグ用のコマンドラインが表示されて、localhost:5000 へ接続できるようになる。

https://localhost:5001/Issues のようにアクセスすると、MySQL の中身が表示される。Issue の一覧になるので、すべてのプロジェクトの Issue がまとめて表示されてしまうが、これは独自にルーティングを使ってプロジェクト内のみ表示させればよい。

SSH ポートフォワードを使う

options.UseMySQL で記述した接続先を SSH ポートフォワード用に変更すればよいのだが、ひとまず SSH で繋がるかどうかを MySQL Workbench で接続してみる

Connection Method を “Standard TCP/IP over SSH” に変更して SSH 経由で接続できることを確認しておく。

その後で、Ubuntu on Windows で、localhost の 190000番を openccpm.com 内部にある MySQL(3306) に通すようにする。




ssh -L 19000:localhost:3306 masuda@openccpm.com

Setup.cs の該当箇所を書き換える




services.AddDbContext<redmine.web.Data.RedmineContext>(options => { options.UseMySQL(@"server=localhost;user id=redmine;password=redmine;database=redmine;port=19000;sslmode=None"); });

Visual Studio 2019 からデバッグ実行できれば ok.

カテゴリー: 開発 | ASP.NET MVC から Redmine+MySQL を操作する はコメントを受け付けていません

京都アニメーションの被害者に哀悼を込めて

実は、アニメ制作の進行とソフトウェア開発のマネジメントの話 | Moonmile Solutions Blog の追記をしようと思った矢先に、京都アニメーションの放火事件があり、心理的に続きが書きづらくなってしまった。ので、1時間ほど哀悼を込めて綴っておこう。

プログラミングのバックグラウンド映像にアニメを流している位に「アニメファン」ではあるのだが、実は京アニ「だけ」に思い入れがある訳ではなく、どちらかといればそれ以前のアートランドあたりからスタートしている「アニメマニア」であったりする。

先に書いた通り、アニメーション制作の進行係にはプロジェクト管理として興味を持っていて、その周辺の技術(動画とか作画とか諸々)はセルアニメの頃の知識で止まっていたりするので、実は「なつぞら」あたりのほうがよく知っていたりする。知識としてだけだが。

「なつぞら」と「SHIROBAKO」の進行を比べたり、三鷹のジブリ美術館に行ってみたり、ディズニーの絵コンテを買ってみたりするのは、趣味というのもあるけれど、絵を描くことと、プログラムを書くことは「手を動かす」という意味で同じジャンルにあるだろう(あるとしたい)という気持ちがある。まあ、大学の頃に漫研に居たというのもあるし、なんとなく絵を描き続けられなくてプログラムに逃げてしまった?という経緯もあって、いまだにちょっとだけ「憧れ」がある。とはいえ、50歳も過ぎれば、憧れは憧れのままにしておく手法もあり、どこに時間を費やすかといえば、プログラム&文章に費やしたりしてしまう。技術書をちまちまと書きおろしているのはそのためでもある。

いまさら、アニメーションが人々の心に影響が…という話でもないと思うのだが、「けいおん!」がアニメマニアではない高校生に大きな影響を及ぼしたのは間違いないらしい。間違いないらしいというのは、実は「けいおん!」はリアルタイムで見てはいなくて、時期的に言えば就職して暫くテレビを見てなかった頃だったので、後からレンタル屋さんで借りてきてみている。私の高校時代といえば、「うる星やつら」とか「ガンダム」とか「みゆき」とかが午後7時台に放映されたいた頃なので、アニメを見るのは子供でもありつつ高校生でもありつつ、ちょっとマニアックな大学生でもあった時代だった。「おたく」がテレビに認知されつつも、宮崎事件があった頃でもある。そこから、だいぶん下ったところに「けいおん!」があって、放映後にしばらくたった時期ではあるけれど「けいおん!」が放映されてときの同時代性というのものは、当時の高校生にとって非常に大きかったことを伺い知れる。

いわゆる、いじめが陰湿化してしまった後に、学校への不登校とクラスになじめない自分とのはざまの中で、疑似的にではあっても「けいおん!」が高校生活を体験させてくれたというブログ記事がちらほらみられるのが興味深い。それと同時に「けいおん!」を見て軽音を始めた高校生もいて、このアニメが影響を与えた層というものは、従来のアニメファンだけではなくく、一般的に理解されるであろう(おそらく当時の親の層からも理解されたかもしれない)層までも「アニメ」を広げたという感じがしている。おそらく、かつて「金八先生」をクラスで話題にしても恥ずかしくなかったぐらいに、「けいおん!」をクラスの友達と話してもハズか少なかった位にも浸透したのではないだろうか?という気がしている。

同じ現象は、ジブリアニメでも起きているわけで「天空の城ラピュタ」を誰もが知っているように、「ジョジョの不思議な冒険」を知っているように、そこの登用人物や科白を使っても恥ずかしくはない程度に「アニメ」は浸透したのだと思う。

実は京アニ自体に特別な思い入れはないのだけど、あらためて「響け!ユーフォニアム」や「たまこまーけっと」を見返すと、節に復活を願う。当然のことながら、「日常」と「らき☆すた」は、作業用BGMの定番である。

ちなみに、仕事中にアニメをBGMで流しておくのは、

  • タイマー替わり
  • 過集中を避ける

の2つの意味合いがある。タイマーのほうは、艦これでもよいのだが、TVアニメの場合24,5分単位で終わるので時間が測りやすい。よって、映画ではなくてTVアニメの各話を流し続ける。

あと、プログラミング自体に集中しすぎると最終的には効率が悪い。職業柄、大量なサンプルコードを書くことが多いので適度な休憩が必要になる。その休憩のタイミングをTVアニメの各話に挟めるというメリットがある。また、過度に集中するよりも、ある程度気を散らしたほうが疲れないというのもある。このあたり、ラジオが良い人もあれば、音楽が良い人もいる。あるいは、静かなほうが効率が良い場合もある。それぞれだ。

カテゴリー: 雑談 | 京都アニメーションの被害者に哀悼を込めて はコメントを受け付けていません

チケット駆動のチケット数を概算見積もりする

うまいチケット駆動でのプロジェクト管理を見たのは、20年ほど前のアジャイル協議会のTLだったと思う。ライントレーサーのロボットを作るのに、チケット駆動とPSP(パーソナル・ソフトウェア・プロセス)を組み合わせて、Excelで進捗チェックをするひとりプロジェクトだ。

複数名のチケット駆動というと、壁に付箋を貼るか、チケット駆動のツール(Redmineとか、Backlogとか)を使うことが多いのだろうが、何もツールの全ての機能を使わなくてもよい。というか、全ての機能を使おうとすると何かしらうまくいかないことが多い。最大公約数で機能を詰め込んであるのでオーバースペックなのだ。

で、

チケット駆動の最大の難点なのは、最終的にプロジェクトがいつ終わるのか?が見えないことだ。スクラムのバックログ方式も同じだけど、アジャイル方式で開発を行うとどうも終わりが見えなくて困る。当然のことながら終わりが見えないからアジャイル方式を使うのだけど、じゃあ、いつ終わるのか?という概算的な時間見積もり≒納期はどのあたりに定めればよいのだろうか?

プロジェクトが終わった時点から見れば、チケット駆動であれスクラムのバックログであれ、消化したチケット数/タスク数は決定的である。当たり前だ。プロジェクトは完成して終わったのだから、目の前にできたものに費やした時間は「記録さえしてあれば」計算できることになる。

なので、実はチケット駆動でも概算的な規模見積もりは可能であったりする。

ソフトウェア見積り 人月の暗黙知を解き明かす
https://www.amazon.co.jp/dp/B00KR96M6K

FP とかも含めて、いろいろと試してきたけれど、私の場合マコネル氏のこの本に同意する。マコネル氏はこの前後に計量的にタスクの時間見積もりをするツールを売っている(今はなくなっている…はず)けど、細かなタスクあるいはチケットを確率的に求めなくても、もっと概算で十分だろう、ってところに今の私は落ち着いている。年初あたりに確率統計を使って計算する試みをしてみたのだが、正確なシミュレーションをしたとしても途中のタスクの増減の影響が大きいのでプロジェクトを進める間は、その正確さは重要ではなくなってくる。大規模プロジェクトの計画段階(予算と期間を決めるという意味で)は重要になっているのだが、高々数百万のプロジェクト、期間が4か月程度のものに最初の正確さを求めても意味がないことが多い。それよりも、プロジェクトを運営する上での「やりくり=本当の意味でのマネジメント」を考えたほうが安全にプロジェクトを終わらせることが可能である。

期間を概算する

会社にいた頃は、機能を洗い出して機能ごとに時間単位あるいは日単位で見積もりを出して積み上げていたものだが、今はやっていない。超概算見積もりで人月を計算した後に、Excelで機能に割り振る、あるいはチケットに割り振ってしまう。

正確に言えば、

  • 超概算見積もりで、人月で算出する
  • 顧客の懐具合で、予算を算出する
  • 機能の数で、人月で算出する

と3つの人月を出す。大体において、派遣なり契約社員なり社員なりに支払うお金は「月単位」になることが多いので、週単位で出してもあまり意味はない。細かい単位でずれを修正しても仕方がないし、そもそもスポンサー≒お客の懐具合に予算を合わせないといけない。

ならば、月単位の単価をベースにして、超概算してしまうのがよい。細かいところはプロジェクトを進めながら合わせていく。

チケット数を概算する

期間と人数が決まれば、おのずと動いている時間が決まってくる。当然だが、20日/月、160h/月で考える。22日で計算すると祝日や別な割り込みの分を勘定できないし、そもそも計算が面倒くさい。2日≒10%程度の余裕が最初からあるほうがよい。

1日で消化するチケットする数は3つ程度と決めておく。期間が長ければ1日1チケットでもよい。しかし、1週間1チケットみたいなのは駄目。スクラムのスプリント期間に近くなってしまうし、1つのチケットが1日よりも長くなる場合は、チケットを分割するか、複数のチケットに同じタイトルで割り当てたほうが良い。いつまでも進行中のまま終わらないからだ。

チケットの作業時間の粒をできるだけ揃えておくのがよい。そうするとバーンダウンチャートで先行きが見えやすくなる。

プロジェクトの開発期間と人数が分かれば、全体のチケット数が概算できる。

既知の開発をチケットに割り振る

プロジェクトの開始時点(規模見積もりをしている時点)で、ある程度の既知の開発チケットがあるはずだ。そうじゃないと、どうやって規模/金額見積もりをしたんだ?という話になる。大まかな機能と、おおまかな時間(1日なのか3日なのか)を適当に決めて、チケットに割り当てる。

見積もったチケット数をすべて書き込む必要はない。いや、むしろ書き込んではいけない。プロジェクト開始時のチケット数はあとから増える可能性が大なので、空白のチケットを残しておく。これは保険だ。あるいは、未知なるチケットだ。

あるいは、チケットが全て埋まってしまう状態になったら、それはそもそもが全体のチケット数が足りない → プロジェクト期間が短すぎる、ことを意味している。先の超概算に戻って、再確認する。

残チケットを消化する

プロジェクトが進む中で、さまざまな要望が増えていくる。チケットを消化しつつも、チケットが増えてしまうのがチケット駆動の難点ではあるが、あらかじめ全体のチケット数が分かっていれば≒概算してあれば、プロジェクトが進んだとして大幅にチケット数が増えることはないだろう(それでも予想を超えて増えてしまうのが常なんだけど)。

私の場合、チケットの消化記録は、Excel か Redmine を使っている。先に書いた通り、Redmine を全ての機能を使うと多機能すぎてオーバースペックになる。なので、

  • チケットは新規/進行中/終了しか使わない。進捗率は使わない
  • 作業時間はいらない
  • ガントチャートも使わない
  • 優先度も使わない
  • チケットはあらかじめ概算時点で大量に置いておく。順々に消化する。

という非常にシンプルな使い方をする。

ひとりプロジェクトだと Excel ベースで十分なのだけど、2名以上だとファイル競合がでるので Redmine を使う。最初に大量のチケットを投入する必要があるので、現在ツールを作って投入中。ClosedXML を使って、Excel へのマージを作っている。これ、Redmine の CSV のインポート機能でいいんじゃないだろうか?と気づいたのだがどうだろう。あとで試してみる。

追記

CSV からインポートすると常に新規になるので、二重にチケットができてしまう。更新版を自作しないと駄目。初期チケットの大量投入は CSV を使うと便利。

カテゴリー: プロジェクト管理 | チケット駆動のチケット数を概算見積もりする はコメントを受け付けていません