お腹.ヘッタ。

関数型とかセキュリティとか勉強したい。進捗つらぽよ

現役高校生が知識ゼロから、倒立振子による玉乗りロボットの機構を作り、それを活かして杖を作ってる話。

 これはStudent Advent Calendar 2016の25日の記事です。
 qiita.com

 竹です。工業高校の三年で、専攻は電気(強電です)。ひょんなことからこんなタイトル通りのことをすることになりました。
 なぜこんなこと書こうかと思ったかというと大学に進学し、高校から離れるにあたり解体することになってしまったからです。
 そして私が未だに完全に作りきれなかったことの研究が出来なくなったからでもあります。
  f:id:taketarou2:20161225010547p:plain:w400
 これは、今後パーツや素材を一から集めれた時の備忘録&これからメカトロニクス倒立振子を始めたい人のために書きました。あと残念ながら訳あってソースコードはお見せできません。すいません。ですがそのうち載せたいと思います。


 ちなみに私自身元々は自称ソフト屋さんでマイコンを取り扱うことや弱電は一度たりともありませんでした。完全に電子工作及びメカトロ初心者で、工具の使い方ひとつでさえわかりませんでした。
 メカトロニクスについて勉強したいなーと思う人は僕みたいなフローを辿るといいかもしれません


 以下に本記事の中身を記していきます。拙い文章ですが気長にお付き合いください。


概要

 大会に出すのに人の役に立つものを作りたいと考えました。
 その中のアイディアとして自立移動する杖があればじじばばが楽になるのではという理由から自立する杖を作りたいと思いました(適当)
 ちなみにこれをやったのは二年生の後半から3年の前でした。

機構を考える

 検索しまくった結果、植え付けられたせいか私の中では立つ=倒立振子だったので倒立振子を採用しました。
f:id:taketarou2:20161223124612p:plain
こんな感じが原案。

倒立振子とは?

 読んだ名の通り「逆立ちする振り子」です。普通の振り子は支持点が重心の上方に存在するのに対し、倒立振子は支持点が重心の下方に存在します。
つまり、箒を手のひらでおっとっと〜と支える感じです。

 倒立振子が倒れないようにするには,常に支持点を重心の真下に位置させる制御技術が必要です。
つまりあれです。箒が倒れそうな方向に走っていくと倒れないアレです。

取り掛かってみる

 しかし結局検索して出てきた知識を使いたくてもどうやればいいんだこれでした。全くわからん。

 というわけで先行研究を調べました。

 どうやら東北学院大学の熊谷教授が研究しているそうです。(地元なのに知らなかった。。。。)
 論文:玉乗りロボットの開発 第一報 ロボットの実装と基本制御
 https://tohoku-gakuin.repo.nii.ac.jp/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=136&item_no=1&attribute_id=22&file_no=1&page_id=34&block_id=86

(それに乗っかるつもりで)これを読み込みました。ちなみにメカトロ知識ゼロです。大学数学もわかりません。ですので並行して自動制御とメカトロについても勉強しました。

 http://www.mech.tohoku-gakuin.ac.jp/rde/contents/sendai/mechatro/archive/RMSeminar_No09_s8.pdf
 などがあるこれまた東北学院大学の熊谷教授の資料が初心者向けで最高です。以下のインデックスから漁ってください。
 Index of /rde/contents/sendai/mechatro/archive

 また
 センサの基本と実用回路 (計測・制御テクノロジーシリーズ)
 Amazon CAPTCHA
など難しい知識が必要な時はこういう本を読んでました。
 基本方針は上で紹介した熊谷教授の公開なされているpdfを読んで、たりなきゃ考えればいいみたいなのが一番よかったと思います。

 正直そんな難しいと考え込んでしまってしまっていたのが失敗なので是非楽に考えましょう。

 ちなみに今玉乗りロボットは僕が始める時にはなかったこんな知識の宝庫みたいなサイトがあるみたいです。羨ましい。。。。
 玉乗りロボット BallIPMini 技術情報

 さてさて。どうすればいいかはなんとなくわかってきましたがそれでもモーターでさえ一つ回したことありません。

 論文中にはステッピングモーターを使っています。まずは回すとこからスタートをしました。

主に使用したもの電子デバイスは
ステッピングモーター
ArduinoMega
MPU6050(6軸センサー(加速度とジャイロ))

を使いました。
また、なめらかオムニホイールと呼ばれる軌跡が一つになる特殊なオムニホイールを使用しました。


ステッピングモーターを回す

 こういう記事ととかみたりどんなのあるのかメーカサイトを見たり。
 ステッピングモーターの基本(前編)〜Arduinoでパーツやセンサーを使ってみよう | Device Plus - デバプラ
 駆動方法を調べたりしました。ぶっちゃけモーター駆動とモーター回路が一番難しくて一番大変です。しっかりと理解しましょう。

 モータードライバは細かい動きをさせるマイクロステップをやりたいが故に市販のを使いました。
 akizukidenshi.com


 これまた僕が回路周りめっちゃ苦労した時にあったら最高だったなというサイトがありました。
この回路設計まんまパクってもいいねというぐらいいいと思います。
 1500円で作る!CNCフライス用ドライバー | 自作工房


 モーターは色々使ったんですがこの辺がすごくおすすめです。
 バイポーラ ステッピングモーター 17PM−K044−AKZ: パーツ一般 秋月電子通商 電子部品 ネット通販


 ちなみに回路周りなのですが紛失しました。。。。ごめんなさい。。。(手書きなのでどこに置いたか。。。)

 さてさてなんとなくモーター周りを理解したところで「倒立振子って結局技術的にはなんぞや」というところと「6軸センサー(角速度と加速度)の制御」、「機体の設計」の足場を固めながら三点に取り掛かります。

倒立振子って結局技術的にはなんぞや

 論文読んでもネット見てもわからん。
 今思うに、初心者には論文で使うような真面目な理論は難しすぎる。でもネットの半日でできるなんちゃらとかはの理論抜きでやりすぎてるのである程度しっかり知りたい人には全くわからない。つまりまぁ慣れろってことなんでしょうけど。

 とりあえず調べていくと平然と
”まず車体へ働く力を物理的に把握することが必要です。運動方程式を立て行います。”
とか言われます。がこれらは現代制御法の場合必要です。

 ですが今回は論文に沿うことにしたので私は今回はPD制御による加速度制御、簡単に言えば古典制御でのアプローチをしました。

古典制御とは

 偏差(修正すべきずれ)に対して比例制御、積分制御、微分制御これらを組み合わせアプローチを行う制御。
イメージとしては、
比例制御:偏差(誤差)に対して比例させて治すアプローチ。
積分制御:偏差(誤差)がどんどん溜まった際にまとめて打ち消すアプローチ。
微分制御:起こりゆく誤差に対して起こすアプローチで、少し偏差(誤差)を打ち消したい時に行うアプローチ。ズレ始めとか強く効く。
 こんな感じです。


 もう少し具体的に説明をします。
 距離、速度、加速度これらの関係は微分積分で変化させることができます。距離を二階微分すると加速度になり。で逆に二重積分すれば距離になります。この時微積分でのΔになる部分は”t:時間”です。つまるところ、微分で成分に対して制御をし、積分でまとめての大味な制御をすることができます。つまり時間のP,I,Dこれらは次元ごとの制御をしてるとも言えます。



 さてここまで理解したところで不思議なことに気がつき、疑問を持つ方もいるかもしれません。なんでPD?PIDじゃないの?という疑問です。普通に考えたらPIDの方が全部に対してやっていて良さげですよね。ですが今回の使用しているモーターはステッピングモーターです。トルクに対する指令ができません。できるのは回転速度に対することのみです。ですので角速度と角加速度のみが制御可能なので、PD制御による加速度制御となります。

具体的な制御について

f:id:taketarou2:20161225003121p:plain
  f:id:taketarou2:20161225010547p:plain
 この図はロボットに用いた,センサによるロボットの姿勢角と車輪の移動量を用いる典型的なPDフィードバックのブロック図です。


 制御部は以下の式で表されます
f:id:taketarou2:20161225003524p:plain
aは操作量で球の外周の加速度であり、θは各軸の方向の傾斜角x,yは車輪の移動量、vは速度である。添え字x,yはそれぞれの軸に関する状態量(距離)であること を示し,K*は実験を行い調整した定数制御ゲインである。またvx(y)aを数値積分することで得られました。

なおこの場合はx,y,vx,vyはワールド座標系ではなく球の回転量です。

 一般的に倒立振子はトルク制御の方が有名ですが、今回はステッピングモータ を利用したというのことから加速度制御を採用したということを前述したと思います。
 今回採用したPDフィードバックは、センサーノイズがダイレクトに操作に関わってくることが一般的に知られています。(よくわからない場合は熊谷教授のPDFを参照)
そこでセンサー対策として簡易的な一次デジタルローパスフィルタを作成し、センサデータをリプル状のノイズを消すようにしました。

f:id:taketarou2:20161225004051p:plain:w300

 パラメータはrのみで、入力を比率rをゲインとする特性を持っている。r=1のときは、ただの素通し、r=0のときは、y[k]=y[k-1]となるつまり、値を維持となります。r=0.1など小さい値にすれば変位値が元の値に寄っていながら増えるというものです。
実際に制御とデジタルローパスフィルタ(LPF)をソースに書き起こしたものが以下のソースです。なおKsという記述はゲインの入れ込んだ配列であり、LPFのゲインは実験的に求めたものです。

thx -= thofx; thy -= thofy; //PD制御
acxt = (Ks[0] * thx ) + //角度 
   (Ks[1] * thvx ) +//角速度 
   (Ks[2] * distance_x - xofs) ) + //目標距離
   (Ks[3] * vx); //速度

acyt = (Ks[0] * thy)+
           (Ks[1] * thvy)+
           (Ks[2] * distance_y - yofs) +
           (Ks[3] * vy );

//ローパスフィルタ //LPF:y=(1-r)y+ru(u入力、y出力、rフィルタ係数r<1)*(2^n/1) #define LPF_f(y,u) y = (LPF_A*u)+((1-LPF_A)*y)
#define LPF_A 0.05
LPF_f(acx, (acxt-acx));
LPF_f(acy, (acyt-acy));
/*積分*/
vx += acx; vy += acy;
distance_x += (vx); distance_y += (vy); MotorSpeedX = (vx);
MotorSpeedY = (vy);

このような形になります。

「6軸センサー(角速度と加速度)の制御」

今回はMPU6050と呼ばれるデバイスからセンサデータを取得し、角度を得ました。
 MPU6050は少しだけ他のデバイスと異なっていて、DMP (Digital Motion Processor) という機能を使うことで、補正済みのデータを簡単に利用できるのが特徴です。一般にジャイロ(角速度センサ)の特性は温度によって変化し、ノイズも多く乗るので適切な処理が必要とされています。
私は角度を得るために今回DMPのバージョンとカルマンフィルタのバージョンを作りました。
DMPのバージョンは多くの記事があるので割愛して、初めてセンサーを触る人のために簡単に分解能についても話し、その後カルマンフィルタについて少し説明したいと思います。

分解能

このMPU6050などセンサーを調べている際にLSBという文字を目にすることがあります。LSBとは最下位のビットではなく(私が勘違いした例なんですけど)制度を論じていて、分解能という意味です.
分解能の概念は以下のサイト曰く、1メートルの物差しに1ミリメートル単位で目盛りつけた時の目盛りが、分解能だそうです。
分解能 - National Instruments

詳しくは以下のサイトなどがよくわかりやすいのかと思うので査収ください。
www.widesnow.com



カルマンフィルタ

カルマンフィルタは逐次ベイズフィルタの一種で、オンラインのフィルターです。簡単にいうと確率論をベースにしたフィルターで、昔のアポロ計画、カーナビ、今回のように角度を求めるなどなどの様々なところで利用されていて、モデルが線形である(または線形近似したもの)ことや,ノイズがガウス分布である必要があります。


基本的には

  • 状態空間表現(動作モデル,観測モデル)
  • 予測ステップ(事前推定値,事前誤差共分散)
  • フィルタリングステップ(カルマンゲイン,事後推定値,事後誤差共分散)


の三つを基本としています。
簡単にざっくりいうと対象のデータにはホワイトノイズが乗っていてその際にはどれがどのノイズかがわかりません。
そこでデータの中間を取り、それに対してその時共分散という値の関係する度合いを用いて、誤差に寄与率加えて、センサーのノイズを薄めるという手法です。



今回の場合、なぜ使うのかというと、角度を求めるのには加速度センサーを使うことで求めることができ、止まっている時は重力加速度のみなので、十分に値が取ることができます。ですがそれだけでは並行に移動し加速(以下並進加速度と呼ぶ)している時に思わぬ値が出てしまいます。そこで、角速度センサーの値を用いて、移動している時は角速度センサーの値を用い、相補的な方策で立てて対抗をすることができます。



しかし、角速度センサーには弱点があり、ドリフトと呼ばれる値のズレが存在します。それに対してのアプローチの方法がこのフィルターなのです。



具体的には

  • ジャイロにドリフトあるが、加速度センサには誤差ないとしたときがある。⇒この時は、誤差の要因は全てジャイロであり加速度センサの値を正解として補正をしたい。
  • ジャイロにドリフトないが、加速度センサには誤差あるとしたとき⇒この時は、誤差の要因は全て加速度センサであり加速度センサの値は無視したい。


という判断をしていかなくてはいけません。



もし詳しく知りたい場合は以下の記事を見てください(私の説明が正解なのか怪しいので)
qiita.com



さて、以下にソースコードを示します。なお、このソースコードは以下のサイトを参考にしました。
TKJ Electronics » A practical approach to Kalman filter and how to implement it



gist.github.com
gist.github.com

このような形になります。ぜひこれはソースコードと参考サイト、上での紹介した記事をぜひ読み込んで理解してください。


機体の設計

結論としては、球乗りの機構を実現するためにオムニホイールをモータ軸につけ、等間隔に3軸を並べそこへ球に乗せる形を作りました。またギアによるバックラッシをなくすためにステッピングモータを使用し、それをダイレクトドライブにしました。それ故移動制御 がパルス分だけの移動なので確実に移動距離を把握できるようになりました。

言葉ではわかりにくいので以下の実際の球乗りの台座を写真a写真bを参照してください。

f:id:taketarou2:20161225002808p:plain:w300
f:id:taketarou2:20161225002816p:plain:w300

ちなみにbは改良を行い捻りを加えサイズの大きいモータでも十分にコンパクトな サイズにできるようにしたものです(論文中と同じですね)

さて。モーターが三つなので少し複雑になりました。そのためにx,yの制御をに変換しなくてはいけませんですので、

まずはX,Y軸の制御を変換するために球駆動のための車輪速度の算出を行いました。

車輪速度の算出

始めに球の中心を原点とする局所座標系を定義します。
(図a)この座標系はロボット本体に固定し,z軸は球の中心とロボットの質量中心を通る鉛直線として,x,y 軸はz軸に垂直に定義します。
f:id:taketarou2:20161224225324p:plain


1.球の角速度ωを得るための車輪の速度を導くために、車輪iと球の接点をPiそ の位置ベクトルをpiとする.球の角速度ω対応する,Piにおける球の周速度viは次式で得られます。
f:id:taketarou2:20161224225435p:plain:w300

2.球の周速度vと車輪の周速度vsの関係を導出する。(図b)最初に右の図の ように速度vを車軸に平行な成分vfと垂直な成分vsに分解する。vfは車輪外周 の樽型の小さいローラの自由な回転によって生成され、vsはモータの回転によ る車輪の周速度である。このvvsは,車輪の駆動方向単位ベクトルsによって対応付けられ、
f:id:taketarou2:20161224230140p:plain:w300
となり、vsの正負は車輪の回転方向を示す.各車輪の位置piと方向siを定めることにより、角速度に対応する車輪速度が求まります。

3.vsの正負は車輪の回転方向を示す。各車輪の位置piと方向siを定めることにより、角速度に対応する車輪速度が求まり、車輪の速度の基本式が
f:id:taketarou2:20161224230256p:plain:w300
とわかります。

4.3の式よりモータ3つの式を求めていく。天頂角φrを球の半径と置く時、位置ベクトルpiは以下となりました。
 f:id:taketarou2:20161225000804p:plain:w300

5.駆動方向siは球の俯瞰図及び車輪の上面図(図a)より
 f:id:taketarou2:20161225000858p:plain:w300
となる。

6.x軸周りに角速度ωxで回転させる時(ω=(ωx,0,0)とする時)サラスの公式を 用いて4.、5.より求めました。
なお単位ベクトルの和は
 f:id:taketarou2:20161225001435p:plain:w300
とします。

 f:id:taketarou2:20161225001307p:plain

7.同様にしてy軸周りに角速度ωyで回転させる時(ω=(0,ωy,0)とする時)を求めました。
 f:id:taketarou2:20161225001654p:plain

 以上よりx方向とy方向へのベクトルを分解する式を得ました。
 これをソースに書き起こす際は以下のようにしました。
 なお以下で√3/2を近似で扱った理由としてはマイコンのスペックを考慮した故です。

  //x>>1は1/2、√3/2~=222/256->√3/2*256=221.7という近似で扱っている 
  Moter_action_1 = -((long)MotorSpeedX ) + 0;//モータ1
  Moter_action_2 = ((long)MotorSpeedX >> 1) - (((long)MotorSpeedY * 222) >> 8;)//モータ2
  Moter_action_3 = ((long)MotorSpeedX >> 1) + (((long)MotorSpeedY * 222) >> 8);//モータ3

これらを用いて加速度的にモーター駆動を行いました。
この時加速度的というのは自分なりでいいのでオレオレ加速度(つまり自然界の尺ではなく相対的なものでもいい)を作りモーターの駆動を行いましょう。
意味がわかりにくいと思いますが、V=V0+atみたいなことになれば良いのです。ここがかなりキモになります。

もしピンとこない場合は以下のソースコードを読んでください。モーター駆動の記述でオレオレ加速度を設定しているのがわかります。
self balancing arduino robot

機体の作成

せっかくなので、初めて旋盤やポール盤、シャーなどを使い、色々試行錯誤した後も含め見てもらいたいと思います。

1番最初は、
   f:id:taketarou2:20161225025750j:plain:w300
このような形で鉄を曲げてそれに小型のステッピングモーターを入れました。
ちなみにアルミの柱、オムニホイールのハブはアルミの廃材より全て手作りです。(ほんと苦労した。。。。)

ですがこれでは若干のトルク不足など応答性が低いということがありました。その後もこれをベースに何度か改良をするのですが、残念ながらうまくいきませんでした。

下の写真は改良の跡で、写真の上には、球を止めるための機構で、キャスターで使うような玉がついています。
改良を行った際にピラミット型にしてその表面三つにモーターを設置できないかとアプローチした後です。
f:id:taketarou2:20161225030847j:plain:w300



その後思い切って下のベースごと変えました。

f:id:taketarou2:20161225030245j:plain:w300

この時ねじりを加える工夫を行い、モーターも通常のステッピングモーターへと換装しました。

ちなみにモーターのブランケットも手作りで、
f:id:taketarou2:20161225030648j:plain:w300
このような台紙をCADで作り、それを元に廃材のアルミ板を切り、曲げて、下のようになりました。
f:id:taketarou2:20161225031214j:plain:w300

中間はまだ安定してないのでスカスカでした笑

f:id:taketarou2:20161225031638j:plain:w300

そして上部には下からモータードライバー、マイコン、センサーと設置しました。
f:id:taketarou2:20161225031903j:plain:w300
f:id:taketarou2:20161225031940j:plain:w300
f:id:taketarou2:20161225032006j:plain:w300

そうして現在の改良を行った形へとなりました。

まとめ

ここまでお付き合いいただき有り難うございました。
肝心のこれって立つのという話ですが、まだ5〜15秒ぐらいしか安定しません。最長で30でした。何が悪いのかわからんので今後の課題です。

それと、実はこのロボットの機構には続きがあって、”ステキなすてっき”という親父ギャグの効いたシステム名をつけてもらい、まさかの友達にロゴを作ってもらうなど、いろいろなことをしました。

f:id:taketarou2:20161225040851p:plain
また、スマホで動かすためにespwroomというWi-Fimoduleを繋いでいて、iOSアプリサイドのお話も実はあるのです。また、espwroomもArduino化していて、温湿度と気圧をはかり、ミスナールの式で体感温度や気圧の変動のスパンで簡単な天気予報をしてくれる機能がついている。といったまだまだ実はネタがありますが、それはぜひまたの機会にとでも思います。もし気になる方がいれば説明書を以前作ったのでぜひ見てください。
Suteki-Na-Stick/SutekiNaStick取扱説明書.pdf at master · Suteki-Na-Stick/Suteki-Na-Stick · GitHub

 これを手伝ってださった先生や、関係している方々、所属してる部活動の人たちに感謝の気持ちを申し上げます。

 また、まだまだ初学者の身分で偉そうなことを言っていて、これにも間違えがあるかもしれません。もしよければ優しくご指導ください。



 最後になりますが、これを通じて何かお互いに拙い文章の中でも学べるものがあれば幸いと感じます。


 Studentアドベントカレンダーお疲れ様でした!!!(結局当日の朝4時までかかったので遅刻(白目))

Haskell(再)入門2回目中編。

こんにちは。竹です。そろそろ"MASAKARI"が飛んできそうで震えてますがやります。怒られることにより圧倒的な成長((

関数の定義方法。

名前::引数 ->返り値

これだけです。忘れないでください。いきなり使います。(突然)
詳しいのは後々説明しますが、とりあえず今日はこれをまず覚えてください。あとから使います。

思い出しフェイズ

[ ]

これ覚えてますか?多相型です。この前出したキーワードでした。
”仲間としては、タプルやEitherなど。
具体的に言うとC++のテンプレートのようないわゆる型ジェネリックと言われているもののように柔軟に扱えれるタイプのことです。”(前回記事よりコピペ)

今回はこれにフォーカス当てて型の続きを進めていきたいと思います。

多相型は型変数

型変数の中でも幾つかを多相型と呼びます。
Haskellにおいて多相型の具体例は

  • リスト
  • タプル
  • Either
  • Mayby

などがあります。
今回はこれらを使って”多相型と型変数”のテーマでいきたいと思います。

リスト

リストはリストです。他の言語と同じで”何かの型のリスト(配列)”という形になります。(しかし飽くまでHaskellは一つの型のみ。)
具体的には文字のリスト

[Char]

整数のリスト

[Interger]

といった感じです。
ちなみにリストの先頭に要素を追加するときは

入れたいもの:[ ]

でできます。

さて「型変数is何?」って思うと思います。ではリストの中の長さを求める関数(突然関数を覚えろといった理由)を考えることにしましょう。
例えば

[Interger]

の長さの関数を考える時

[Interger] -> Int

といった具合になります。
その際、Doubleで使いたい時とか毎回とか型を変えて関数を作るのって大変ですよね。そこで型を変数のように振舞わせれたら楽ですよね?
安心してください。それが型変数です。
ex.

length::[T] -> Int

このように定義できます。
ちなみに型コンストラクタと言ってある型に別のものを足しあわせて別の型を作ることを型コンストラクタといいます。
リストで考えると

[]

で包んでリストになるリスト型の型コンストラクタと理解してください。

タプル

いわゆる無名構造体です。2つの値を組みにした構造です。
Haskellでは

(4,5)

このように表現します。
これも多相です。
ちなみに二つの型の組み合わせを使って作る型を直積型とも言われます。

Either

二つの値のうちどちらかを取るのがEitherです。
Haskellではどっち取るかをLeft,Rightで表現します。


ナニコレ

下書きに入っていた頑張ってた跡がある過去です(めんどくさくなったんで勝手に打ち切り)

esp-wroom-02でラジコン作って遊んだのでまとめとく

この記事はStudent Advent Calendar 2016の24日目の記事です。

qiita.com


f:id:taketarou2:20161223114317p:plain
どうにか事故?自己紹介を回避しました褒めてください。



esp-wroom-02ってみなさん知っていますか?強いWi-Fiモジュールです。
知らないのであればググり倒してください。以上です。



さて、当記事は完全二番煎じで、以下のものと同じようなノリです。がっかりした方ごめんなさい。
あとやっつけです。実質2日分ぐらいで終わります。(私は、モーターの電流特性計り忘れてモタド殺したりしてしまったのでその辺なければ1日ぐらい)

https://www.elekit.co.jp/product/docs/PU-2709Wi-ficar.pdf

ハードウェア構成

RCカー を作る ( バギー工作基本セット + Arduino + Bluetooth + Androidスマートフォン )
ArduinoBluetoothesp-wroom-02で置き換えて、行いました。

また今回は速度を出すためにトルクチューンモーターを採用しました。個人的には普通のモーターでも十分です><(理由は反省点で述べる)
トルクチューン2モーター タミヤ ミニ四駆モーター・電池 15484 :4950344154845:みなと模型 Yahoo!店 - 通販 - Yahoo!ショッピング

これを使うための注意点として電圧がmax3Aなのでそれに対応したモータードライバーを使用してください。
DRV8835使用DCモータードライブキット: 組立キット 秋月電子通商 電子部品 ネット通販
私はDRV8853を採用しました。回路図はめんどくさくて作ってないです><ごめんなさい><

ソフトウェア構成

スマホをコントローラーとしてesp-wroom-02UDPでデータを投げつけたいと思います。
UDPの採用理由としてはOSCアプリ等でも利用するのを前提にしたからです。

今回はiOSのネイティブアプリを作ってUDPで投げつけました。
(時間なくてUIを作り込めませんでしたが。。。)


以下にソースを示します。

ラジコン側(esp-wroom)

gist.github.com
gist.github.com

iOSのやつ

github.com

UDPで投げるためにSwiftSocketというライブラリを使って投げました。
cocoapods.org


これらを組み合わせて使う感じです。

完成!

すいません画像撮り忘れました(学校に置きっぱなしにしてしまった。)
年明けには更新します・・・・

反省点

モーターを欲張ってトルクチューンモーターにしたところ、まさかの定格で書いてる3Aを超えて流れて熱暴走をしてしまいました。。。。(余裕を持ったHブリッチ買えばよかった。。。。)
うまくいかないのでコンデンサをモーターにさしてやったり(セラコン0.1pFぐらいかな?)逆にダイオード差し込んだりという手でどうにしましょう(リプル殺せるので)。



次は竹 (@takemioIO) | Twitterさんですw!(俺やんけ)

進学って大変ですねっていうポエム

進学って大変ですね

 こんにちは。しくじり先生(?)です。進学なんか決まったぽいんで悔しさと浅はかさを込めて自戒のための記事を書きます。ぜひ笑ってください。
(単純に希望大学全部落として、第四希望ぐらいのAOでスルッと地元の私大の新設の情報学科に入ってしまったというオチ)

 あとこれから技術だけで受けようとする人に対してちゃんと考えて欲しいという気持ちで書きます。ぜひ受験生の人は考えてください。

お前ってどこ受けたの?

coinsと農工大電通(夜間)と地元の私大です。

お前ってなんで大学行きたかったの?

高校進学時は大学でも終着駅は就職なら就職でいいだろと思っていました。
ですが元カノに大学行こうぜって誘われ、そのうち自分自身が情報を学び進めて行くうちに、様々なことに興味が出てきて、関数型言語に興味があり、特に型理論(リファーメント型でのコンパイル時の安全性など。。。)を学びたくなったから。

お前にそれだけの頭あったの?

頭ありませんでした。地元の工業高校(偏差値は50前後だと思う)に在学で評定は安定して3.5でした。

お前技術力はあるの??

微妙なところです。高校プロコン優勝でITジュニア賞もらったり、サイバー甲子園で入賞して、2015のSECCON決勝大会に出場したり、iCANという国際大会の予選に出て奨励賞とか、地元のソフトウェアコンテストで一位になってみたり、機械学習が好きで遊んだり、関数型好きで勉強したり人並み以上だとは思ってました。

実際の受験フロー(しくじり部分ともいう)

 僕は三年時にパソコン部(名前は違いますが)で部長をやっていて10月の文化祭が引退でした。ですの本当は受験勉強で忙しい3年の夏も大会のために強制的に平均睡眠時間3時間ぐらいでマイコンをいじりプログラムを書いていました。そこで私は一般を早々に諦めて技術力だけでの勝負に切り替えました(つまり推薦やAOに切り替えた)
しかしそれでも大学に出願するには大変時間がありませんでした。(どれくらい時間がなかったかというと大学に間に合うのにのせなきゃいけない郵便配達の集荷の締め切り1時間前までやってたり、台風なのに高校まで行って調査書を取りに行くなど。。。。)



 さて微妙な出来の書類をまずはcoinsへ出しました。このとき、色んな人や先生、フォロワーさんに見てもらったりして大丈夫でしょと言われ自信満々でした。
 しかし落ちました。辛い。今思うに評定なのかなとか思います。
 さて農工にも出しました。実際に受かった人に見てもらっておそらく一次は確実に通るって言われたりしてたので、この時も自信満々でしたが。落ちました。
 



 さぁ困りました。次どうしよう。。。迷走します。センターとりあえず払いこむとか他の推薦やAOを探すとか色々手当たり次第探していました。



 迷走を経て次の進路を決めました。電通大の夜間を受けることにしました。
 理由は単純でお金の面を心配せず行え、やりたい研究室もあり、かつMMAに入れるから。
さてそれに向けて頑張りました。ちなみに夜間と言いながらも入試問題は一般の電通大の推薦入試と同一の問題です。ですので私の高校では開講していない基礎なしの物理や化学、数学Bなどを自力でやりました(必死)

 しかし、努力叶わず爆死しました。それは今年の問題がレベルが過去三年分と比べてえらく上がっていたということ。例えば電磁気が今までは電気回路だったのがいきなりコンデンサの静電容量がどれくらい貯めれるとかクーロンの法則が出たりなど、また僕がそれに対して絶対これだろというふうにある程度ヤマを張っていたこと。ちなみにヤマは全て外した記憶があります。本当にしくじりました。まさか融合問題が出るとは。。。。(頭抱え)


 その後とりあえず浪人はみんなに止められたので、やめようという方針を立て始めた失意の中、顧問の先生の助けを借り、第四希望の大学に出願したのがポーンと受かりました。(おそらくそれは面接に出した賞状で殴った感じだと思う。)
まぁそんなもんだろうみたいな感じ。

まとめと反省と僕みたいに失敗して欲しくないためのポエム

 受験をなめてた。正直夏休み明けの時点で高校選択間違えたなと、さえ思った。
中学の時にもう少し頑張って高専狙うとかできれば。。。とか評定がもう少し高ければ。。。とか就職であれば楽だったのに誘われてたとこに行けば。。。とか自分より実績がない部活の同級生が公立に受かるのを見て公立なら受かったのかな。。。とかIFばかり考えてしまう。本当に後悔後先立たずとはこのことなんだろうなと思う。
 

 だけどもこの経験は後悔してはいない。自分自身の足りないところや至らないところ。言葉ばかりでとり作ってきたところ。本当に色んなところに気がついた。精進が足りませんでした。過程があれば評価されると思っていた。本当に甘かった。


もしこの記事を読んでくれた中高生(特に工業高校の人)がいるならしくじった人並みのアドバイスをします。

高校生へ。
 一度将来をしっかりと考えましょう。このためになら1~2日潰しても構いません。ネットサーフィンしまくるなり、本屋さんに行くなりして何やりたいのか考えましょう。いつでも遅くありません。できるなら一年生の時からです。
 そしてもし就職なら評定を一生懸命上げましょう。
 進学ならば、1年生は今すぐ河合塾に行くなりスタディサプリ(科目の足りない学校にいるならなおさら。)を取るなりしましょう。最低限進学就職どっちに転んでもできるように知識をつけましょう。一年生なら評定もあげやすいですし一年生の科目だけを課す試験が就職にも進学にも多いです。
2年ならまずは模試を受けるべきだと思います。自分の実力によっては最悪頑張っても難しい場合があります。全統模試など全国クラスのにしましょう。自分が低く出た方が危機感が湧きます。
3年次の人で早い段階の入試を受ける場合で部活が忙しいなら部活をやめましょう。それくらい覚悟が必要だと思います。

中学生へ。
 もし工業高校に行きたいとか思う人がいたとしてもやめておくべきだと思う。少なくても大学に行くのがお金的に無理とか家を継ぐとかない限り。もしくはそこの高校でしかできないとかない限り。初め進学なんてしねぇよと思っても、専門分野を深く学ぶうちにやっぱ大学進学したいと思うようになると思います。特に大学数学などが必要だったり化学が好きだったりとかだと特にその可能性が高くなります。(正直工業高校の化学は実用よりで大学の範囲までは言わないので)
それでも専門分野を学びたいと思うならば高専か理数科を目指すべきです。高専であれば3年次編入があり、それは高専生向けである場合多く、進学時学んでないなどでのカリキュラムで困ることが少ないと思います。理数科であれば特に物理系の部活や化学系の部活などで工業高校でやれる部分と同じ理論基礎に対して取り組めます。また、もしそのような取り組みをした場合、理数科目でのバフになり得ることが多く点数が取りやすくなり、さらにはその学校が科学オリンピックなどに力を入れてる場合が多いです。

高いレベルの高校に行く意味はあります。先生の質も変わります。是非頑張ってください。


これらは人によってはそんなことないみたいな顔するかもですけど少なくても僕がすればよかったなと感じたことなので書きました。


 僕はこれから大学生活をするわけなんですが足りない科目を自力で埋めなきゃいけません。辛いです。ですが一つやろうとしていることで大学での編入を目指そうと思っています。そのためには一度高専に行くとかしなきゃいけないんですけど。。。自分のやりたいことをするために賭けてみたいと考えています。


以上ポエムでした。

何かあれば@takemioIOにメンションをください

Arukas-CLIをbrewで入れる

 こんにちは今回はクジラさんではなくイルカシャチさんに(イルカに見えたんだもん)簡単にお世話になろうという話です。

 仮想化技術、皆さんは使っていますか?VMとかVagrant とかdocker使っていますか?使ってますね。僕もお世話になっています。



・・・ではもう一つ知っていますか?「Arukas
arukas.io

なんと純国産の仮想化コンテナ技術を提供するサービスである。ちなみに今ならベータ版という理由で使い放題無料なので今のうち使いましょう!

本題:Arukas-CLIbrewで入れる

 さてそんなArukasをじゃんじゃん使おうぜということでArukas-CLIを簡単にbrewで入れようという記事です><
 ちなみにですが今は公式だと手動(バイナリDL)大変なのです><
github.com
qiita.com
上のqiitaには入れ方があります。



brewとは。
Homebrew — OS X 用パッケージマネージャー

 正式名称はHomebrew。詰まる所Macintosh用のパッケージマネージャーです。これを入れると簡単に様々なライブラリ、フレームワークやソフトウェアを入れて便利って感じのものです。これは入れてあるものとして進めます。(入れてない方はbrewインストールとかで調べて戻ってきてくださいね><)


インストール(brewで)をする。

 

Go言語でつくったツールをHomebrewで配布する · THINKING MEGANE


などを参照するとわかるのですがHomebrewに独自リポジトリを実は入れることができます。


上のブログのことをやると brew tap [リポジトリ] , brew install arukasが可能になります。


ただ面倒なので私は直で作ったFormulaファイルを/usr/local/Library/Formulaに投げてbrew install arukasを行いました。



では実際に入れていきましょう。




まずは投げる前に
github.com
からarukas.rbを拾ってきましょう。



拾ってきたら/usr/local/Library/Formulaを参照してarukas.rbを突っ込みます。



そしたらbrew install arukasをしましょう。終わり(早い!!)
これを手動で入れるとめんどくさいのにこんなに簡単ヾ(・ω・*)ノ ワーイ


CLIを入れれた人へ

arukas.io

(力尽きたので上見てやってください(時間があればエントリ書きます)><)

ステッピングモータSTP-42D108の覚え書き

 この前STP-42D108というステッピングモータをちょっとした理由で手に入れた。しかし残念ながらネットを探してもデータシートがなく大変な目にあった。特にとりあえずこれで回るよって言われた経緯で手に入れたものであったので、心置きなく使ったところモータドライバが壊れる壊れる。合計5個ぐらい使った。。。。><。 しびれを切らしてこの販売元のシナノケンシ社に連絡を投げてみました。返答は「外注で作ったものなので教えません(意訳)」どうしても使いたいので交渉をしてトルク特性等以外を聞くことは成功しました。
 以下に記述する。 

STP-42D108のデータ

 STP-42D108: シナノケンシ
 ステップ角 : 1.8 deg / full step
相 数   : 4
 定格電圧  : 2.4 V D.C.
定格電流  : 1.2 A / 相
 サイズ   : 42×42×31(mm)
 口出し線の色: 白→Acom,黒→Bcom,橙→A,赤→B,青→ba-A,黄→ba-B,

こんな感じです。
 

  • とりあえず電流が高いのでモータドライバをFETで自作しないで使う場合はmaxアンペアに注意してください。
  • 2相励磁だと2.4Aとかいうひどいものなので気を付けましょう。
  • また使う際はクラット抵抗やセメント抵抗で端子間に入れるとか外部抵抗に入れるをすると良かった。

セキュリティ・キャンプ全国大会2016の応募用紙を晒す(後編)

自信がないなぁ。。。。後編は選択問題についてです。選択問題は4つ 選択でした。多分間違っていますしボロボロです。。。がそれよりも多くやってしまってたので提出してない分も晒す。(提出したのは4,5,6,11)
以下本文〜〜まんま載せます。

【選択問題】

選択問題.1: 以下は変数hogeとfugaのメモリアドレスを表示するプログラムと、その実行結果です。実行結果のhogeとfugaのメモリアドレスを見て、思うことを説明してください。
・ソースコード
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char **argv){
 int hoge[10];
 int *fuga;
 
 fuga = malloc(1);
 
 printf("hoge address = %p\n", hoge);
 printf("fuga address = %p\n", fuga);
 
 free(fuga);
 return 0;
}
 
・実行結果
hoge address = 0x7fff539799f0
fuga address = 0x7fca11404c70 

スタックに積まれたhogeは上位のアドレスに積まれて、fugaはヒープ領域の下位アドレスに積まれています。
先頭の0x7fというのは7ビットの部分を表しているのかと考えています。以前にGCCXcodeでヒープ領域がどこに割り振られるのか見たことがあるのですがその際、先頭アドレスが前者は0x7fで後者が0x10であったので処理系によって変わっているのではないかと感じました。

選択問題.3 :RAMは主記憶装置、HDDやSSDなどは補助記憶装置と呼ばれます。一般にCPUは主記憶装置上のプログラムしか実行できません。ではなぜ、私たちは普段から補助記憶装置に書き込んだプログラムを実行できているのでしょうか?パソコンの電源を入れてからのストーリーを考えてみてください。

電源を入れハードウェアの初期設定が行われ、ブートストラップローダを動かしてBIOSが起動する。(ブートストラップローダはROMに用意されてる可能性もある)Power On Self Testが行われ、CPU、RAM、割り込みやHDD、GPUハードウェアの初期化が行われる。次にBIOSは起動デバイスに設定された記憶装置を探し、。ブートローダが起動する。ブートローダには段階がありプログラムからプログラムを呼び出し、初めてOSを呼び出すことができる。一次ブートローダ、二次ブートローダと細分化できる。この場合は二次ブートローダーでありBIOSは1次ブートローダーである。上でもあるが補助記憶装置に書き込んだプログラムを実行するにはRAM上にROMのデータを展開して起動する。その際できるだけ高速で使うためにキャッシュメモリと呼ばれる使用頻度の多い命令データを保存したりして処理装置と記憶装置を本来の速度を隠蔽したりする。また補助記憶装置をメモリのように振舞わせる仮想メモリはあくまでスワップであり稼働してないものを充てがうのが普通だと考えている。

選択問題.4

突然だが、RH Protocolで用いられるRHパケットのフォーマットを以下に示す。なおRH Protocolは実在しないプロトコルであり、その内容について特に意味は無い。
Format of RH Packet

———————— —————...— ———————…— ———————...— ———————...—
 Magic (2byte)      Source(20byte) Destination(20byte) Data Length(4byte) Data( variable )      
———————— —————...— ———————…— ———————...— ———————...—

 
char Magic [2];
char Source[20]; /* null(‘\0’) terminated ascii strings */
char Destination[20]; /* null(‘\0’) terminated ascii strings*/
uint32_t DataLength; /* min 0, max 4,294,967,295 */
char Data[DataLength]; /* null(‘\0’) terminated ascii strings */
 
バイトオーダーはbig endian(network byte order)とする。
添付するバイナリは、とあるRHストリームのうち片方向のみを抽出したものである。このバイナリストリームを読み込み、1つのRHパケットが以下の条件のすべてにマッチするときに標準出力に文字列”PASS”、 それ以外の場合は”REJECTED”と表示するCもしくはC++のプログラムを記述し、実行結果と共に提出せよ。また、マッチングにかかるCPUサイクル及びメモリ使用量を計測し記載した場合、評価に加味する。
 
Condition(条件)1: Magicがchar[0] = ‘R’、 char[1] = ‘H’であること。
Condition 2: Sourceが”rise-san”または”cocoa-san”であること。なお、”RiSe”や”Cocoa”など、小文字大文字が混ざっていても、マッチさせること。
Condition 3: Destinationが”Chino-chan”または”Chino"であること。なお、cond. 2と同じく、小文字大文字が混ざっていても、マッチさせること。
Condition 4: Sourceが”cocoa-san”かつDestinationが”Chino”の場合はREJECTする。
Condition 5:  Dataに下記の文字列を厳密に含むこと。
char** valid_order_brand =
{
    “BlueMountain"
    “Columbia”,
    “OriginalBlend"
};
Condition 6: Dataに下記の文字列を厳密に含まないこと。なお、cond. 4よりも、cond. 5が優先される。
char** invalid_order_brand =
{
    “DandySoda"
    “FrozenEvergreen”
};

以下送ったやつ

・実行結果 
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
PASS
PASS
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
REJECTED
PASS
REJECTED
REJECTED
ソースコード

////
////  main.cpp
////
////  Created by 〜〜〜on 2016/05/06.
////  Copyright © 2016年 〜〜〜. All rights reserved.
////
//

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <cstring>
#include <sys/time.h>
#include <sys/resource.h>
using namespace std;

int Mstricmp (const char *s1, const char *s2)
{
    int cmp;
    
    while (*s1)
    {
        //toupper:大文字小文字に変えれる関数
        if ((cmp = toupper (*s1) - toupper (*s2)) != 0){
            return cmp;
        }
        s1++;
        s2++;
    }
    return (*s2) ? -1 : 0;
}
int main(){
    char outfile[] = "/Users/HayasakaTakeru/Desktop/RH_secamp/pyonpyon.rh";  //読み込むファイルの指定
    char Magic [2];
    char Source[20]; /* null(‘\0’) terminated ascii strings */
    char Destination[20]; /* null(‘\0’) terminated ascii strings*/
    uint32_t DataLength; /* min 0, max 4,294,967,295 */
    char Data[256] ; /* null(‘\0’) terminated ascii strings */
    string buf;

    ifstream fin( outfile, ios::in | ios::binary );
    //  ファイルを開く
    //  ios::in は読み込み専用  ios::binary はバイナリ形式
    
 //  ファイルが開けなかったときの対策
    if (!fin){
        cout << "ファイル:pyonpyon.rh が開けません";
        return 1;
    }
    
    //文字列ではないデータ
    
    while(!fin.eof()){  //ファイルの最後まで続ける
        //データを読みこむ
        fin.read( ( char * ) &Magic, sizeof( Magic ) );
        fin.read( ( char * ) &Source, sizeof( Source ) );
        fin.read( ( char * ) &Destination, sizeof( Destination ) );
        fin.read( ( char * ) &DataLength, sizeof( uint32_t ) );
        size_t DataLengther = htonl(DataLength);//ホストバイトオーダーからネットワークバイトオーダーに変換
        
        int i=0;
        do{
            fin.read( ( char * ) &Data,  DataLengther);
            buf+=Data;//一時保存
        }while (256<DataLengther-(256*i++));
        
        
       //paternmach
        //Condition1
        if (Magic[0]!='R'&&Magic[1]!='H') {
            goto False;
            
        }else if((0!=Mstricmp("RISE-SAN",Source))&&0!=Mstricmp("COCOA-SAN",Source)){//Condition2
            goto False;
            
        }else if((0!=Mstricmp("CHINO-CHAN",Destination))&&(0!=Mstricmp("CHINO",Destination))){//Condition 3
            goto False;
            
        }else if ((0==Mstricmp("Chino",Destination))&&(0==Mstricmp("cocoa-san",Source))){//Condition 4
            goto False;
            
        }else if (string::npos != buf.find("DandySoda")||string::npos != buf.find("FrozenEvergreen")){//Condition 6
            goto False;
            
        }else if (string::npos == buf.find("BlueMountain")||string::npos == buf.find("Columbia")||string::npos == buf.find("OriginalBlend")){//Condition 5
            goto False;
            
        }else{
            printf("PASS\n");
            buf="";
            continue;
            }
       
       
    False:printf("REJECTED\n");
        buf="";
    }
    
    fin.close();  //ファイルを閉じる
    return 0;
}

・メモリ/CPUサイクル使用量計測
環境:MacBook Pro Retina2014(Core i5-4308U &RAM 8G)、GCCコンパイルしたもので行った。
#include をincludeし、 getrusage関数による最大消費メモリ量のチェックを行った。
Max RSS : 684.000000 MB

rdtsc命令を使用して計測を行った。
CPUCycle(10回計測):
1443299938,
1133714246,
766179364,
3249800630,
2473480668,
3753169854,
4201688936,
1112906710,
3299073340,
420707638

10回の平均値:2185402132.4

最後に計測に使用したソースコードを添付します。

// 最大消費メモリ量のチェック
    int chk;
    struct rusage usage;
    chk = getrusage(RUSAGE_SELF, &usage);
    if(chk != 0){
        printf("error\n");
        exit(-1);
    }
    printf("Max RSS = %lf MB\n", usage.ru_maxrss / 1024.0);    // このプロセスが消費した最大メモリ領域

  //CPUサイクル取得
static inline uint64_t get_cycles()
{
    uint64_t t;
    __asm volatile ("rdtsc" : "=A"(t));
    return t;
}
  cout<<get_cycles()<<endl;

てかstricmpはXcodeにないのな。。。いじめだ急遽作ったわ。。。

選択問題.5 :PCなどに搭載されているOSは「汎用OS」と呼ばれますが、それに対して、家電やAV機器などの「組込みシステム」に搭載されているOSは「組込みOS」と呼ばれます。組込みOSと汎用OSの違い、「OSが無い」や「ベアメタル」という環境、そもそもOSとは何なのか?など、あなた自身はどう考えているのかを、あなた自身の言葉で自由に説明してください。(「正しい答え」を聞いているわけではありません。あなた自身の考えを教えてください)

組み込みOSは必要がない機能を削除する事が容易で、それ故にいらないものを削ることにより小さい構成にしてリソースを確保してるもの、汎用OSは使われそうな機能はすべて盛り込んでおいているものでアップデートで汎用性をもたせているものと思います。
 そもそもOSというものは今までそれぞれ独自の仕様を持っていたハードウェアとのインターフェースとなりアプリケーションやソフトウェアを作るのに一定の指針を持たせたものであり、逆に言えば今日の多様なプログラムが使われているのはOSがあるからと言えると考えています。またアプリケーションとハードウェアのインターフェースだけではなくユーザーとのインターフェースでもあると言えて操作方法が統一されるので、1つの操作方法やシステムコールを覚えれば他の場所でもそのノウハウをそのまま生かすことができます。他にもデスクトップリビューションを組み込むことによりそのOSのブランド性というものも演出できると考えれます。このようにOSというのはアプリケーションとハードウェアだけではなく多くに対するインターフェースと私は捉えています。
 しかし逆にOSがないとどうなるのでしょうか、一般的にベアメタル実行やベアメタルコードなどと呼ばれるのですが具体的には直接ハードウェアを叩いていることを指しています。OSやフレームワークがなくて何が嬉しいかというと自分の手で高速化をすることとだと言えます。普通はメモリを意識しないようなライブラリやフレームワークAPIを使わせてそれを使えばどこでも簡単に駆動を可能に設計しています。しかし高速なIOをしたい時やコンパイルされたプログラムの容量を削りたい時などはレジスタを意識して必要最低限のコードに自力で最適化することにより高速に出来ます。実際Arduinoを高速で使いたくてIOをライブラリではなくポートをいじってあつかった際は数倍速度の向上がありました。このようにレジスタを意識するということだけでもチューニングが出来るようになります。
 違うOSに観点を移すと、例えば組み込みOSは「実時間制約を保証のOS」という言い方も可能であり、RTLinux やART-Linuxが有名です。実際にロボットなどを制御する場合,通常は一定の時間間隔でセンサ信号を読み取り,制御演算を行い,アクチュエータに指令を出します。外部との情報の入出力の可否は,ソフトウェア上では一般にI/Oポートの操作 とメモリの読み書きの可否 でありそのタイミングの周期的な制御動作を達成すれば実際に動かすことも可能だとも言えると思います。組み込みOSでなくても普通のLinuxカーネルで時刻を指定して行いたい処理の直前で、タイマ割り込みの直後などで目的の実行時刻と現時刻の差を指定し、休眠システムコールを行うなどプロセスの優先度を高めておくなどで周期動作は得ることができると考えています。あえて問題を挙げるとすればART-Linuxなど、ある特定のハードウェアでは対応してないなどということがあるのでもっとマルチに作成することが望まれると考えています。
 自分自身のまとめとするとOSは現在のエンドユーザーの手にソフトウェアを私たちエンジニアが届けるのに必要不可欠のもだと思います。しかしそれは今の潤沢なマシーン環境と高レイヤーな考えがあるからであり環境が変わればそれを維持するためにどれだけ高速にチューニングするかというのが勝負に踏んでいます。また今ある資源をうまく使うのもOSの仕事でありリソースの管理を行い、必要に応じてはポーリング、スレッド、メモリの処理もするものだと思っています。例えばスレッドであれば、windowsのThreadやiOSのGCDなどが挙げられ、実際これらの処理は簡単でGCDであればキューに投げ込むだけでそれをOS側が入れられたものの優先度とFIFOで実行していくという形で成り立っています。しかし並列であるならばデッドロックが起きる可能性もありえます。チューニングしていく上で仕方がないことではありますがOSだけではエンドユーザに良いソフトウェアを届けることはできないと言えるところだと思います。つまるところの結論というものはまだ未熟な私には出せませんが一番感じていることはOSはという考え方があったからこそ潤沢なアプリケーションがあり我々はハードウェアに苦悩しないのだと感じています。

選択問題.6 :IDとパスワードを入力してユーザの認証を行うWebアプリがあります。あなたがこのアプリに対してセキュリティテストを行う場合、まず、どのようなテストをしますか? なぜそのテストを選択したのか、その背景や技術的根拠と共に記載してください。アプリの内部で使われている技術やシステム構成に、前提を置いても構いません

今回使われているのはバックにDBがありNoSQLとSQL系の2パターンと想定して、その際使われているのはApacheサーバ(PHP、Laravelやcakephpといったフレームワーク)や他のサーバフレームワーク(node.jsなど)という想定でテストを考えた。

まず使用しているものバージョンを確認し、node.jsであればnpmのパッケージに脆弱性があったりなどosinjectionの危険を回避したいのでバージョンが古い際は最新版にできるだけ変更します。
次にWiresharktcpdumpなどを開いてパケットを見ながらレスポンスを確認を行います。その際PHPのバージョンの隠蔽などを確認し、Cookieにhttponlyの属性を付けるなどもしておくべきと考えます。(その際ヘッダ周りを見るべきでX-Content-Type-Optionsなどが叩かれる恐れがありえます)。またワンタイムトークンなどを導入するなどでCSRF などの対策をすべきで、他にもXSSの対策について確認を行い、バインドして『”’<>&』などを文字実体参照・数値文字参照に置き換え、弾くようにします。
その次にDBに対してチェックを行い、NoSQL系であれば演算子インジェクションやSSJI(Server Side JavaScript Injection)、JSONを使ったinjectionなどで攻撃が可能なので、対策としてはSSJIであればバインド機構を入れたり動的なJSを避けたり、演算子インジェクションであれば型にキャストするなどで対策ができ、ホワイトリストを入れたりしてパラメータをを追加されるのを阻止するのも有効だと考えれます。
SQL系であればSQLinjectionがあるのでバインド機構を入れてサニタリーングをしたりホワイトリストを入れるのも有効だと言えると思います。
他にもSQLmapなどを使って脆弱性の確認などをするのも有効だと言えます。
次にサーバの権限の制限を確認し、トラバーサルができないようにしておくなど、またidなどをパラメータに入れて投げるときはすでに許可してるものをキーとしている時などに気をつけるべきだと思います。それを含むとトラバーサルできてしまうので、気を付けたいところと考えれます。

選択問題.11 :2015 年に発行された CVE の内、あなたが興味を持った”サーバに存在した”脆弱性について1つ提示してください。その脆弱性を悪用した攻撃を検知する方法について詳細に記述してください。また、興味を持った理由を記述してください。 CVE番号:CVE-2015-◯◯◯◯

CVE-2015-1793について
攻撃を検知する方法:
 この脆弱性はOpenSSLの証明書チェーンのチェック機構に不備があったというものです。この脆弱性を利用した際に想定されるのはman-in-the-middle attackが想定されます。証明書の検証において初めの証明書チェーンの構築に失敗した場合、代替の証明書チェーンの構築を試みますが、この処理の実装に不備がありました。その結果、例えば CA フラグが FALSE とされている証明書を使って発行された証明書を、不正なものであると検知せず、バイパスして信頼している CA によって発行された証明書として扱ってしまう可能性があります。
 具体的に効率的な対策を思いつかなかったのですが、今回考えられるのは中間者攻撃なので直接サーバーにつなぐのではなくサーバを経由して別サーバでのチェックとサーバーでのIPのチェックをするという手を取るのが良いかと考えました。
 具体的にはAが接続者、Bがサーバ、Cが別サーバとした際に攻撃者がAB間、AC間のどこかに接続をしなくてはなりません。流れとしては、まずAC間およびBC間の確認を行います。
A->B: CのIPアドレス->B:認証、
B->A: CのIPアドレス->A:認証
これにより、Aの確認者とBの確認者のIPアドレスが一致しなければ、 AC間またはBC間に攻撃者がいることが判明します。
次にAB間の確認をします。
A->C:BのIPアドレス、C->B:AのIPアドレスをCに送る、B->C:AのIPアドレス、C:認証、C->A: 認証結果、C->B: 認証結果。
これにより攻撃者がいない通信経路が成り立っていることが確認できたなら通信が窃盗されるということはないと思います。
弱点としては攻撃者がAB間およびAC間に同時に割り込むことで迂回される恐れがあると考えます。その際はCを動的に変え続けるなどして接続を乱すことで対応できるかなと思っています。

せっかくなので脆弱性のコードを見てみました。”openssl-1.0.2c/crypto/x509/x509_vfy.c”が攻撃される原因のところです。

// CAが追加されるところのソースです。
        // continue to construct the chain of certificate(add issuer)
        for (;;) {
            // self-sign and exit
            if (cert_self_signed(x))
                break;
            // look for the issuer in the trust chain
            ok = ctx->get_issuer(&xtmp, ctx, x);
            // error
            if (ok < 0)
                return ok;
            //  not found
            if (ok == 0)
                 break;
            x = xtmp;
            // add the issuer for the untrusted certificate to the chain of verification
            if (!sk_X509_push(ctx->chain, x)) {
                X509_free(xtmp);
                X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
                return 0;
            }
            num++;
        }
// CAのチェック機構です
        // verify the issuer chain in for (;;) 
        i = check_trust(ctx);
        if (i == X509_TRUST_REJECTED)
            goto end;
        retry = 0;
 // 代替チェーンを検証
        // verify the alternative chain
        if (i != X509_TRUST_TRUSTED
            && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
            && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
            while (j-- > 1) {
                xtmp2 = sk_X509_value(ctx->chain, j - 1);
                 // return when get a “reasonable-like” certificate,in fact look for the issuer based on CN domain
                ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
                if (ok < 0)
                    goto end;
                // alternative chain exists
                if (ok > 0) {
                    X509_free(xtmp);
 
                    // remove the part above the alternative chain
                    while (num > j) {
                        xtmp = sk_X509_pop(ctx->chain);
                        X509_free(xtmp);
                        num--;
                        // 信頼できない証明書を削除
                        // the problem is 
                        ctx->last_untrusted--;
                    }
                    retry = 1;
                    break;
                }
            }
        }
    } while (retry);

考察:今までのOpenSSLは代替チェーンの検証をサポートしていない古いバージョンであったのでバグらなかっけれどもある程度まともにサポートしたせいでバグが出てきたのかなと推測してます。

興味を持った理由:
 なぜこの脆弱性に興味を持ったかというと中間者攻撃は通常はSSLが正常に動いていれば不可能な攻撃なのですが、今回は肝心要のSSLに問題がありました。ですので実際ゼロデイとかで叩かれたら大変だと強く感じたのでこれを選択しました。
 この脆弱性が出た時他のOpenSSLの脆弱性もかなり多く一緒に公開されました。しかもほぼ緊急度が高めのばかりでそれで大変印象に残っていたからです。例えば2015-1792であればcrypto/cms/cms_smime.cのdo_free_upto関数には、signedDataメッセージの処理に脆弱性が存在し、攻撃者によって細工されたsignedDataメッセージを処理することでサービス運用妨害(無限ループ)状態にされる可能性がある。などかなり怖いものばかりです。しかしあまりその時は知識もなかったので詳しく見るということをしませんでした。(ベンダー情報しか見てなかった)ですので今回見てみました。(かなりガバガバこと&多分ソース読み違えたことしか書いてませんが。。。)

感想

楽しかった!!

自分自身こうやって知見を広げれるのはやはり大きな強みだなぁと感じた。でもかなりボロボロなことばかり書いてるのでもし受かったら気合って感じで通ったって感じですね。。。
あと機種依存文字今度は死なないように
機種依存チェッカー | さぶみっと!JAPAN

を置いておきますね。来年も同じパターンならこれ使って提出してください><