SyntaxHighlighter

2016年11月27日日曜日

ポータブック(XMC10)の初期セットアップ

2万円台に値下がりしているポータブック XMC10を思わず購入してしまった。

以前ヨドバシカメラで触っていて、気になっていたマシンであり、
値段を見て諦めたのが、この値段になるとは思っていなかった。

きちんと設定すれば騒がれているほど使い勝手も悪くないマシンであり、
個人的に初のSSD & 小型 & ファンレスマシンなので期待している。

もっとも、使うならきっちりチューンしてから使いたいタイプの人間なので、
休日丸一日使ってセットアップしたのでその記録をとっておく。

噂によれば、クリーンインストールすることで安定するらしい。
そもそも、空き容量の都合でAnniversaryUpdateが素では適用できないらしい
(USBメモリ等を挿せば行けるらしいが)ので、だったら、AnniversaryUpdate版を
クリーンインストールしたほうが何かと安心だろうと考えた。

SDカードスロットは、他の人のおすすめどおり
サンワサプライ Mac用microSDカードアダプタ ADR-MMICRO
を購入。たしかにピッタリのサイズである。

*セットアップ

初期設定
 →特に何もなし。Windows10の標準的なセットアップ。
  クリーンインストールするので適当にセットアップ。

  セットアップ終了後、電源設定を変更し、
  スリープしないようにすることをおすすめする。
  というのも、時間かかる作業が多い上、BIOSアップデート時に
  スリープしようものなら大惨事になりかねない。

  下手に不安定になられても困るので、自分のときは
  クリーンインストールまではWi-Fiには接続しないで行った。

回復ドライブの作成
 →回復ドライブはとりあえず作成しておかないと、後々失敗した時のダメージが大きい。
  SDカードは使えない(ウィザードで出てこない)ようなので、
  USBメモリか、USBカードリーダーを用意しておくこと。
  (しかし、なぜか手持ちのSDXCリーダは相性が悪いらしく認識してくれない)
  ひたすら放っておき、概ね3時間ほどかかった。

ドライババックアップ
 →先人に従い、C:\Windows\System32\DriverStoreをUSBメモリにバックアップする。
  これがないと、たしかに大変そうである。
  データ量が多いので、そこそこコピーには時間がかかる。
  クリーンインストール直後はSDカードが使えないっぽいのでUSBメモリに入れること。


  追記: バックアップ取れなかった人は、ドライバはSurface3 WiFiモデルの
   ドライバセットが使えるらしい。(未検証)
   http://d.hatena.ne.jp/TAKETYON/touch/20160805

公式BIOSアップデート
 →公式のBIOSアップデートツールを使いアップデートする。
  3回くらいの書き換えが走るので、割と時間掛かる。

ライセンスキー取得
 →デジタル認証なので特に意味は無いのだが、
  一応Windows Product Key Viewerでプロダクトキーをとっておく。
  結果的に言えば不要であった。


*クリーンインストール

AnniversaryUpdateのクリーンインストール
 →別のPCで、公式のインストールメディア生成ツールを使い、
  セットアップ用USBメモリを作成。
  ポータブックに差し、F2キー連打でUSBブート。

  散々言われているのでご存知だとは思うのだが、
  本体のマウスやキーボードは使用できないので、
  USBハブにUSBメモリと、マウスと、キーボードを挿して挑むこと。

  ドライバがないせいで、Wi-Fi接続が使えない
  →Microsoftアカウントが使えない になるので注意。
  監査モードで組み込むなり、USB-LANでも挿せば行けるのかもしれない。

ドライバのインストール
 →無事セットアップが済んだら、デバイスマネージャを開き、不明なデバイスを片っ端から
  バックアップしたDriverStoreを指定して認識させる。
  Wi-Fi、キーボード、マウス、音声、SDカード、Bluetoothなどは
  すべてこの段階で認識される。

  再起動して、増えたらまたそいつらも突っ込むこと。

  また、何の気なしに認識されているディスプレイアダプターも
  DriverStoreで更新するのを忘れずに。
  これだけやたら時間が掛かるが、Intel HD Graphicsで認識する。

  これが済んだら、USBハブは引っこ抜いて良い。

プリインストールappの削除
 →最初から入っている例えば「フォト」などを消す。
  どのくらい空き容量に貢献するのかは不明。
  ただ、片っ端からダウンロードしようとしていたので、多少は空くはず。
  Xboxアプリはシステムと結合されたらしく、削除できなくなっている。


facebook、minecraftなどの削除
 →Wi-Fiに接続すると色々入ってくるので、片っ端からアンインストール。
  スレによれば、Minecraftはそこそこ遊べるらしい。

公式ドライバアップデート導入
 →キングジム公式のドライバアップデートを適用。
  自分のときは、Wi-Fiしか適用できなかったが...?

電源設定、「退席中である事を〜」の解除
 →スリープの設定などもクリーンインストールでもとに戻ってるので、
  またスリープしないように直す。
  「退席中であることをデバイスが認識しているときに電力を節約する」は、
  調べる限り不味い挙動しかしないようなので解除。

Windowsアップデート
 →Windowsアップデートを一通り当てる。
  自分の環境だと2~3時間くらいかかった。

Cortanaを止める
 →お好みで。

その他カスタマイズ
 →視覚要素をパフォーマンス優先にしたり
  (アニメーションは切らないほうがいい。
   アップデート時などの実行中表示も消えるため、フリーズしたかと思うことになる。)
  マウス速度を「左から3番目」にしたり。

1GBを復元ポイントに割り当て
 →復元ポイントなしは流石に不安なので、ここで1GB分割り当てた。
  意味があるかは不明。

追記: ディスク暗号化の解除
 →ディスク管理で確認すると、なぜかディスクが暗号化されていたので解除。
  ただでさえ圧縮しているのに、暗号化するとさらに重くなるであろう。
  暗号化用モジュールと、携帯機であることから、自動で有効になったか。

  設定→システム→バージョン情報→デバイスの暗号化 
  にて「オフ」にすると解除される。

*空き容量の確保

ここから、空き領域確保を行う。WindowsUpdateが終わってから行うこと。
結果として、6GBほど空く。28GB中の6GBなので、21%ほど空くことになる。

この時点で空き容量: 10.7GB
dismによるWinSxsのクリーンアップ
 →WindowsUpdateなどの情報や、不要なドライバ情報を整理してくれる。
  しかし、100%が2回出てから、フリーズしたようになるので注意。
  ひたすら放って置くこと。じりじりと空き容量が増える。

  一度、エラー2で終了するが、もう一度行うと20%くらいで正常終了となる。
  2.2GBほど空き領域が増える。

  Dism.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase

この時点で空き容量: 12.9GB

ディスククリーンアップ
 →おなじみのディスククリーンアップ。
  Windowsの販売デモ用ファイルなんかがある。
  といっても、環境にもよるのだろうが、0.1GBくらいしか減らない。

この時点で空き容量: 13.0GB
NTFS圧縮
 →CドライブにNTFS圧縮をかける。
  2時間半かかるという表示だったが、実際には1時間ちょっとで終わった。
  1.7GBほど空く。

この時点で空き容量: 14.7GB
compactos
 →Windows10から導入された、システムファイルの圧縮機能を実行する。
  30分~1時間ほどかかる。

  これで2.1GBほど空き領域が出来る。
  これは持続的に作用するらしいので、WindowsUpdateでの
  増加を抑える効果もあるのでは。

  compact /CompactOS:always
この時点で空き容量: 16.8GB (使用量11GB)


*SDカードの利用

SDカードHDD化
 →めっちゃくちゃアクセス遅い(書き込みが恐ろしく遅い)ので取りやめ。
 →VHDを用いて、SDカードを物理ドライブに見せかける。
  生成後、500MB以上の空きがないと不安定になるらしいので注意。
  1時間半ほどかかった。


  作成後は、SDカードをSドライブに変更。
  遅延書き込みを有効にし、性能アップを期待する。

  VHDをフォーマットし、圧縮を有効。Dドライブに割り当て。
  VHDマウントツールを用いて、起動時に自動マウント。

  VHDマウントツール

  タスクスケジューラの設定の際、アカウントをSYSTEMにし、
  「スタートアップ時」と「ログオン時」、「ワークステーション アンロック時」
  の両方をトリガにしておくと安心。
  -bootの効果で、既にマウントされている場合は無視されるし。

  その後、レジストリからSドライブを非表示(0x40000)に設定。
  HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\に
  Explorerキーを作り
  HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer
  そこにDWORDで値:NoDrivesを作り、0x40000を設定して再起動。
  すると、ExplorerからSドライブが見かけ上消える。

  もちろん、見かけ上なので、S:\を直接叩くと開けるし、

  ディスク管理にも存在する。他のアプリケーションからもアクセスできる。
  容量パンパン赤ゲージのSDカードを見たくない人専用である。


  参考:マイコンピュータのドライブを非表示にする - 日経トレンディ

SDカードのCドライブ組み込み
 →NTFSを適用した上でさらにVHDを適用すると、
  (設定が悪いのか)数kb/secとかいう超低速になったので、
  代わりに、「空のNTFSフォルダにマウントする」で、SDカードをCドライブに割り当てた。
  一応、これでリムーバブルメディアへインストールできないタイプのソフトウェアも
  インストールできるようになるらしい。

  参考: http://funlike.org/wp/archives/11693

  SDカードをSドライブに割り当てるのはそのままにしておき、
  Sドライブを非表示にするのもそのままとした。

ユーザーフォルダ(デスクトップなど)の移動
 →これは移動するだけ。

画面調整編
ポータブックって妙に目疲れない?

nyoiscreenの導入
 →XMC10の画面は、ギラついている上に、最低輝度でもまだ明るい。
  メインPCの最低輝度より明るいため、同等に下げる効果を狙ってnyoiscreenを導入。
  これはカラーフィルタであり、ソフトウェア的に画面の輝度を下げる効果がある。

Intel HD Graphicsでの調整
 →どうみてもこの液晶は青が強すぎる。
  ただでさえ16bitカラーで色が悪い液晶をさらに悪くするのもあれだが、
  青の明るさを-60、緑と赤の明るさを+3に設定。
  個人的に見やすい色に変更。

スピーカーのプロパティ
 →このPCの音、妙に高音ばかりのスカスカした音だと思わないだろうか。
  なんと、Intel HD AudioのSystem Effectsが有効になっており
  こいつがステレオ感を無駄に上げている。
  オフにすると、少しこもった低音が出るようになる。

アプリケーション導入編
Chromeの導入
 →メモリ不足環境では嫌われがちのChromeだが、
  自分が主にGoogle関係のサービスをメインに使うので導入した。
  Edgeでもいいかと思ったが、崩れてしまうため。
  
  導入先はCしか選べないが、キャッシュ先を
  先程フォルダにマウントしたSDカードに変更した。

  シンボリックリンクを貼る手法である。
  ※SDカード上にキャッシュを配置するのは、本来は悪手である。
   (低速化するため)。RAMDISKがいいのだが、RAMに余裕が無いのでこうするしかない。

office365の導入
 →office365は、インストールしようとするとフルセット5GBくらい入れようとしてくる。
  SkypeやらAccessやらはポータブックには不要だろう。
  以下のconfiguration.xmlを保存し、Office 展開ツール付属のsetup.exeに食わせると
  Word、Excel、PowerPoint、Outlookの標準セットのみ(1.02GB)でインストールできる。

  なお、インストール先は強制でCドライブである。

  注意:  Product IDは入れる対象のライセンスにより変化する。

<Configuration>
  <Add OfficeClientEdition="32">
    <Product ID="O365ProPlusRetail">
      <Language ID="ja-jp" />
      <ExcludeApp ID="Access" />
      <ExcludeApp ID="Lync" /> 
      <ExcludeApp ID="Groove" /> 
      <ExcludeApp ID="OneNote" />
      <ExcludeApp ID="Publisher" /> 
      </Product>
  </Add>
</Configuration>


VisualStudioの導入
 →Dドライブ(仮想VHDのSDだった)を2GB、Cドライブを5GB食う(強制)な上に
  インストールにまる一日程かかり(環境により)
  アンインストールしてもゴミをたくさんおいていくので、
  入れようとしないほうが良い。
  そういうマシンではない。

 →入れてしまったら
  「@pnp0a03氏: VS2013-2015の場合、VS根こそぎアンインストーラというのを
   MSのエンジニア氏がGitHubに上げています
   機会がありましたらどうぞ 僕は一度試しましたがきれいさっぱり消えました
   https://github.com/Microsoft/VisualStudioUninstaller
  https://twitter.com/pnp0a03/status/803568494478401536


休止状態を使えるようにする
 →なぜかポータブックは(クリーンインストール後だけかもしれないが)
  スリープはできても休止状態にできない。

  powercfg /a で確認すると、
  「この休止状態ファイルの種類では休止状態はサポートされません」と
  言われるので、管理者権限のあるコマンドプロンプトで以下を実行。

  powercfg /h /type full
  powercfg /h on

  これで、電源設定に休止状態のチェックボックスが現れるようになる。
  参考: http://kokoore.com/windows10-hiber  

  ちなみに、原因かと思ってInstant Goをレジストリで無効にしたところ、
  電源設定に、隠蔽されていた各種省電力設定が現れたので、
  いじりたい人は試してみるといいかもしれない。


Bluetoothネットワークの設定
 →iPhoneなどのBluetoothテザリングが使える機種を持ってる場合、
  端末操作無しでテザリング開始でき、省電力なBluetoothテザリングの
  設定をしておくと気軽に使えて便利。

  Bluetoothテザリングを有効にした状態でペアリングし、
  コントロール パネル\すべてのコントロール パネル項目\デバイスとプリンター を開き
  Bluetoothデバイスを右クリックして、「接続方法」→「アクセスポイント」をクリック。
  
  というのも面倒なので、デスクトップにデバイスのショートカットを作っておくと
  右クリック→クリックの2操作だけで接続できる。

  参考: http://mobamen.info/pc/887

2016年10月8日土曜日

自作基板用にPS/2キーボードを買った

PS/2キーボードを購入した。



サンワサプライ PS/2キーボード SKB-L1 サンワサプライ via amazonJP (682円)
サンワサプライ SANWA SUPPLY SKB-L1 [PS/2キーボード] - ヨドバシ.com (750円)
見ての通り、値段がかなり安い。それでいて、今時PS/2専用である。

もっとも、自分はネットショップで買う時間ももったいなかったので、地元の電気店で850円で購入した。
安い割に、キータッチも悪くなく、アプリケーションキーまでついている。
そして綺麗だ。中古の200円のPS/2キーボードを買おうか迷ったので、尚更きれいに見える。

なぜ今更PS/2キーボードなんかを購入したかというと、とある基板にキーボードを繋ぐためである。

その基板ではTTBASICが動いているが、シリアル入出力では使いにくいので、画面とキーボードを繋いで使うのだ。

Arduino互換機版で作成しているため、Arduino PS/2ライブラリ(の日本語キーボード仕様版)で動いてくれる必要がある。
このライブラリ、簡単のためにPS/2キーボードのセルフテストや初期化をやっていないらしく、
一部の変なキーボードや、USB/PS/2兼用だと変な反応を示す。(俗に、ichigojamで使えないキーボード)

このキーボードは問題なく動作したことを記しておく。

2016年10月4日火曜日

Sound Packet


マイクからの音量を監視し、しきい値以上の大きさの音を検出したら、
外部サービスへ通知するツール、作りました。

別室のラジコンバッテリーの充電が終わるのを待つのが面倒だったので、
こういうツールがないかとネットを探し回るも、全然見つからず。

スマホに通知するために簡易ツールを作ったのですが、
せっかくなのでネットに上げたら誰か使うことあるかな、と思い、
見栄えを整えて上げた次第です。

ダウンロードはこちら
https://sites.google.com/site/gpsnmeajp/tools/sound-packet

2016年9月15日木曜日

ボクのかんがえたさいきょうのFlashAir拡張ボード

ボクのかんがえたさいきょうのFlashAir拡張ボード。
検討だけ。

・ボード上にはMCUが乗っており、共有メモリを使ってFlashAirと通信する

・共有メモリ上には固定の領域を設けておく。
 デジタル入力(8本?)
 デジタル出力(8本?)
 A/D入力(10bit?5本?)
 PWM出力(サーボ用)(5本?)
 LCD(I2Cでもなんでもいいので適当に)
 UART(つける?)

・一定周期で更新。
 出力は、サイクルごとにメモリを読みだし、に書き込まれた情報通りに出力。
 A/Dや入力も、サイクルごとに行う。
 LCDは、共有メモリ上の更新フラグが立った時、LCDに書き込む感じ。

・MCUはAVRかそこらで実装する。
・MCUの書き換えは想定しない。

・空き領域を使って、特殊コマンドを発行していろいろ出来ると楽しそう?

利点
・共有メモリなので、FlashAir上のLuaや、ブラウザのjavascriptの両方から操作可能。
・入出力が少なく、種類もないFlashAirの欠点をカバーできる
・一般的な5VのI/Oが利用できる
・Wi-Fiを活かせる
・FlashAir側からすれば単に共有メモリへの読み書きであり、プログラムがシンプル
・MCU側で好きなようにできるため、機能の拡張がしやすい

欠点
・共有メモリを扱う都合上、遅い。8MHzで通信しても、書き込み・読み出し合計3ms掛かる。
 いろいろ考えると、200Hzで更新できればいいほうか。
・汎用マイコンでいい気もしないでもない。
・せっかくのPIOやSPI機能を活かせない
・I2CのIOポートエキスパンダーのほうが安価では?
iSDIOとしての通信になるため、SDカードライセンスの問題が出てくる


ライセンスさえ問題なければ、個人で作って売れそうな気もしないでもない。

SDカード対応と謳わなければよいのか?
ArduinoとSDカードシールドなんかのライセンスはどうなってるんだ?
プログラムが入っていなければ問題ないのか?

Airioなんかは、あれはSDカードとしての動作ではないから引っかからないのか?

2016年9月9日金曜日

FlashAirの共有メモリにアクセスするサンプル

突然、無性にArduinoのSDカードライブラリに頼らず、FlashAirの共有メモリにアクセスしたくなったので。

今後、Luaスクリプトとマイコンの間で通信したくなる機会が増えると思うので、
苦手意識の強かったSDカードコマンドでの通信を試すべきだと思った。

SDカードライブラリに頼らなかったのは、あれがGPLだということと、
PIC等他のC環境で使いたかったため。移植を楽にするため、共有メモリアクセスに特化したかった。

ACMD41での初期化など、色々はまったので、SDカードの初期化の手順的な参考にもなるかもしれない。
プログラム本体は、長いのでサイトの方にあげてある。
https://sites.google.com/site/gpsnmeajp/electricmemo/flashairno-gong-youmemoriniakusesusurusanpuru

DIV4で、512Byteのアクセスに2.5ms程度。
DIV2だと1.8ms程度。

2016年9月6日火曜日

Grove MP3モジュール v2.0 (KT403A)の仕様について(曲選択機能)

Grove MP3モジュール v2.0 (KT403A)の仕様について。

秋月で売られているKT403Aのモジュールは、安価で、
SDカード(およびUSBメモリ)からmp3音楽を再生できる、非常に便利なモジュールであるが、
曲選択機能においてわかりづらい場所があって困ったので、記録しておく。

このモジュール、単に入れた曲を再生したり、切り替えたりするのは問題ない。
しかし、このモジュールを使いたい多くの人は、特定のmp3ファイルを指定して再生したいだろう。
ここで引っかかりが出る。

まず、予め言っておくが、秋月のページに有る英文データシートは明らかに項目数が少ない。
翻訳の際の誤植もある。中国版データシートを参照することをおすすめする。

ちなみに、通信のチェックサムがさもあるかのように書かれているが、実際に通信する際には
チェックサムは不要である。有効にするオプションが有るのかもしれないが。


まず、最初に、特定のファイルを再生しようとして使うのは、
"Play specific track*" だろう。
Groveのサンプルで言うところの
void SpecifyMusicPlay(uint16_t index)
である。

0x7E 0xFF 0x06 0x03 0x00 FF FF 0xEF
と送れば、65535.mp3が再生される、と思うかもしれない。
実際には、65535番目に記録されたファイルが再生される。

0.mp3
1.mp3
999.mp3

があったとき、
0x7E 0xFF 0x06 0x03 0x00 00 02 0xEF
と送ると、999.mp3が再生される。(02ではなく、03だったかもしれないが)

データシートをよく読むと、「Note that the empty filed need to be filled with specific numbers.」と
書かれているが、それはこの仕様のためである。


"2.3.7 Specify a file to play tracks inside [0x14]"
も同じで、

Play track 0255 (track’s name) in folder 0001 : 7E FF 06 14 00 10 FF FD D8 EF
Play track 1999 (track’s name) in folder 0001 : 7E FF 06 14 00 17 CF FE 01 EF
Play track 0001 (track’s name) in folder 0012 : 7E FF 06 14 00 C0 01 FE 26 EF
Play track 0255 (track’s name) in folder 0012 : 7E FF 06 14 00 C0 FF FD 28 EF
Play track 1999 (track’s name) in folder 0012 : 7E FF 06 14 00 C7 CF FD 51 EF

と書かれていることから、

例えば
7E FF 06 14 00 10 FF FD D8 EF
と送れば、フォルダ0001の、0255.mp3が再生される。
...と思うだろう。実際には、1番目のフォルダの、255番目に記録されたファイルが再生される。
255番目である。ファイル名に関係なく、FATに記録された順番で再生されるらしい。


特定のファイル名を再生したいならば、
"Specify a certain folder and play tracks inside [0x0F]"
Groveのサンプルで言うところの
void SpecifyfolderPlay(uint8_t folder, uint8_t index)
を使う必要がある。

Specify folder name 01 and track name 001xxx.mp3 7E FF 06 0F 00 01 01 EF
Specify folder name 11 and track name 100xxx.mp3 7E FF 06 0F 00 0B 64 EF
Specify folder name 99 and track name 255xxx.mp3 7E FF 06 0F 00 63 FF EF

※255が誤植で001になっているので注意。

これも表記がわかりにくいのだが、

Specify folder name 01 and track name 001xxx.mp3 7E FF 06 0F 00 01 01 EF
というのは、つまり、01という名前のフォルダの、001から始まるファイル名が再生されるということである。
中国版データシートでは、スクリーンショットとともに丁寧に説明されている。

つまり、
01\001Test.mp3 → 7E FF 06 0F 00 01 01 EF
01\002Wow.mp3 → 7E FF 06 0F 00 01 02 EF
02\255Buzz.mp3 → 7E FF 06 0F 00 02 FF EF
ということである。

もちろんこちらは空のファイルで埋める必要はない。きちんとファイル名で再生してくれる。

とりあえず以上。

2016年9月5日月曜日

Pebble Timeのファームウェアが4.0になった。

Pebble Timeのファームウェアが4.0になった。
メニュー画面がシンプルになり、アイコンが表示されてわかりやすくなった。


また、QuickViewが追加され、近いイベントがウォッチフェイスに表示されるようになった。
ところがこれが曲者で、自作のWatchFaceは、ちょうどQuickViewにすっぽり隠れる位置に
情報を集約させているため、時計が見えなくなってしまうのだ。

時計が見えず、次の予定までの時間のみが見える時計、というのも、悪くはないかもしれないが困る。
一応、設定からQuickViewを無効にすれば今までどおりに使えるのだが、
せっかくのスマートウォッチな機能を無効にするのもアレである。

ので、QuickViewが表示されるときは、単にWatchFace全体を上にずらすことにした。単純明快である。

しかし、Pebble公式SDKの解説がわかりづらくて困った。自分の読解力がないだけかもしれない。
ようは簡単な話で、

今まで、
   GRect bounds = layer_get_bounds(window_layer);
で得ていた全画面の描画領域を、
   GRect bounds = layer_get_unobstructed_bounds(window_layer);
に置き換えて、座標指定を相対化してあれば勝手にずれる、という話なのだが、
自作のWatchFaceはそれではうまくいかない。

結局、描画オブジェクトを1枚のレイヤーに集約し、

   GRect QVbounds = layer_get_unobstructed_bounds(window_layer);
   layer_set_bounds(all_layer, GRect(0, QVbounds.size.h +(0-168), QVbounds.size.w, 168));
で移動。

しかしこれでは、表示中にQuickViewが現れた場合に対応しないので、
//unobstructedハンドラ
static void prv_unobstructed_will_change(GRect final_unobstructed_screen_area,
void *context) {
  GRect bounds = final_unobstructed_screen_area;
  layer_set_bounds(all_layer, GRect(0, bounds.size.h +(0-168), bounds.size.w, 168));
}

//unobstructedハンドラ
static void prv_unobstructed_did_change() {
   Layer *window_layer = window_get_root_layer(s_main_window);
  GRect bounds = layer_get_unobstructed_bounds(window_layer);

  layer_set_bounds(all_layer, GRect(0, bounds.size.h +(0-168), bounds.size.w, 168));
}
を追加。

static void main_window_load(Window *window) 
  //画面領域サービス(Quickview)に登録する
  UnobstructedAreaHandlers handlers = {
    .will_change = prv_unobstructed_will_change,
    .did_change = prv_unobstructed_did_change
  };
  unobstructed_area_service_subscribe(handlers, NULL);
を追加。

でなんとかなった。
詳細は後でサンプルを上げようと思う。

2016年9月1日木曜日

ポテンシャル法のC言語での実装例

ロボットの障害物回避などに使われる、ポテンシャル法のC言語での実装例
(あっているかは不明なので、参考程度に)


なんで調べても数式ばっかりで実装例が出てこないんだろう?


*ポテンシャル場の確認
#include <stdio.h>
#include <math.h>

double get_pot(double x, double y)
{
const double Enemy1_x = 5.;
const double Enemy1_y = 10.;

const double Enemy2_x = -10.;
const double Enemy2_y = -20.;

const double Goal_x = 17.;
const double Goal_y = 0.;

const double Weight_Enemy1 = 1.0;
const double Weight_Enemy2 = 1.0;
const double Weight_Goal = 5.0;

//スカラー場なのでx,y成分共に同じ
double Enemy1_pot = 1.0 / sqrt((x - Enemy1_x)*(x - Enemy1_x) + (y - Enemy1_y)*(y - Enemy1_y));
double Enemy2_pot = 1.0 / sqrt((x - Enemy2_x)*(x - Enemy2_x) + (y - Enemy2_y)*(y - Enemy2_y));
double Goal_pot = -1.0 / sqrt((x - Goal_x)*(x - Goal_x) + (y - Goal_y)*(y - Goal_y));

double pot = Enemy1_pot * Weight_Enemy1 + Enemy2_pot * Weight_Enemy2 + Goal_pot * Weight_Goal;
return pot;
}

int main(void)
{
FILE *fp = fopen("output.txt", "w");
if (fp == NULL)
{
printf("Err\n");
return -1;
}

printf("wait...\n");

const double delta = 0.1;
const double max = 1.0; //上限(発散部分除外)
// const double zoom = 10.;
for (double x = -30; x < 30; x += delta)
{
for (double y = -30; y < 30; y += delta)
{
double pot = get_pot(x, y);
if (pot > max)
pot = max;
if (pot < -max)
pot = -max;


fprintf(fp, "%lf,%lf,%lf\n", x, y, pot);
}
fprintf(fp, "\n");//pm3dは空行がないと補完しない
}
fclose(fp);
printf("Done\n");

return 0;
}


*GNUPLOTスクリプト
set pm3d corners2color max
set pm3d depthorder
set datafile separator ","
set xrange[-30:30]
set yrange[-30:30]
#set view map
splot "output.txt" with pm3d


*結果


*勾配ベクトル場の確認
#include <stdio.h>
#include <math.h>

double get_pot(double x,double y)
{
const double Enemy1_x = 5.;
const double Enemy1_y = 10.;

const double Enemy2_x = -10.;
const double Enemy2_y = -20.;

const double Goal_x = 17.;
const double Goal_y = 0.;

const double Weight_Enemy1 = 1.0;
const double Weight_Enemy2 = 1.0;
const double Weight_Goal = 5.0;

//スカラー場なのでx,y成分共に同じ
double Enemy1_pot = 1.0 / sqrt((x - Enemy1_x)*(x - Enemy1_x) + (y - Enemy1_y)*(y - Enemy1_y));
double Enemy2_pot = 1.0 / sqrt((x - Enemy2_x)*(x - Enemy2_x) + (y - Enemy2_y)*(y - Enemy2_y));
double Goal_pot = -1.0 / sqrt((x - Goal_x)*(x - Goal_x) + (y - Goal_y)*(y - Goal_y));

double pot = Enemy1_pot * Weight_Enemy1 + Enemy2_pot * Weight_Enemy2 + Goal_pot * Weight_Goal;
return pot;
}

int main(void)
{
FILE *fp = fopen("output.txt", "w");
if (fp == NULL)
{
printf("Err\n");
return -1;
}

printf("wait...\n");

const double delta = 1.2;
// const double zoom = 10.;
for (double x = -30; x < 30; x += delta)
{
for (double y = -30; y < 30; y += delta)
{
//勾配ベクトル算出 -grad(P)
double vx = -(get_pot(x + delta, y) - get_pot(x, y))/delta;
double vy = -(get_pot(x, y + delta) - get_pot(x, y))/delta;
double v = sqrt(vx*vx + vy*vy);

// vx *= zoom;
// vy *= zoom;
//見やすさのためにベクトルを正規化
vx /= v;
vy /= v;

// printf("%lf,%lf,%lf\n", x, y);
if(!isnan(vx) && !isnan(vy)) //無効な値は除外
fprintf(fp, "%lf,%lf,%lf,%lf,%lf\n", x, y, vx, vy,v);
}
// fprintf(fp, "\n");//pm3dは空行がないと補完しない
}
fclose(fp);
printf("Done\n");

return 0;
}


*GNUPLOTスクリプト
set datafile separator ","
set xrange[-30:30]
set yrange[-30:30]
set size ratio 1
set palette rgb 33,13,10
#plot "output.txt" u 1:2:3:4:(sqrt($3*$3+$4*$4)) w vector lc palette ti ""
plot "output.txt" u 1:2:3:4:5 w vector lc palette ti ""


*結果

*ポテンシャル法による障害物回避
#include <stdio.h>
#include <math.h>

double get_pot(double x, double y)
{
const double Enemy1_x = 5.;
const double Enemy1_y = 10.;

const double Enemy2_x = -10.;
const double Enemy2_y = -20.;

const double Goal_x = 17.;
const double Goal_y = 0.;

const double Weight_Enemy1 = 1.0;
const double Weight_Enemy2 = 1.0;
const double Weight_Goal = 5.0;

//スカラー場なのでx,y成分共に同じ
double Enemy1_pot = 1.0 / sqrt((x - Enemy1_x)*(x - Enemy1_x) + (y - Enemy1_y)*(y - Enemy1_y));
double Enemy2_pot = 1.0 / sqrt((x - Enemy2_x)*(x - Enemy2_x) + (y - Enemy2_y)*(y - Enemy2_y));
double Goal_pot = -1.0 / sqrt((x - Goal_x)*(x - Goal_x) + (y - Goal_y)*(y - Goal_y));

double pot = Enemy1_pot * Weight_Enemy1 + Enemy2_pot * Weight_Enemy2 + Goal_pot * Weight_Goal;
return pot;
}

int main(void)
{
FILE *fp = fopen("output.txt", "w");
if (fp == NULL)
{
printf("Err\n");
return -1;
}

printf("wait...\n");

//出発地点
double x = -10.;
double y = 20.;

const double delta = 0.1;
const double speed = 0.1;
for (int i = 0; i < 1000;i++)
{
//勾配ベクトル算出 -grad(P)
double vx = -(get_pot(x + delta, y) - get_pot(x, y)) / delta;
double vy = -(get_pot(x, y + delta) - get_pot(x, y)) / delta;
double v = sqrt(vx*vx + vy*vy);


//ベクトルを正規化
vx /= v / speed;
vy /= v / speed;

//移動反映
x += vx;
y += vy;

fprintf(fp, "%lf,%lf,%lf,%lf,%lf\n", x, y, vx, vy, v);
}
fclose(fp);
printf("Done\n");

return 0;
}


*GNUPLOTスクリプト
set datafile separator ","
set xrange[-30:30]
set yrange[-30:30]
set size ratio 1
set palette rgb 33,13,10
#plot "output.txt" u 1:2:3:4:(sqrt($3*$3+$4*$4)) w vector lc palette ti ""
plot "output.txt" u 1:2:3:4:5 w vector lc palette ti ""


*結果

追記: コメントにスカラー場なので」と書いてしまっているが、x,yによらず同じ形状なので、が正しいか。