logicoolのマウスがチャタリングを起こすので修理した

はじめに

僕はlogicoolのマウスを愛用しています.これまでに買ったマウスは,

MX620

M570

G700s

しかし,もう購入して3年以上たっているので,チャタリングが多発するようになりました.そこで,今回の記事ではM570とG700sのスイッチを交換した記録をまとめようと思います.

M570

代替品

ネットでググった情報をもとに,オムロンのD2F-01Fを2個購入しました.マウスの左クリック・右クリック部分のスイッチを交換していきます.

分解手順

これがM570です.

分解していきます.
分解には,トルクスレンチのT5が必要です.

ウラ面の滑り止めを3つ剥がし,計4箇所のネジを外します.


電池ボックスのシールを剥がし,その下のネジも外します.

これでマウスのケースを分離することができます.ケースを外したときの様子です.

基板は普通にプラスネジで外すことができます.せっかくなので,少し観察.
この写真の上部分が無線通信用のアンテナっぽい.

基板表面の全体像.コンパクトに収まっていていいですね.マイコンはAtmega168PAを使っているみたい.右側が電源用の昇圧回路かと予想.それ以外には目立った部品はなかったので,本当にシンプルに作られているようです.

さてさて,問題のスイッチを交換していきます.まずはもともとのスイッチを取り外しました.ハンダ吸い取り線とハンダを使って取り外します.最後までハンダを吸い取らないと外しにくいので頑張ってください.ハンダをすべて剥がせなかったときは,その上に少量のハンダを乗せます.そうすることで,半田の吸い取りがしやすくなります.

さいごに,どーんと新しいスイッチをはんだ付けすれば完了です!

無事,チャタリングの起こらないマウスへと変貌しました.

G700s

代替品

ネットでググった情報をもとに,オムロンのD2F-01Fを2個……はい,先ほどと同じです.同じようにやっていきましょう.

分解手順

これがG700sです.有線でも無線でも使えるゲーミングマウスということで,かゆいところに手が届く……気がしたのですが,いかんせんバッテリー持ちが極端に悪いので(1日持たない)完全に有線ゲーミングマウスとして使っています.キー数はこれが最適解だと思っています.親指で4キーを操作できるのは素晴らしい.

さて,分解していきます.裏側のカグスベールっぽいやつ(マウスソールと呼ぶらしいです)をすべて剥がし,ネジを5本外します.こちらは普通のプラスネジでした.

ケースを開いた様子です.M570とは打って変わって,基板がでかい!

マウスホイール部分の,写真で言う右端部分に,ピンのようなものがついています.これを力づくで抜くことで,マウスホイールを取り外すことができます.
また,写真の左側についていた金属部分も,ネジを外して取っておきます.小さなバネが2つついているのでなくさないように気をつけて.
それから,右端部分の黒いプラスチックパーツも,ネジを外して取っておきます.

これだけの部品が出てきました.

余談ですが,レーザー部分がモジュール化(?)されていました.ここだけ別開発して,いろんなマウスで使いまわせるようにしているのでしょうか?

さて,ひとつだけ問題があって,上の基板と下の基板は,2mmピッチの連結ピンヘッダではんだ付けされています.この14ピンを気合で取り外す必要がありました.見た目ほど難しくもなかったので写真は取ってませんでした.
外した基板の全体像です.スイッチは交換済みです.
マイコンはNXPでした.電源回路がめっちゃデカイです.このマウスはニッケル水素電池専用で,充電もできるようになっています.その影響ではないでしょうか.

元々使用されていたスイッチ

さて,左がM570,右がG700sのマウスに元々ついていたスイッチです.左は型番不明(そもそもオムロン製ではない気がする),右は系列品の中国製造品でした.

今回交換したスイッチは機械的耐性100万回,電気的耐性10万回となっていました.交換もなかなか面倒なので,頑張って2,3年位は持ってほしいなあと思います.

2017年は波乱の年

あけましておめでとうございます

2016年の目標を書こう書こうと思っていたら,もう2017年なの?
今年は目標を書きます.書きます(迫真).最後の学生生活1年間だもんね.

2017年の目標

就活

就活が迫ってきているけれど,こんなものはぱっぱと終わらせたい.この企業に入るためにはどうこう,面接の対策がどうこう,とかどうでもよいので,これからの人生をどう過ごしていきたいか,じっくり考えるほうが重要だと思う.自然体で受け入れてくれる会社だったら,しばらくはやっていけるでしょう(多分).

家にある部品で遊ぶ

FA機器.comとか,(自主規制)で拾ってきたものとか,秋月で衝動買いした物がたくさんあるので,これらで遊ぼうと思います.自由な時間があるのも今のうちだけだろうからね.

きれいにする

後1年で引っ越しということなので,家にある大量のグッズを整理したい.いらないものは売ればいいし,必要なものは記録してまとめておこう.
パソコンのデータも同じく.クラウドにあげてるものは良いだろうけど,それ以外のデータは整理しないと.できれば写真はタグ付けして保管したい.
あっパソコンのお掃除もしないといけないんだった…….

サーバーを整える

そういえばサーバーもそろそろバージョンをあげたい.あげたいと言うよりは,ArchLinuxにしたい.もうそろそろUbuntu12.04LTSのサポートが切れるので割と急ぎの課題だ.
最近流行りのnginxにしてみたいし,そういえばVPNで接続できるようにもしたい.家の中でサーバーにつなげるのが面倒だからプロキシも立てておきたい.
できれば間にハブを挟んで,通信を監視できるようにしたい.RaspberryPiでもいいから,手を付けてみたいなあ.

遊びに行く

学生のうちにいっぱい遊んでおきたい.徹夜とかそろそろ(体力的に)厳しいので,遊べるのは今のうちという感じがしている.

マウス

ハーフのライバルも増えそうなので,ぼくもがんばります(白目)

研究室に配属される

ヤバイ。単位ヤバイ。まじでヤバイよ、マジヤバイ。
単位ヤバイ。
まず少ない。もう少ないなんてもんじゃない。超少ない。
少ないとかっても
「今年届いた年賀状ぶんくらい?」
とか、もう、そういうレベルじゃない。
何しろ無限小。スゲェ!なんか単位とか無いの。何単位とか何科目とかを超越してる。無限小だし超少ない。
しかも堕落してるらしい。ヤバイよ、堕落だよ。
だって普通は学生とか堕落しないじゃん。だって自分の取った単位がだんだん減ってったら困るじゃん。進級が超遠いとか困るっしょ。
不可が伸びて、一年のときは40単位だったのに、三年のときは一年間で60単位とか泣くっしょ。
だから進級しない。話のわかるヤツだ。
けど堕落はヤバイ。そんなの気にしない。堕落しまくり。最も出席した授業がどれとかよくわかんないくらい少ない。ヤバすぎ。
堕落っていたけど、もしかしたら向上かもしんない。でも向上って事にすると
「じゃあ、進級する方法ってナニよ?」
って事になるし、それは誰もわからない。ヤバイ。誰にも分からないなんて怖すぎる。
あと超高い。約100万。生活費を入れると200万。ヤバイ。高すぎ。アルバイトする暇もなく死ぬ。怖い。
それに超何も無い。超スカスカ。それに超ぐーたら。留年とか平気で出てくる。留年て。小学生でもならねぇよ、最近。
なんつっても進級は馬力が必要。無限とかやってられないし。
うちらなんて単位とかたかだか積分計算できただけで上手く扱えないけど進級したり、fと置いてみたり、演算子使ったりするのに、
留年は全然平気。堕落を堕落のまま過ごしてる。凄い。ヤバイ。
とにかく貴様ら、単位のヤバさをもっと知るべきだと思います。
そんなヤバイ単位に立ち向かっていったFNDとか超偉い。もっとがんばれ。超がんばれ。

頑張って進級して研究室に配属されたいですねえ.でないと就活もなにも始まらないし,とても困る.

今年も一年間頑張っていこうと思います.

2016年に買ってよかったもの

はじめに

2016年は色々と冒険をした年になりました.色んな所に行ったり,いろんなものを買ったり,美味しいものを食べたりしていた一年じゃないかと思う.
そんな一年を締めくくる記事として,「これは買うべき」もしくは「これにお金を払うべき」と思うものをまとめることにする.

食べ物

温州みかんのかき氷

セブンイレブン限定のかき氷.みかんの実がいっぱい乗っているだけでなく,かき氷の中にもみかんが入っていてポイントが高い.そんなに高くもないので,夏になったら食べまくろう.

買い物

ステッカー

ステッカーはとても良くて,界隈の人と話をはじめやすくなった.そうでなくても,ガルパンの「ボコ」は単純に可愛いキャラクターであるので,そういったところから話が始まることもあったと思う.

別の効果としては,Windowsキーの上にArchLinuxのシールを貼ったため,Superキーが押しやすくなった.i3-wmのmodキーをSuperに割り当てている自分からすると,非常に重要.

A3プリンター

Canon インクジェットプリンター PIXUS iP8730

CDレーベル印刷もできる,A3プリンター.画質はさすがcanonという感じでとても良かった.
僕は,別のA4モノクロレーザー複合機を持っているので,書類・コピーと,カラー印刷という感じで住み分けができているのでちょうどいい.コミケに出展する人はブースに大きなポスターを用意したほうが良いと思うのだけれど,業者に発注するほどでもないと思うのであればこのプリンターがオススメ.A4とA3では全然違った.
唯一の難点は,棚の上にプリンターを置いて稼働させているので,印刷の動きに合わせて棚が左右に揺れること.棚の補強をしろって話ですよね.

駿河屋の福袋

レア物が置いてあることで話題の駿河屋で,試しに「中古福袋 レンタルアップ 邦楽シングルCD 40枚セット」というものを買ってみた結果が上の画像の通り.なんと280円で40枚もの邦楽CDが入っていた.
どういう層にオススメかというと,「音楽ライブラリを肥やしたいけど特にどういう曲が良いかわからない」,「自分の知らない曲を増やしたい」と思っている人たち.ジャンクの福袋だと,よりどりみどりの品が破格の値段で売られているので,きっとその中に好きな曲が入っているはず(という甘い考えを持って買ったが,実際好きな曲がいくつもあった).
良さげな福袋はあっというまに売り切れるので,1月第1週は駿河屋公式サイトのチェックが欠かせない.

Binary Hacks

Binary Hacks ―ハッカー秘伝のテクニック100選

低レイヤについて勉強しようと思って,とりあえず買ってみた本.タイトルの通り,細々とした話題について100の項目についてまとめられている.tips的な感じの内容もあるので,とりあえず読んでるだけでもすごく楽しい.
十分に理解していない内容が結構多いので,来年への持ち越し課題かなあ.

契約してよかったこと

契約と言うには少し違う気もするが,便利な有料サービスとか.

DMM月額CDレンタル

DMM.com 月額CDレンタル 無料体験1ヶ月キャンペーン中!

月額1980円で無制限にCDやDVDを借りられるサービス.無制限とは言っても事実上の制限があるが,配達が遅れなければ3日に2枚借りられる.およそ1枚100円でCDもDVDも借りられるし,しかも郵便ポストにいれるだけで返却ができる,という便利サービスだ.このおかげでCDのライブラリがかなり増えてほくほくしている.
また,アニメを見るときにはdアニメストアとAmazonPrimeビデオを併用しているが,どちらでも見られない作品があったりする.そういう時にDMMでDVDをレンタルすることで,大半のアニメが見られる環境が整った.違法DL,ダメ!

そういえば,たまこラブストーリーもDMMで借りた.良すぎたのでBlu-ray買ってしまったけど.

subsonic

subsonic

subsonicはストリーミング配信ができるサーバーサイドのアプリケーションだ.サーバーにこいつを仕込んでおき,音楽や動画を入れておくだけでどこからでも楽しむことができる.
音楽を聞くだけであれば無料なのだが,動画を見たりDLNAを使ったりするときには有料のsubconic premiumになる必要がある.結構お世話になっているソフトなので,思い切って課金することにした.月額$1なので良心的.
詳しくはまた別の記事を書こうと計画中.

行ってよかったところ

買い物ではないけれど,行って楽しかったところ.

京都鉄道博物館

京都に新しくオープンした鉄道博物館.
幼い頃から親しんでいたSLに久しぶりに乗り楽しかった.それだけでなく,鉄道のあんなところやこんなところまで,舐めるように見ることができるため本当にオススメ.生まれて初めて架線を触ったし,解説も充実している.次は「おしゃべりな」鉄ヲタと機械科を連れていきたい.

さいごに

みなさんよいお年を.来年もよろしくお願いします.

タイル型WMで快適な環境を構築する

はじめに

この記事は東京理科大学 Advent Calendar 2016 - Qiitaの6日目の記事です.昨日はfujitoraさんのNew Relicでめっちゃ簡単にRailsアプリケーションの監視をするでした.明日の枠はまだ埋まっていないので,この記事を見た誰かが書いてくれると嬉しいなあ.

デスクトップ環境とは

さて皆さん,快適なデスクトップ環境をお過ごしでしょうか?

唐突ですが,このスクリーンショットは半年前の僕のパソコンの様子です.

この頃はCinnamonというウインドウマネージャを使っていました.これは「スタック型」と呼ばれるウインドウマネージャです.Windowsでも同じような雰囲気だと思いますが,いくつものウインドウがあり,マウスで自在に動かせるタイプの環境です.
僕は今までスタック型の環境しか使ってこなかったわけですが,あるときふと気付きました.
「新しいウインドウを開いた時,いつも最大化している!!」

そして,知人の紹介で「タイル型」のウインドウマネージャがあるということを知り,ウインドウマネージャを変えることにしました.

タイル型を使う

今使っている環境はi3です.
こんな感じに,モニタをn分割していい感じのレイアウトで表示してくれます.


ブラウザでおなじみの「タブ」のようにウインドウを切り替えることもできます.

画面を分割した中に,タブを作ることもできます.

またi3には”floating mode”なるモードが存在し,GIMPなどスタック型のウインドウマネージャ用に作られたアプリケーションも楽々使うことができます.これが,タイル型の中でもi3をオススメしたい一番の理由です.

i3の設定

ノートパソコンで運用する上で,必要と思われる設定をまとめておきます.

ランチャー

今までGNOMEのランチャー(スタートメニュー?)を使っていたため,i3標準のdmenuは使いづらく思いました.
freedesktop.org準拠のデスクトップファイルを参照できるようにしたい,ということで,僕はrofiを使っています.rofiはコマンドライン引数に色々と書くことで挙動や見た目を変更させることができます.
i3の設定ファイルに次にように設定しました.

1
bindsym $mod+semicolon exec "rofi -show drun -font 'snap 10' -fg '#505050' -bg '#000000' -hlfg '#ffb964' -hlbg '#000000' -o 85 -kb-cancel 'Escape,Control+g' -kb-mode-next 'Control+i'"

Emacsのhelmと対応させて”S-;”で起動,”C-g”で閉じられるように設定しています.

デスクトップファイルについてはfreedesktop.org 規格のデスクトップファイルについてのメモ - Λlisue’s blogを参照しました.

電源管理

ロック・サスペンド・シャットダウンあたりはぱぱっとできるように設定をします.

ロック

i3の場合はi3lockを使うことでお手軽にロックがかけられます.

1
2
3
4
5
6
7
8
9
10
11
12
set $Locker i3lock -i ~/Pictures/Wallpaper/kishimen.png && sleep 1
set $mode_system System (l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (Shift+s) shutdown
mode "$mode_system" {
bindsym l exec --no-startup-id $Locker, mode "default"
bindsym e exec --no-startup-id i3-msg exit, mode "default"
bindsym s exec --no-startup-id $Locker && systemctl suspend, mode "default"
bindsym h exec --no-startup-id $Locker && systemctl hibernate, mode "default"
bindsym r exec --no-startup-id systemctl reboot, mode "default"
bindsym Shift+s exec --no-startup-id systemctl poweroff -i, mode "default"
bindsym Return mode "default"
bindsym Escape mode "default"
}

PrintScreen

スクリーンショットも撮りたいので設定を行います.
僕はmaimを使いました.なかなかよいアプリケーションで,画面の一部を切り取ってキャプチャを行うことができます(別途slopが必要).

1
2
3
bindsym Print exec "maim ~/Pictures/screenshot/$(date +%F-%T).png"
bindsym $mod+Print exec "maim -i $(xdotool getactivewindow) ~/Pictures/screenshot/$(date +%F-%T).png"
bindsym Shift+Print exec "maim --select ~/Pictures/screenshot/$(date +%F-%T).png"

その他のキーボード・ショートカット

音量・ミュート・明るさなどを特殊キーから調整できるようにしました.
この際,キーの名前を取得する際にはxevコマンドを利用して調べました.
参考:特別なキーボードキー - ArchWiki

1
2
3
4
5
6
bindsym XF86MonBrightnessDown exec "xbacklight -dec 5"
bindsym XF86MonBrightnessUp exec "xbacklight -inc 5"
bindsym XF86AudioMute exec "amixer -q -D pulse set Master toggle"
bindsym XF86AudioLowerVolume exec "amixer -c 0 -D pulse sset Master 1%- unmute"
bindsym XF86AudioRaiseVolume exec "amixer -c 0 -D pulse sset Master 1%+ unmute"
bindsym XF86AudioMicMute exec "amixer -c 0 -D pulse set Capture toggle"

インターネットにつなぐ

この辺からただの覚書です.
コンピュータの起動時にネットワークに接続できるようにします.

1
exec_always --no-startup-id nm-applet

音を出せるようにする

1
exec_always --no-startup-id pulseaudio --start

背景を設定する

1
exec_always --no-startup-id feh --bg-scale ~/Pictures/Wallpaper/1366_768_20091126090927427353.jpg

i3の基本操作(大嘘)

i3の初期設定についてはデフォルトの設定ファイルを見てもらうとして,この記事では僕オリジナルの設定を自慢したいと思います.

ワークスペースの切り替え

ワークスペースの切り替えは”S-[1234567890]”がデフォルトになっているようですが,正直狙った数字キーを押すのが面倒なので,思い切って変更しています.
“S-[asdfuiop]”とすることでいい感じに使っています.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
set $WSa 1:a
set $WSs 2:s
set $WSd 3:d
set $WSf 4:f
set $WSu 5:u
set $WSi 6:i
set $WSo 7:o
set $WSp 8:p
bindsym $mod+a workspace $WSa
bindsym $mod+s workspace $WSs
bindsym $mod+d workspace $WSd
bindsym $mod+f workspace $WSf
bindsym $mod+u workspace $WSu
bindsym $mod+i workspace $WSi
bindsym $mod+o workspace $WSo
bindsym $mod+p workspace $WSp
bindsym $mod+Shift+a move container to workspace $WSa
bindsym $mod+Shift+s move container to workspace $WSs
bindsym $mod+Shift+d move container to workspace $WSd
bindsym $mod+Shift+f move container to workspace $WSf
bindsym $mod+Shift+u move container to workspace $WSu
bindsym $mod+Shift+i move container to workspace $WSi
bindsym $mod+Shift+o move container to workspace $WSo
bindsym $mod+Shift+p move container to workspace $WSp

もう一つポイントがあって,ワークスペース名を”数字:名前”にしています.
次の設定を書くことで,i3bar上に並ぶワークスペースが降順にソートされるようになります.

1
2
3
4
5
bar {
status_command i3status
font pango:DejaVu Sans 10px
strip_workspace_numbers yes
}

ウインドウの切り替え

複数のウインドウを表示している時,その間の移動は”S-[jkl;]”がデフォルトになっています.しかし,vimキーバインドと一つずれていてとても気持ちが悪かったので,”S-[hjkl]”で移動できるように変更しました.

1
2
3
4
5
6
7
8
bindsym $mod+h focus left
bindsym $mod+j focus down
bindsym $mod+k focus up
bindsym $mod+l focus right
bindsym $mod+Shift+h move left
bindsym $mod+Shift+j move down
bindsym $mod+Shift+k move up
bindsym $mod+Shift+l move right

最後に

ここまで長々と設定を書いてきましたが,僕の設定ファイルをgithubに公開しているので貼り付けておきます.
taniho0707/dotfiles - gihub

また,i3の設定で参考にしたサイトです.

2016年度の大会が終わり平凡な日々を取り戻した話

大会

今年の大会シーズンが終わりました.各地区大会に行きまくっていたため,本当にあっという間でした.
これでようやく平凡な日々を過ごせそうです.

全日本大会では無事決勝進出(これにより部内ハーフ人権の確保)
残念ながら決勝で最短走行をすることはできませんでしたが,これは来年の課題であるということにします.来年はセンサ回路をいい感じに作り直したいなあと思っています.
(他にも色々構想はありますが,はてどこまでできることやら)

さてこれまでのマウスの成長はというと,

斜めをしだした

斜め直進もなんのその

徹夜で調整をした

斜めが早くなった

大会会場でも走っ……りたかった

なんか「もしかしたら決勝でも走るかも……!?」と思えてしまう走りを見せてくれてはいましたが,残念ながら叶わず.

大会会場にて

全日本大会の予選日午前中,突然マウスが走らなくなりました.いつものセンサ周りのハンダ不良かなあと思って温め直すも全く治らず,途方に暮れていまいた.
マウスを壊しても良いという勢いで調査を始めると,なんとセンサ用のLEDが壊れていることが判明.奇跡的にnse先輩が全く同じLEDを持って来られており(なぜあんなマイナーなLEDを持っていたのか),無事ハードは復旧.
センサ値が変わってしまったので予選で満足に走ることはできませんでした.
それでも,決勝にありつけたのは先輩や手伝ってくれた後輩,これまで応援してくれたみんなのおかげと思っています.
来年も共に頑張っていきましょう.

こちらが壊れたLED

来年度

来年度はもちろんハーフをやります.今年困りまくったセンサを突き詰めたいと思っています.クラシックでも通用するくらいの精度の良いセンサにしたいなあ.
もしかしたら他の競技もやるかもしれませんが,それは気が向いたらということで.
そういえばデレステをしないと.自動演奏機,なんとしてでも完成させようとしています.
マウスの頭脳も賢くしたい.そのためにもシミュレータを完成させます.

あれっ平凡な日々がもう終わってしまった???

滑らかな加速がしたい(三角関数編)

はじめに

みなさん,台形加速していますか?
僕もしています.


(初めてマウスを作り始めたときの様子)

綺麗な目標速度ですね.
しかし先日「このグラフはありえないよねー」とのツッコミを頂き,滑らかな加減速がしたいなあと思い始めました.
というのも,速度の変化時に微分不可能な部分があるため,追従が悪くなるということだそうです.

今回は,三角関数を用いた加減速についてまとめようとおもいます.

条件

僕の場合,走行するときには次のパラメータを用意します.

  • 初速度 $ v_s $
  • 最高速度 $ v_{max} $
  • 終速度 $ v_e $
  • 最高加速度の絶対値 $ a_{max} $
  • 到達目標距離 $ x_{all} $

今回の加減速では三角関数を使うといいましたが,次のような加速・減速になってほしいなあと思いました.

加速のようす(式 $ f_1 $ )

この式の基本形には $ \cos $ を使っています.

$$
\begin{eqnarray}
f_1 &=& A \left( 1-\cos\left( \alpha t \right) \right) +v_s \\
&=& \dfrac{\Delta v}{2}\left( 1-\cos\dfrac{2a_{max}}{\Delta v}t \right) +v_s
\end{eqnarray}
$$

ただし, $\Delta v = v_{max} - v_s$ としました.

減速のようす(式 $ f_2 $)

こちらも同様に

$$
\begin{eqnarray}
f_1 &=& A \left( 1+\cos \alpha \left(t-t_1-t_2\right) \right) +v_e \\
&=& \dfrac{\Delta v^{\prime}}{2}\left( 1-\cos\dfrac{2a_{max}}{\Delta v^{\prime}}\left(t-t_1 \right) \right) +v_e
\end{eqnarray}
$$

ただし, $\Delta v^{\prime} = v_{max} - v_e$ としました.

これらの加減速区間と等速区間を組み合わせて,次のような速度変化にすることが理想形です.

しかし,目標距離が短くて最高速度に達しない場合を考慮する必要があります.
この場合は次のような速度変化になります.

というわけで,
最高速度に達するかどうかの判定をしてから,目標とする加速距離と加速時間・減速距離と減速時間を導出していきます.

ひたすら計算

加速区間と加速時間

与えられたパラメータから,加速に必要な距離と時間を求めます.
ただし,次のように変数を設定します.

  • 加速区間(加速に必要な距離) $x_1$
  • 加速時間(加速に必要な時間) $t_1$
  • 等速区間(等速運動し続ける距離) $x_2$
  • 等速時間(等速運動し続ける時間) $t_2$
  • 減速区間(減速に必要な距離) $x_3$
  • 減速時間(減速に必要な時間) $t_3$

加速時間

これは簡単で,位相が $\pi$ 動く時間であるので,
$$
\begin{eqnarray}
\dfrac{2 a_{max}}{\Delta v} t_1 &=& \pi \\
t_1 &=& \dfrac{\pi \Delta v}{2 a_{max}}
\end{eqnarray}
$$
として導出できました.

加速区間

では,加速に必要な距離を求めます.
先程導出した $t_1$ までの時間で積分をすれば距離が求まります.

$$
\begin{eqnarray}
x_1 &=& \int^{t_1}_0 f_1 dt \\
&=& \left( \dfrac{\Delta v}{2} + v_s \right) \dfrac{\Delta v}{2 a_{max}} \pi \\
&=& \dfrac{v_{max}^2 - v_s^2}{4 a_{max}} \pi
\end{eqnarray}
$$

減速区間と減速時間

同様に,減速に必要な距離と時間を求めます.

減速時間

$$
\begin{eqnarray}
\dfrac{2 a_{max}}{\Delta v^{\prime}} t_3 &=& \pi \\
t_3 &=& \dfrac{\pi \Delta v^{\prime}}{2 a_{max}}
\end{eqnarray}
$$
として導出できました.

減速区間

では,減速に必要な距離も同様に.
$$
\begin{eqnarray}
x_3 &=& \int^{t_1+t_2+t_3}_{t_1+t_2} f_2 dt \\
&=& \left( \dfrac{\Delta v^{\prime}}{2} + v_e \right) \dfrac{\Delta v^{\prime}}{2 a_{max}} \pi \\
&=& \dfrac{v_{max}^2 - v_e^2}{4 a_{max}} \pi
\end{eqnarray}
$$

最高速度に達するかどうかの判定

ここで,最高速度に達するかどうかの判定を行います.
次の式が満たされる場合は最高速度に達する,そうでない場合は達しないということになります.
$$
\begin{eqnarray}
x_{all} &>& x_{1} + x_{3} \\
&>& \dfrac{\pi}{2 a_{max}} \left( v_{max}^2 - \dfrac{v_s^2 + v_e^2}{2} \right)
\end{eqnarray}
$$

最高速度の設定

先程の式が満たされなかった場合,つまり最高速度の再設定が必要な場合は,次の式から新しい最高速度を求めます.
$$
\begin{eqnarray}
x_{all} &=& x_{1} + x_{3} \\
&=& \dfrac{\pi}{2 a_{max}} \left( v_{max}^2 - \dfrac{v_s^2 + v_e^2}{2} \right) \\
v_{max}^2 &=& 2 a_{max} \dfrac{l}{\pi} + \dfrac{v_s^2 + v_e ^2}{2} \\
v_{max} &=& \sqrt{ 2 a_{max} \dfrac{l}{\pi} + \dfrac{v_s^2 + v_e ^2}{2} }
\end{eqnarray}
$$

おわり

きれいな加速ができるようになりました.

第31回全日本学生マイクロマウス大会で徹夜調整をした話

大会前日

いつぞやの記事では,学生大会でシードを取ると言っていましたが,そんな事を言っている場合ではないほど探索ができずに苦しんでいました.
そこで,先輩のご厚意に甘えて特別に徹夜で調整させていただく機会をもらいました.

探索の安定性を向上させ,きりが良くなったタイミングで大回りパスでの最短走行を実装.
うむ夫。くんに怒られたので,最短時には必ず壁切れを読むようにしました.
徹夜の結果,なんとか走るようになり,清々しい気分で朝の電車に飛び込んだ……ような気がします.正直フラフラで記憶がありません.

今年の大会は,(まあ毎大会恒例となってしまいましたが,)多くの部員が参加し,大会がより盛り上がったのではないかと思います.
前日準備の担当もスムーズに決まり,積極的に運営に協力していく風潮はなくさないようにしたいと思いました.

大会当日

大会開場はとてもきれいな学校で,そこに通う学生がとても羨ましかったです.

午前中のクラシックでは,「赤子」が圧倒的な実力を見せつけて数台のDCマウスを撃沈していました.すごい.全日本でも期待しています.
しかしそれ以外のフレッシュマンの人たちも本当に頑張って欲しいと思っています.ライバルは多いほうが良いですからね.

で,肝心の自分の走行はというと,

ということで,往復探索+オートスタートでの小回り最短が成功
しかし,せっかく徹夜で実装した大回り最短が失敗してしまったのが大変悔しく,次回の大きな課題となりました.

帰り

頭の悪い集団が集まりだし,なにやらマウス集合写真を撮影していました.その最中,

「組長!! 来い!!」

とかいわれて無理やり参加させられることに

僕がLEDをチカチカさせると,他の人たちも次々と電源を入れ始めました.クリスマスみたいでとてもきれいでした(小並感).
赤・橙・緑・青の組み合わせ格好良いですね.次回作では真似てみたいなあと思ったり.

その後はおっさn女子中学生と一緒にごはんに行き,お互いの話をしたりしました.ぜひMiceにお越しください!

次回

さて,次は週末の北信越大会ですが,頑張ってシードを取りたいと思っています.
そのために必要なことは,

  • 斜めでの最短走行を成功させる
  • 探索でこけない

この2つを達成できるように,いろいろと細かな修正をいれていこうかと考えています.
シード取るぞ!

組み込みでもC++/C++11を始めよう

はじめに

この記事は,悪い人にそそのかされてC++を初めてしまった先輩方のために書いています.
C++,C++11,STLの機能の中から,お手軽に使えて便利なものをピックアップして紹介しようと思います.
少しでも興味がある人がC++を始めてもらえれば僕としては嬉しいです.

過去記事に似たようなエントリがあるので,こちらも見てみてください.
e2studioを用いてGCC-C-で開発する

お決まり文句ですが,この記事の内容には誤りがある可能性があります.その際ご指摘をいただければ幸いです.
また,僕は割と適当にC++の勉強をしているので,そのあたりお気をつけください.この記事ではほんの一部の機能紹介にとどめているため,よく研究してから使われることをオススメします.

STL

STLとはStandard Template Libraryの略で,C++で用意されている標準ライブラリのことです.とても便利なライブラリなのでふんだんに使っていきたいですね.
ただし,コードサイズが大きくなるため組み込みで使用する際はよく考えてください.僕のマウスはSTL使いまくっていますが今の所問題なく動いています.

ではいきましょう.

std::pair

例えば座標管理を考えるときに,次のような変数を用意すると思います.

1
2
int current_x = 0;
int current_y = 1;

しかし,迷路座標はxとyはペアで考えるべきです.
というわけで,STLのpairを使って定義しましょう.

1
2
3
std::pair<int, int> current_pos(0, 1);
current_pos.first; //0
current_pos.second; //1

std::array

どんなプログラムでも,配列変数をたくさん使っていると思います.次のコードはよくあるミス.

1
2
int arr[16];
arr[16] = 1; //範囲外アクセス

というわけで,ここでもSTLを使っていきましょう.

1
2
std::array<int, 16> arr;
arr.at(16) = 1; //例外が発生(例外無効化なら何も起こらない)

std::vector

きました,可変長配列です!
サイズの変えられる配列を使えます.

1
2
3
4
std::vector<int> vec = {1, 2, 3};
vec.at(2); //3
vec.push_back(4); //vec = {1, 2, 3, 4}
vec.size(); //4

少し話がずれますが,std::arraystd::vectorなどのすべての要素にアクセスしたい場合,次のような方法があります.

1
2
3
4
5
6
for(int x : vec){
std::cout << x << std::endl; //すべての要素が標準出力に出される
}
for(int& it : vec){
it *= 2; //すべての要素が2倍される
}

std::queue

キューを自前で作っている人や,歩数マップ生成ルーチンとキューが一体型になっている人がいらっしゃるようですが,ここでもSTLを使いましょう.

1
2
3
4
5
6
7
8
std::queue<int> que;
que.push(1);
que.push(2);
que.front(); //1
que.pop();
que.front(); //2
que.pop();
que.empty(); //true

std::bitset

頑張ってビット演算をしていろいろなデータを格納しているかもしれませんが,ここでもSTLを使います.

1
2
3
4
5
6
std::bitset<8> bs; //0b0000
bs.set(); //0b1111
bs.reset(1); //0b1101
bs.test(0); //true
bs.test(1); //false
bs.to_string(); //"1101"

C++

auto

ちょっと使いたいだけのときに一々型を調べるの,面倒じゃないですか? そんなときには楽をしちゃいましょう.

1
2
3
4
5
6
for(auto x : vec){
std::cout << x << std::endl; //すべての要素が標準出力に出される
}
for(auto& it : vec){
it *= 2; //すべての要素が2倍される
}

enum class

使い勝手の良い列挙型です.

1
2
3
4
5
6
7
8
9
10
enum class N : uint8_t{
N1,
N2 = 100,
N3,
N4,
};

N1; // 存在しない
N::N1; // 0
N::N4; // 102

cast

キャストにも幾つか種類がありますが,一番良く使うのはこのキャストです.できるだけ明示するようにしましょう.

1
2
3
4
int a = 10;
float b = static_cast<float>(a) * 2.0f;

uint8_t c = static_cast<uint8_t>(N::N1);

参照渡し

C言語でアドレスを渡す際にはポインタしかありませんでした.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct foo{
int x;
int y;
};
void hoge(int *a, struct foo* b){
*a = b->x;
return;
}
int main(){
int a = 10;
struct foo = {1, 2};
hoge(&a, &foo);
return 0;
}

正直いろいろと面倒くさい,そんなときはC++の参照渡しです.constも付けられます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct foo{
int x;
int y;
};
void hoge(int& a, const struct foo& b){
a = b.x;
return;
}
int main(){
int a = 10;
struct foo = {1, 2};
hoge(a, foo);
return 0;
}

constexpr

配列のサイズを指定するには,定数かマクロを使うしかありませんでした.

1
2
#define SIZE 10
int x[SIZE];

このサイズがコンパイル時に確定する場合(ex.他のパラメータから配列サイズが決まる場合),どうすればいいでしょうか?
C++11ならconstexprを使いましょう.

1
2
3
4
constexpr int size1 = 10;
constexpr int size2 = size1 + 5;
int x[size1];
int y[size2];

おわり

第一弾おわり!
(つづくの!?)

第26回マイクロマウス九州地区大会で再現性の高さを見せつけてきた

九州大会

どうしてこんな遠いところに来てしまったんだろうか……(遠い目)

今年2回めの飛行機で,初めての九州上陸です.
航空会社はSTAR FLYERを使いましたが,国内線なのにモニタがついていたりしていてとてもすごかったです(小並感).

屋台

着日の夜には頭の悪い人たちと天神の屋台に行きました.

ずーーーーーっと歩き続けた後,とりあえず入った照ちゃんが大当たりで最高でした.
おでんもうまい,肉がうまい,酒がうまい,ラーメンがうまい.

僕はアジの唐揚げ(800円)をしゃぶり尽くして満面の笑みを浮かべていたと思います.

戦績

さて,前の記事で目標を書いていたような気がします.
前回の東北大会では照明の影響が大きく,まともに走ることができませんでした.

今回の九州大会では,どうにかゴールをすることができました!
……が,なんと帰り探索でクラッシュ.5回連続で同じところで止まってしまい,最短走行をすることができませんでした.

反省点は,

  • スラロームの調整が甘い
  • 探索でコケた時に迷路データが消えるのはダメ
  • 前壁補正入れよう
  • 壁切れ補正入れよう

要するに準備不足なので,今週もがんばります.

進捗

出走が終わり,しょげていた時にぽちぽちとコードを書いていました.

おかげで迷路データのMRAMへの保存ができるようになりました!
これで,仮に探索でコケてもそれまでのデータが消えることはなくなりました!!

次の中部大会では,

  • 走行の安定
  • モード機能の実装

あたりを強化したいと思っています.

僕の考えた最強のパラメータ格納法

パラメータ格納

マイクロマウスではいろいろなパラメータ,調整項目があります.きれいに走るためには,たくさんのパラメータを真心込めて調整してあげる必要があります.ほんとうにしんどい.

さて,乱雑なコードを書いているといろんなよくない問題が発生します.
例えば,

  • 同じパラメータが複数ヶ所で定義されている
  • 使われていないパラメータが乱立している
  • 変更したいパラメータがどこに書かれているか見つからない

……などなど.ちなみに全て実話です

というわけで,パラメータの格納方法はこだわったほうがいいというのがこの記事で言いたいことです.

先駆者

某先輩がポインタまみれのスラロームパラメータ保存を紹介していました.全容を把握するのには苦労しますが,すべてのパラメータを#defineするよりも良い方法だと思います.
C言語を頑張りたい人はこの記事を読んで,ポインタとは何者なのか理解しちゃいましょう!

ぼくのかんがえた(以下略

では,僕の考えた最強のパラメータ格納法をででんと紹介します.

あ,予め言っておきますがC++11とSTLを使いまくっているので,用法用量にはお気をつけください.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
namespace slalomparams{
enum class RunType : uint8_t {
SLALOM90SML_RIGHT,
SLALOM90SML_LEFT,
SLALOM90_RIGHT,
SLALOM90_LEFT,
SLALOM180_RIGHT,
SLALOM180_LEFT,
SLALOM45IN_RIGHT,
SLALOM45IN_LEFT,
SLALOM45OUT_RIGHT,
SLALOM45OUT_LEFT,
SLALOM135IN_RIGHT,
SLALOM135IN_LEFT,
SLALOM135OUT_RIGHT,
SLALOM135OUT_LEFT,
SLALOM90OBL_RIGHT,
SLALOM90OBL_LEFT,
TRAPACCEL,
PIVOTTURN,
};

struct pack{
float d_before;
float d_after;
float acc_rad;
float deg;
float const_deg;
float in_vel;
float out_vel;
float min_vel;
float acc_lin;
};
typedef struct pack pack_t;
}

array< map<float,pack_t>* , 16> slalomparams::getParams(){
static map<float, pack_t> SLALOM90SML_RIGHT = {
// { vel, {d_bef, d_aft, a_rad, deg, cnsdeg, in_vel, out_vel, min_vel, acc_lin}},
{0.25, {0.010, 0.012, 9000,95.5, 30, 0.25, 0.25, 0.25, 0.0}},
};
static map<float, pack_t> SLALOM90SML_LEFT = {
// { vel, {d_bef, d_aft, a_rad, deg, cnsdeg, in_vel, out_vel, min_vel, acc_lin}},
{0.25, {0.010, 0.012, 9000,95.5, 30, 0.25, 0.25, 0.25, 0.0}},
};
static map<float, pack_t> SLALOM90_RIGHT = {};
static map<float, pack_t> SLALOM90_LEFT = {};
static map<float, pack_t> SLALOM180_RIGHT = {};
static map<float, pack_t> SLALOM180_LEFT = {};
static map<float, pack_t> SLALOM45IN_RIGHT = {};
static map<float, pack_t> SLALOM45IN_LEFT = {};
static map<float, pack_t> SLALOM45OUT_RIGHT = {};
static map<float, pack_t> SLALOM45OUT_LEFT = {};
static map<float, pack_t> SLALOM135IN_RIGHT = {};
static map<float, pack_t> SLALOM135IN_LEFT = {};
static map<float, pack_t> SLALOM135OUT_RIGHT = {};
static map<float, pack_t> SLALOM135OUT_LEFT = {};
static map<float, pack_t> SLALOM90OBL_RIGHT = {};
static map<float, pack_t> SLALOM90OBL_LEFT = {};

static array< map<float,pack_t>* , 16> params = {
&SLALOM90SML_RIGHT,
&SLALOM90SML_LEFT,
&SLALOM90_RIGHT,
&SLALOM90_LEFT,
&SLALOM180_RIGHT,
&SLALOM180_LEFT,
&SLALOM45IN_RIGHT,
&SLALOM45IN_LEFT,
&SLALOM45OUT_RIGHT,
&SLALOM45OUT_LEFT,
&SLALOM135IN_RIGHT,
&SLALOM135IN_LEFT,
&SLALOM135OUT_RIGHT,
&SLALOM135OUT_LEFT,
&SLALOM90OBL_RIGHT,
&SLALOM90OBL_LEFT,
};

return params;
}

struct pack がスラロームの1パラメータを格納した構造体です.
スラロームには,代表的なターンが16種類あるので,
1種類のスラロームパラメータをまとめたもの(A) へのポインタを,サイズ16の配列(B) にしています
(A)map<float, pack_t>で,(B)array< map<float, pack_t>*, 16>です.

(A)にstd::mapを使うことで,パラメータの存在確認を可能にしました.
スラロームのターン速を引数に取ることで,欲しいパラメータを参照することができます.

具体的には,次のようなコードでターンパラメータを取得・参照できます.

1
2
3
4
5
6
using namespace slalomparams;
auto it = getParams().at(static_cast<uint16_t>(RunType::SLALOM90SML_RIGHT))->find(0.25f);
if(it == getParams().at(static_cast<uint16_t>(RunType::SLALOM90SML_RIGHT))->end()) printf("Undefined parameter");

it->second.deg; //95.5
it->second.d_before; //0.01

ちなみに,諸事情あってconstにはしていませんが,問題なくconstをつけられると思います.