制御とコンピューターサイエンスの間

This is a blog to share codes and ideas for building robots/aeronautical systems

vs code で latex

この記事は自分へのメモ

参考にしたサイト

前提

  • TexLiveをインストール(latexの諸々のcompiler?が入る)
  • vs codeLatex Workshopをインストール

コンパイル設定

あとは,vs code内でtexliveでインストールしたcompilerたちを使ってどう文書を作成するかの設定.
躓いたのが日本語のlatex
いつもノリでlatexをやっていたので,ptex2pdfやpbibtexで-kanji=utf8オプションを加えると日本語コンパイル出来るの知らなかった.

そこで,英語・日本語の文書のコンパイルが選べるように,
Latex Workshop内でそれぞれのコンパイラを組み合わせてrecipeを作っておきます.
作り終わったら,あとはそのrecipeをvs code内で走らせるだけ.

cmd+,で設定を開き,settings.jsonに以下を記述

 {
    "window.zoomLevel": 2,
    "latex-workshop.view.pdf.viewer": "tab",
    "latex-workshop.latex.autoBuild.run": "never",
    "latex-workshop.latex.clean.fileTypes": [
        "*.aux", "*.bbl", "*.blg", "*.idx", "*.ind", "*.lof", "*.lot", "*.out", "*.toc", "*.acn", "*.acr", "*.alg", "*.glg", "*.glo", "*.gls", "*.ist", "*.fls", "*.log", "*.fdb_latexmk", "*.synctex.gz",
        // for Beamer files
        "_minted*", "*.nav", "*.snm", "*.vrb",
    ],
    "latex-workshop.latex.tools": [
        {
            "name": "latexmk",
            "command": "latexmk",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "-pdf",
                "%DOC%"
            ]
        },
        {
            "name": "pdflatex",
            "command": "pdflatex",
            "args": [
                "-synctex=1",
                "-interaction=nonstopmode",
                "-file-line-error",
                "%DOC%"
            ]
            },
        {
            "name": "bibtex",
            "command": "bibtex",
            "args": [
                "%DOCFILE%"
            ]
        },
        {
            "name":"ptex2pdf",
            "command": "ptex2pdf",
            "args": [
                "-l",
                "-ot",
                "-kanji=utf8 -synctex=1",
                "%DOC%"
            ]
        },
        {
            "name":"ptex2pdf (uplatex)",
            "command": "ptex2pdf",
            "args": [
                "-l",
                "-u",
                "-ot",
                "-kanji=utf8 -synctex=1",
                "%DOC%"
            ]
        },
        {
            "name": "pbibtex",
            "command": "pbibtex",
            "args": [
                "-kanji=utf8",
                "%DOCFILE%"
            ]
        }
    ],
    "latex-workshop.latex.recipes": [
        {
            "name": "ptex2pdf -> pbibtex -> ptex2pdf*2",
            "tools": [
                "ptex2pdf",
                "pbibtex",
                "ptex2pdf",
                "ptex2pdf"
            ]
        },
        {
            "name": "latexmk",
            "tools": [
                "latexmk"
            ]
        },
        {
            "name": "pdflatex*2",
            "tools": [
                "pdflatex",
                "pdflatex"
            ]
        },
        {
            "name": "pdflatex -> bibtex -> pdflatex*2",
            "tools": [
                "pdflatex",
                "bibtex",
                "pdflatex",
                "pdflatex"
            ]
        },
        {
            "name": "ptex2pdf*2",
            "tools": [
                "ptex2pdf",
                "ptex2pdf"
            ]
        },
        {
            "name": "ptex2pdf (uplatex) *2",
            "tools": [
                "ptex2pdf (uplatex)",
                "ptex2pdf (uplatex)"
            ]
        },
        {
            "name": "ptex2pdf (uplatex) -> pbibtex -> ptex2pdf (uplatex) *2",
            "tools": [
                "ptex2pdf (uplatex)",
                "pbibtex",
                "ptex2pdf (uplatex)",
                "ptex2pdf (uplatex)"
            ]
        },
    ]
}

コンパイル用のショートカット設定

  1. Ctrl+Shift+Pを押下し、『Build with recipe』を検索・選択
  2. 選択画面が出てきたら、操作をキャンセル
  3. Ctrl + Kを押下
  4. Ctrl + Sを押下
  5. 検索窓で『Build with recipe』を検索
  6. Build with recipeをダブルクリック
  7. キーショートカットを設定

latex workshopそのほかの設定

latex workshopの公式ページに諸設定の説明が書いてあります.
今僕が設定したのは,以下の通り.
pdfをvs code内の「タブ」で見たいときは"tab", そのほかに"none" | "browser" | "external"があります. こんな感じで,勝手にビルドしてしまう設定もオフにします. autoBuild.run: "never" また,いらない途中生成ファイルをビルド後に削除も設定.

    "window.zoomLevel": 2,
    "latex-workshop.view.pdf.viewer": "tab",
    "latex-workshop.latex.autoBuild.run": "never",
    "latex-workshop.latex.clean.fileTypes": [
        "*.aux", "*.bbl", "*.blg", "*.idx", "*.ind", "*.lof", "*.lot", "*.out", "*.toc", "*.acn", "*.acr", "*.alg", "*.glg", "*.glo", "*.gls", "*.ist", "*.fls", "*.log", "*.fdb_latexmk", "*.synctex.gz",
        // for Beamer files
        "_minted*", "*.nav", "*.snm", "*.vrb",
    ],

macにROS Kineticを入れた

環境

公式サイトとの違い

ROS公式サイトでは Pythonbrew install pythonでインストールしているが,自分はpyenvで管理しているのでそこのパスを使う

手順

設定

1.1 Homebrew

$ brew update
$ brew install cmake
$ brew tap ros/deps
$ brew tap osrf/simulation   # Gazebo, sdformat, and ogre
$ brew tap homebrew/core # VTK5
$ brew tap homebrew/science  # others

1.2 環境設定

公式との違い1 どこにインストールされているPythonとsitepackagesを使っているか確認

$ which python
/Users/kandai/.pyenv/shims

ディレクトリが分かったのでパッケージ管理しているフォルダを探し,homebrewでインストールしたモジュールをPythonに教えてあげる.

$ echo "$(brew --prefix) /lib/python2.7/site-packages" >> /Users/kandai/.pyenv/versions/2.7.15/lib/python2.7/site-packages/homebrew.pth

1.3 その他ツール

$ sudo -H python2 -m pip install -U pip  # Update pip
# wsPythonはしっかりインストールしましょう.rosde installの部分で怒られました.
$ sudo -H python2 -m pip install wxPython # Install python-wxtools
$ sudo -H python2 -m pip install -U wstool rosdep rosinstall rosinstall_generator rospkg catkin-pkg sphinx
$ sudo -H rosdep init
$ rosdep update

2 インストール

2.1 catkin packagesのビルド

ここからはUbuntuとほぼ一緒

$ mkdir ~/ros_catkin_ws
$ cd ~/ros_catkin_ws
$ rosinstall_generator desktop_full --rosdistro kinetic --deps --wet-only --tar > kinetic-desktop-full-wet.rosinstall
$ wstool init -j8 src kinetic-desktop-full-wet.rosinstall

依存フォルダーを解決

$ rosdep install --from-paths src --ignore-src --rosdistro kinetic -y

catkin packagesのビルドをしていきます

./src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release

~/ros_catkin_ws/install_isolatedにパッケージがインストールされたので,バイナリーを使えるようにするには,

$ source ~/ros_catkin_ws/install_isolated/setup.bash

UnityのCoRoutineについて

CoRoutineとはUnity公式マニュアルによると

コルーチンとは実行を停止して Unity へ制御を戻し、ただし続行するときは停止したところから次のフレームで実行を継続することができる関数です。

ほへ?

CoRoutineの動作がわかりやすいスクリプト

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HelloCoroutine : MonoBehaviour
{
    private int count = 0;

    // Use this for initialization
    void Start ()
    {
        Debug.Log("start");
        enabled = false;
        string str = "Hello World";
        StartCoroutine(IEnumeratorMethod(str));
        StartCoroutine(IEnumeratorMethod(str));

        enabled = true;
        Debug.Log("EndStart");
    }
    
    // Update is called once per frame
    void Update ()
    {
        Debug.Log("update");
    }


    public IEnumerator IEnumeratorMethod(string str)
    {
        Debug.Log("before");
        yield return null;
        Debug.Log("after");
        yield return null;

    }
}

f:id:kandaiwata:20180720113755p:plain

まず初めにyieldは英語で生産という意味がありますが、 諦めるや止めるという意味もあります。 処理を一旦ここで止めましょうということで意味で捉えることとします。

1 Loop目: Start()関数の中身がまず実行されます。 ちょっと待ってーやという感じでStartCoroutine(IEnumeratorMethod(str));が割り込んできます。 するとbeforeが出力されますが、 「うふふふ今回はここまで♡」みたいな感じでyield return null;で処理を中断します。 次のStartCoroutine(IEnumeratorMethod(str));も同様。 すると、Start()の最後にたどり着きEndstartを出力。 まだまだ続き、update()関数があるHz数分呼ばれます。(ここどうなっているんでしょう)

2 Loop目突入: CoRoutineで「うふふ次回のお楽しみ♡」みたいな感じで寸止めされた処理がありますよね? ここでafterが出力されます。

もう少し発展させます。次はStart()関数をIEnumeratorにしたいと思います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HelloCoroutine : MonoBehaviour
{
    private int count = 0;

    // Use this for initialization
    IEnumerator Start ()
    {
        Debug.Log("----------Start----------");
        enabled = false;
        string str = "Hello World";
        yield return StartCoroutine(IEnumeratorMethod(str));
        count += 1;
        StartCoroutine(IEnumeratorMethod(str));

        enabled = true;
        Debug.Log("----------EndStart----------");
    }
    
    // Update is called once per frame
    void Update ()
    {
        Debug.Log("update");
    }


    public IEnumerator IEnumeratorMethod(string str)
    {
        Debug.Log(count);

        Debug.Log("before");
        yield return null;
        Debug.Log("after");
        yield return null;

    }
}

f:id:kandaiwata:20180720114901p:plain するとどうでしょう。 IEnumerator Start()とすると、Start()関数が終わるまでUpdate()が始まりません。

yield return と書いているので StartCoroutineが終わらせるまで帰らせてくれません。 yield return君は変態ですね。

研究とは

自分

工学の人間.ロボティクス. 研究成果を出すのに悩んでいるが,そもそも研究ってなんだっけってなったので思考.

研究とは

Google 検索結果

辞書

とりあえず辞書に聞いてみる.
- 広辞苑第五版
よく調べ考えて真理をきわめること
- ウィキペディア
ある特定の物事について、人間の知識を集めて考察し、実験、観察、調査などを通して調べて、その物事についての事実を深く追求する一連の過程のこと。

う〜ん.納得いかない.研究を分解して分析する

分類

  • 基礎研究
    新たな法則や定理などの「発見」
  • 応用研究
    基礎研究の成果の応用.既存の技術に対して新たな手法の提案など.
  • 開発研究
    企業との連携が多い.ある特定の科学「技術」の創出・改良.装置、製品、システム、工程など

うーん.まだ納得いかない.工学の人間からするとごちゃ混ぜになる.

理工学に限定して

  • 理学
    現象を分析し,関係性を見いだすこと.定理・法則・分類など
  • 工学
    課題を解決するための新しい手段を提案すること.数式・アルゴリズム・システム・機構など
    課題はなんでも良い.ある特定のドメインに対する課題でも,幅広い人類の課題でもなんでも.

なんとなくスッキリ.関係性を見いだすことと,課題を解決する手法を提案することは,水と油ほど違う.

研究にオススメの本

紹介

イシューからはじめよ 研究活動(知的生産活動)をする上で必須の本.イシュー(研究課題)を特定するために便利.
ただし,1つ抜けていることとすれば,課題を特定する前に,研究では大事なことである「自分は何を実現したいか」という手順を挟むこと.

0秒思考 悩まず考えろ.研究やっているとのんびりするけどそうじゃないぜ.

思考・論理・分析 これはどちらかというと理学の世界.現象における関係性を論理的にどう見出して人に伝えるか.
論文を書く上では工学も必要だが,工学は関係性というよりどう創造するかなので少し違った.

総評

3つともマッキンゼー出身者の本.知的生産のプロフェッショナル. しかし,どれも「課題特定」の本.そして,どこを改善すればいいですよ〜〜〜と論理的に説明するための手法. 残念ながら工学に必要な「手法」を提案することは載っていない.

「創造力」「イノベーション」を体系化した本があったら読みたい.

イシューから始めよ (研究課題の特定に絡めて)

まず一番重要なメッセージ.毎日繰り返し言う.

生産性 = アウトプット / (時間×お金)
価値=イシュー度×解の質
悩やむ時間があれば考えろ

良い「イシュー」(課題)とは

1. 本質的な選択肢

  • 大きな分岐点を見つけよう
    • 例)店舗数減 vs. 売上減/店舗 どちらか?
  • 落とし穴
    • 1.1 なんちゃってイシュー
    • 1.2 イシューは動く
      • 「これがイシューだ」と思ったら,そのイシューの主語を確認

2. 深い仮説

2.1 常識を否定
直感に反したものを探す→エキスパートに聞こう
2.2 「新しい構造」で説明する
- 共通性の発見
- 関係性の発見
- グルーピングの発見
- ルールの発見 → 数式とか重力とか

3. 答えを出せる

イシュー特定のための情報収集

1. 一次情報

  • 論文
  • 著者本人にメール
  • 学会などで話す
  • 自分で実装

    2. 基本情報をスキャン

  • 数字
  • 問題意識
    • コレらを知らないとその分野の人との会話が成り立たない」ということを一通りカバー
  • フレームワーク
    • 教科書・書籍・雑誌・レビューに載っている大まかな手法を理解する

      3. 集めすぎない

イシュー特定の5つのアプローチ

1. 変数を削る

【研究】例えば研究の理想像(応用先)がいくつかあるとして,それらに共通する課題をグルーピングする.
ロボットの場合:新しい動作の生成など

2. 視覚化する

問題を絵にする.
想定状況・構造・特徴

3. 最終形からたどる

最後に何が欲しいのか
では,「目指すべき姿」は今,「何がわかれば決められるのか」と更に考える
例)ある特定の遺伝子の変異が50代以降でアルツハイマー病を引き起こす確率を大幅に高める
1. 50代以降で特定の遺伝子の変異を持つ人は,持たない人に比べて大幅にアルツハイマーにかかりやすい
2. その差は50代以前では顕著ではない
という2つを検証しなければいけないイシューとなる. このように見極めなければならないイシューを再集計から逆算的に考える

4. So What?を繰り返す

地球温暖化は間違い」とイシューを設定しても何を間違いとしているのかが曖昧.
答え出せない. 【研究】ロボットは汎用的な動作を獲得することはできない
So what is 汎用的・・・?which robot?

5. 極端な事例を考える

変数が多い場合は,どれかを極端な値に振ってみるとどの要素の動きが鍵になるのかが見えてくる.

イシュー分析

イシュー分解する

基本姿勢:MECEに分解せよ

新規事業コンセプトを考える場合:
- Where: どのような領域を狙うか
- What: 具体的にどのような勝ちパターンを築くべきか
- How: 具体的な取り組みをどのように実現していくか
研究の場合(脳科学神経):
- 生理学的(機能)
- 解剖学的(形態)
- 分子細胞生物学的(仕組み)

型がない場合

「最後に欲しいもの」から逆算する (工学の場合この手法が一番一般的ではないか)
例えば,ロボットを自動化しなければならない場合

なぜ分解すると嬉しいか
1. 課題の全体像が見やすい
2. サビイシューのうち優先順位の高いものが見えやすくなる

Theta V の Client Mode設定を間違えてしまってハマった話

モチベーション

Theta VのイメージをRouter経由でPCで接続し、他の機器へ送りたい。 theta_router_pc.png

そこで、以下を参考にClient Modeの設定を変更しようとした。
WiFiのsecurityとpasswordを空にしたかったので、
空のstringでHTTP Post送ったらThetaがどこのWiFiにもアクセスできなくてハマった。
image.png

サポートデスクに連絡したら以下の通りリセットを推奨されましたが、 上手くいきませんでした。

■TEHTA V本体のリセット

THETA V本体が「電源オフ」の状態で、電源ボタンと
無線ボタンを同時に長押し(6秒以上)します。

※通常、ボタンを同時に長押している間に状態ランプ
  (シャッターボタンの上のランプ)が点滅し、点滅が
  終わってランプが消灯するとリセット完了となりま
  す。

■THETA V無線機能のリセット

THETA V本体が「電源オン」の状態で、無線ボタンを
長押し(6秒以上)します。カメラの電源が自動的にな
ってリセット完了となります。

USBを使ってMTP接続

APIの発見

THETAにはWiFiのほかにもUSBのAPIが用意されています。
USB Reference · v2 · API & SDK | RICOH THETA Developers

USB経由でコマンド送ればいいんだなーーーと思ったんですけど、
どうやるんだと???

ライブラリを作っている人発見

しっかり作ってくれている人がいました。

qiita.com github.com

早速試していきます

1. まずはダウンロード

git clone git@github.com:kon0524/WpdMtp.git

2. Visual Studio 2017で開く

WpdMtpLib.slnを開きます Testプロジェクトを「スタートアッププロジェクトに設定」するのを忘れないでください f:id:kandaiwata:20180722163801p:plain

Testプロジェクトの中のProgram.csを変えていきます。

2.1 デバイスの名前を自分のThetaに変更する

MtpResponse res;
MtpCommand command = new MtpCommand();

// 接続されているデバイスIDを取得する
string[] deviceIds = command.GetDeviceIds();
if (deviceIds.Length == 0) { return; }

// RICOH THETA V デバイスを取得する
string targetDeviceId = String.Empty;
foreach (string deviceId in deviceIds)
{
    Console.WriteLine(command.GetDeviceFriendlyName(deviceId));
    if ("RICOH THETA V".Equals(command.GetDeviceFriendlyName(deviceId)))
    {
        targetDeviceId = deviceId;
        break;
    }

2.2 デバイス情報(deviceInfo)の上手くいくか試してみる。

メイン文にいろいろ書いてありますが、とりあえずDeviceInfoだけ取得してみる。
DeviceInfo以外のcommand.Executeはすべて消す。

            // DeviceInfo
            res = command.Execute(MtpOperationCode.GetDeviceInfo, null, null);
            DeviceInfo deviceInfo = new DeviceInfo(res.Data);
            Console.WriteLine(deviceInfo.Manufacturer);

コンソールが最後閉じてしまうので、キーが押されるまで閉じないようにする

            Console.WriteLine();
            Console.WriteLine("Press any key to continue.");
            Console.ReadKey();

            // デバイスよさようなら
            command.Close();

実行するとTheta Vの情報が取れます。

2.3 DeviceInfoに見習ってAcccessPointを取得するExecute Commandを書いていきます。

            res = command.Execute(MtpOperationCode.MtpOperationCode, null, null);
            uint[] accessPointHandles = Utils.GetUIntArray(res.Data);

この時MtpOperationCodeMtpOperationCodeはないので追加していきます。
他のAPIのついでに追加してしまいましょう。

namespace WpdMtpLib
{
    /// <summary>
    /// MTPオペレーションコード(Thetaでサポートしている値のみ)
    /// </summary>
    public enum MtpOperationCode : ushort
    {
        GetDeviceInfo           = 0x1001,
        OpenSession,
        CloseSession,
        GetStorageIDs,
        GetStorageInfo,
        GetNumObjects,
        GetObjectHandles,
        GetObjectInfo,
        GetObject,
        GetThumb,
        DeleteObject,
        InitiateCapture         = 0x100E,
        GetDevicePropDesc       = 0x1014,
        GetDevicePropValue,
        SetDevicePropValue,
        TerminateOpenCapture    = 0x1018,
        GetPartialObject        = 0x101B,
        InitiateOpenCapture,
        StopSelfTimer           = 0x99A2,
        GetAccessPointHandles   = 0x99A3,
        GetAccessPointInfo      = 0x99A4,
        SetAccessPoint          = 0x99A5,
        DeleteAccessPoint       = 0x99A6,
        SetAccessPointPassword  = 0x99AD
    }
}

OperationCodeは分かったのでGetAccessPointInfoが何をする子なのか教えてあげます。
MtpOperation.csファイルにデータを書き込むのか読み込むのかを記述します。

        private static Dictionary<MtpOperationCode, DataPhase> OperationCode2DataPhase
            = new Dictionary<MtpOperationCode, DataPhase>()
            {
                // データフェーズのないオペレーション
                {MtpOperationCode.OpenSession,          DataPhase.NoDataPhase},
                {MtpOperationCode.CloseSession,         DataPhase.NoDataPhase},
                {MtpOperationCode.GetNumObjects,        DataPhase.NoDataPhase},
                {MtpOperationCode.DeleteObject,         DataPhase.NoDataPhase},
                {MtpOperationCode.InitiateCapture,      DataPhase.NoDataPhase},
                {MtpOperationCode.TerminateOpenCapture, DataPhase.NoDataPhase},
                {MtpOperationCode.InitiateOpenCapture,  DataPhase.NoDataPhase},
                {MtpOperationCode.StopSelfTimer,        DataPhase.NoDataPhase},
                {MtpOperationCode.DeleteAccessPoint,    DataPhase.NoDataPhase},

                // R->Iのデータフェーズがあるオペレーション
                {MtpOperationCode.GetDeviceInfo,            DataPhase.DataReadPhase},
                {MtpOperationCode.GetStorageIDs,            DataPhase.DataReadPhase},
                {MtpOperationCode.GetStorageInfo,           DataPhase.DataReadPhase},
                {MtpOperationCode.GetObjectHandles,         DataPhase.DataReadPhase},
                {MtpOperationCode.GetObjectInfo,            DataPhase.DataReadPhase},
                {MtpOperationCode.GetObject,                DataPhase.DataReadPhase},
                {MtpOperationCode.GetThumb,                 DataPhase.DataReadPhase},
                {MtpOperationCode.GetDevicePropDesc,        DataPhase.DataReadPhase},
                {MtpOperationCode.GetDevicePropValue,       DataPhase.DataReadPhase},
                {MtpOperationCode.GetPartialObject,         DataPhase.DataReadPhase},
                {MtpOperationCode.GetAccessPointHandles,    DataPhase.DataReadPhase},
                {MtpOperationCode.GetAccessPointInfo,       DataPhase.DataReadPhase},
                // I->Rのデータフェーズがあるオペレーション
                {MtpOperationCode.SetDevicePropValue,       DataPhase.DataWritePhase},
                {MtpOperationCode.SetAccessPoint,           DataPhase.DataWritePhase},
                {MtpOperationCode.SetAccessPointPassword,   DataPhase.DataWritePhase}
            };

2.4 ハンドラーからAccessPointInfoを取得する

最終的にこうなります。

            res = command.Execute(MtpOperationCode.GetAccessPointHandles, null, null);
            uint[] accessPointHandles = Utils.GetUIntArray(res.Data);
            foreach(uint handle in accessPointHandles)
            {

                res = command.Execute(MtpOperationCode.GetAccessPointInfo, new uint[1] { handle }, null);
                foreach(byte b in res.Data)
                {
                    Console.Write(b);
                    Console.Write(" ");
                }
                AccessPointInfo accessPointInfo = new AccessPointInfo(res.Data);
                Console.WriteLine("");
                Console.WriteLine(accessPointInfo.SSID);
````
情報を抽出するためには`AccessPointInfo`型を定義しないといけないので、定義します。
新しく`AccessPointInfo.cs`ファイルを作成し
````c#:AccessPointInfo.cs
using System;

namespace WpdMtpLib
{
    public class AccessPointInfo
    {
        public string   SSID                { get; private set; }
        public ushort   SSIDStealth         { get; private set; }
        public string   Security            { get; private set; }
        public ushort   ConnectionPriority  { get; private set; }
        public ushort   IpAddressAllocation { get; private set; }
        public uint     IPAddress           { get; private set; }
        public uint     SubnetMask          { get; private set; }
        public uint     DefaultGateway      { get; private set; }


        public AccessPointInfo(byte[] data)
        {
            int pos = 0;
            SSID                = Utils.GetString(data, ref pos);
            SSIDStealth         = BitConverter.ToUInt16(data, pos); pos += 2;
            Security            = Utils.GetString(data, ref pos);
            ConnectionPriority  = BitConverter.ToUInt16(data, pos); pos += 2;
            IpAddressAllocation = BitConverter.ToUInt16(data, pos); pos += 2;
            IPAddress           = BitConverter.ToUInt32(data, pos); pos += 4;
            SubnetMask          = BitConverter.ToUInt32(data, pos); pos += 4;
            DefaultGateway      = BitConverter.ToUInt32(data, pos);
        }
    }
}

2.5 最後に消したいAccessPointを削除します。

                res = command.Execute(MtpOperationCode.DeleteAccessPoint, new uint[1] { handle }, null);

実行

Ctrl + F5で実行して消します。

最終的なProgram.csのMain文コード

        static void Main(string[] args)
        {
            MtpResponse res;
            MtpCommand command = new MtpCommand();

            // 接続されているデバイスIDを取得する
            string[] deviceIds = command.GetDeviceIds();
            if (deviceIds.Length == 0) { return; }

            // RICOH THETA V デバイスを取得する
            string targetDeviceId = String.Empty;
            foreach (string deviceId in deviceIds)
            {
                Console.WriteLine(command.GetDeviceFriendlyName(deviceId));
                if ("RICOH THETA V".Equals(command.GetDeviceFriendlyName(deviceId)))
                {
                    targetDeviceId = deviceId;
                    break;
                }
            }
            if (targetDeviceId.Length == 0) { return; }
            command.Open(targetDeviceId);

            // イベントを受け取れるようにする
            command.MtpEvent += MtpEventListener;

            
            // DeviceInfo
            res = command.Execute(MtpOperationCode.GetDeviceInfo, null, null);
            DeviceInfo deviceInfo = new DeviceInfo(res.Data);
            Console.WriteLine(deviceInfo.Manufacturer);

            res = command.Execute(MtpOperationCode.GetAccessPointHandles, null, null);
            uint[] accessPointHandles = Utils.GetUIntArray(res.Data);
            foreach(uint handle in accessPointHandles)
            {

                res = command.Execute(MtpOperationCode.GetAccessPointInfo, new uint[1] { handle }, null);
                foreach(byte b in res.Data)
                {
                    Console.Write(b);
                    Console.Write(" ");
                }
                AccessPointInfo accessPointInfo = new AccessPointInfo(res.Data);
                Console.WriteLine("");
                Console.WriteLine(accessPointInfo.SSID);

                res = command.Execute(MtpOperationCode.DeleteAccessPoint, new uint[1] { handle }, null);
            }

            Console.WriteLine();
            Console.WriteLine("Press any key to continue.");
            Console.ReadKey();

            // デバイスよさようなら
            command.Close();
        }

YOLO (You Only Look Once)を試してみた

YOLOずっと動かしたかった!!!

pythonの環境構築はやり直してひじょ〜〜〜〜〜〜〜にスムーズに行くので
YOLOを試してみることにしました.
Pythonってこんなに楽だったんだ!!!

参考文献: YOLOv2のリアルタイム物体検出をTensorFlowとPythonで実装する方法 | AI coordinator

準備

pip install --upgrade opencv-python
pip install --upgrade tensorflow

YOLOは直接開発元のdarknetのものを使わずにTensorflowに書き換えたdarflowを使います.
pythonでかけます.

git clone https://github.com/thtrieu/darkflow.git
cd darkflow
python setup.py build_ext --inplace

とりあえずサンプル動かさせて頂きます

まずはサンプル画像から

学習の重みをダウンロードしてきます.darkflow/以下に配置
https://drive.google.com/drive/folders/0B1tW_VtY7onidEwyQ2FtQVplWEU

サンプルプログラム

from darkflow.net.build import TFNet
import cv2

options = {"model": "cfg/yolo.cfg", "load": "yolo.weights", "threshold": 0.1}

tfnet = TFNet(options)

imgcv = cv2.imread("./sample_img/sample_dog.jpg")
result = tfnet.return_predict(imgcv)
print(result)

実行すると以下の結果が得られました.

[{'label': 'bicycle', 'confidence': 0.8448341, 'topleft': {'x': 81, 'y': 114}, 'bottomright': {'x': 553, 'y': 466}}, {'label': 'truck', 'confidence': 0.79511166, 'topleft': {'x': 462, 'y': 81}, 'bottomright': {'x': 693, 'y': 167}}, {'label': 'motorbike', 'confidence': 0.27550778, 'topleft': {'x': 59, 'y': 76}, 'bottomright': {'x': 114, 'y': 124}}, {'label': 'cat', 'confidence': 0.12677637, 'topleft': {'x': 139, 'y': 197}, 'bottomright': {'x': 314, 'y': 551}}, {'label': 'dog', 'confidence': 0.7696115, 'topleft': {'x': 136, 'y': 214}, 'bottomright': {'x': 322, 'y': 539}}]

次にウェブカメラです.

rom darkflow.net.build import TFNet
import cv2
import numpy as np
 
options = {"model": "cfg/yolo.cfg", "load": "bin/yolo.weights", "threshold": 0.1}
tfnet = TFNet(options)
 
# カメラの起動
cap = cv2.VideoCapture(0)
 
class_names = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 
              'bus', 'car', 'cat', 'chair', 'cow', 'diningtable', 
              'dog', 'horse', 'motorbike', 'person', 'pottedplant',
              'sheep', 'sofa', 'train', 'tvmonitor']
 
num_classes = len(class_names)
class_colors = []
for i in range(0, num_classes):
    hue = 255*i/num_classes
    col = np.zeros((1,1,3)).astype("uint8")
    col[0][0][0] = hue
    col[0][0][1] = 128
    col[0][0][2] = 255
    cvcol = cv2.cvtColor(col, cv2.COLOR_HSV2BGR)
    col = (int(cvcol[0][0][0]), int(cvcol[0][0][1]), int(cvcol[0][0][2]))
    class_colors.append(col) 
    
def main():
    
    while(True):
        
        # 動画ストリームからフレームを取得
        ret, frame = cap.read()
        result = tfnet.return_predict(frame)
 
        for item in result:
            tlx = item['topleft']['x']
            tly = item['topleft']['y']
            brx = item['bottomright']['x']
            bry = item['bottomright']['y']
            label = item['label']
            conf = item['confidence']
 
            if conf > 0.6:
                
                for i in class_names:
                    if label == i:
                        class_num = class_names.index(i)
                        break
                
                #枠の作成
                cv2.rectangle(frame, (tlx, tly), (brx, bry), class_colors[class_num], 2)
                
                #ラベルの作成
                text = label + " " + ('%.2f' % conf)  
                cv2.rectangle(frame, (tlx, tly - 15), (tlx + 100, tly + 5), class_colors[class_num], -1)
                cv2.putText(frame, text, (tlx, tly), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1)
 
        # 表示
        cv2.imshow("Show FLAME Image", frame) 
 
        # escを押したら終了。
        k = cv2.waitKey(10);
        if k == ord('q'):  break;
 
    cap.release()
    cv2.destroyAllWindows()
    
if __name__ == '__main__':
    main()

f:id:kandaiwata:20180716115818p:plain

なんとか人として認識してくれました!!嬉しい