空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

AtCoderチャレンジまとめ(0)

https://secure-dcdn.cdn.nimg.jp/nicochannel/material/design/2504203/logo2.png

やりたいこと

C++に慣れつつアルゴリズムの知識を上げたい。

そんなわけでAtCoderにチャレンジ ! の前の準備笑

教科書

けんちょんさんわかりやすい記事ありがとうございますm( )m

A問題の学び

  • 問題分をよく読んで出力形式には注意すること。ex: cout << a << " " << b << endl;の" "を書き忘れる etc ...。

  • (プロコンの場合)変数名はシンプル。タイピング速度重視。

  • 一行でかけるときはまとめる。 ex: if (c % 2 == 0) cout << "Even" << endl;

  • stringを受けて文字にアクセスするときはこう↓

string s;
cin >> s;
int counter = 0;
if (s[0] == '1') ++counter;

・ ++i の作用は式の値として、i + 1 の値を返す事、副作用は i に i + 1 の結果が代入される。

・ i++ の作用は式の値として、i の値を返す事、副作用はその後 i に i + 1 の結果が代入される。

B問題の学び

#include <algorithm>
int N; 
int a[100];

// a[0:N] を大きい順にソート
sort(a, a + N, greater<int>());
    #include <set>
    ...
    set<int> values; // insert するときに重複を取り除いてくれます
    for (int i = 0; i < N; ++i) {
        values.insert(d[i]); // 挿入します
    }
  • 最大最小もよく使う。
const int lower = max(A,C);
const int upper = min(B,D);
  • 計算の工夫として、N!のSで割った余りを求めたい時は、オーバーフローを防ぐため、N! % Sより、(N%S) * ((N-1)%S)* ・・・としたりする。

  • a以上b以下の整数のうち条件を満たすものの個数を求める問題ではf(n) := 0以上n以下の整数のうち条件を満たすものの個数のように関数定義するとf(b)-f(a-1)で求めることができる。

C問題の学び

const int dx[8]={1,0,-1,0,1,-1,-1,1};
const int dy[8]={0,1,0,-1,1,1,-1,-1};

感想

めっちゃ楽しい :D

今後の勉強予定

温湿度・気圧センサモジュールを動かしてみる

http://akizukidenshi.com/img/goods/C/K-09421.jpg

やりたいこと

BOSCH BME280センサを動かしてみる

購入先

教科書

準備

  1. ブレッドボード

  2. ジャンパピン

  3. プルアップ用抵抗(10kΩ)x 2

  4. Arduino Nano (Uno)

  5. BME280

配線の仕方

  • VCC(3.3Vへ)
  • GND(GNDへ)
  • SCL(SCK) <- プルアップ抵抗10kΩをはさむ
  • SDA(SDI) <- プルアップ抵抗10kΩをはさむ
  • CSB(3.3Vへ)
  • SDO(GNDへ)

http://trac.switch-science.com/raw-attachment/wiki/BME280/s-BME280_12.jpg

f:id:robonchu:20181210210434p:plain

https://i.stack.imgur.com/GB2hw.jpg

書き込むコード

BME280 – スイッチサイエンスに記載のコードBME280_I2C.inoをそのまま使用

結果

f:id:robonchu:20181210211113p:plain

所感

だいたいあってる。安いし、そこそこの値をとるにはバッチリだと思う。

さすがBOSCH :)

参考

ブログ

ライブラリ

サーモカメラOWLIFTを動かしてみる

http://www.infinitegra.co.jp/owlift/product2.jpg

http://www.infinitegra.co.jp/owlift/sample_photo1.jpg

やりたいこと

サーモカメラOWLIFT Type-AをLinuxで動かす

事前の環境設定

python3

python3のライブラリのみなので、python3環境を用意しておく

既存環境を汚したくない場合、例えばvirtualenvを利用する

$ sudo apt-get install virtualenv
$ virtualenv -p python3 "my_env"
$ source my_env/bin/activate

抜けたいときは

$ deactivate

参考: venv: Python 仮想環境管理 - Qiita

opencv

$ pip install opencv-python

OWLIFTライブラリのインストール

python library

以下からwhlファイルをダウンロード

以下コマンドでインストール

$ pip3 install owlift-xxx.whl

その他

参考: インフィニテグラ株式会社 | 小型サーマルカメラ OWLIFT

APIドキュメント

サンプルコード

以下からダウンロード

実行結果

USBでカメラをPCを繋いで以下を実行

$ python preview_basic.py

暖房を入れた時のエアコンの吹き出し口が熱を持っていることがわかる↓

f:id:robonchu:20181208143230p:plain

蛍光灯に向けるとこんな感じ↓

f:id:robonchu:20181208143706p:plain

所感

バイスやセンサごとに特性があって面白い♪

WideResNetのお勉強

https://image.slidesharecdn.com/presentationslideshare-170919153832/95/deep-learningchainer-83-638.jpg?cb=1507530330

やりたいこと

Wideなネットワークについて理解を深めたい

内容理解

教科書: Residual Network(ResNet)の理解とチューニングのベストプラクティス - DeepAge

スキップコネクションでDeepなネットワークの学習が可能に。

https://deepage.net/img/resnet/bottleneck_architecture.jpg

BatchNormは下図の左を用いるとよい。

https://deepage.net/img/resnet/bn_pos.jpg

activationの位置に関して下図の右の方が良い結果に。

https://deepage.net/img/resnet/post_vs_pre.jpg

WideResNetはこのResNetのフィルタ数を増やすことで、GPUを活用し、浅いネットワークで同等の表現力を持つように改良したもの。kが広さの係数。

https://deepage.net/img/resnet/wide_param.jpg

Dropoutの入れ方。

https://deepage.net/img/resnet/wide_resnet.jpg

実装参考

わかりやすいブログや資料

https://image.slidesharecdn.com/resnetvariant-170221133435/95/convnetresnet-11-638.jpg?cb=1487684306

https://image.slidesharecdn.com/presentationslideshare-170919153832/95/deep-learningchainer-83-638.jpg?cb=1507530330

Global Average Pooling (GAP)

教科書: Global Average Pooling(GAP)を理解してみる - Qiita

通常の全結合

https://camo.qiitausercontent.com/c41fe18f1d26e1a864cb047d3b3c5f4896c3c996/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3133303737312f66343965666537352d306139662d313433642d383633342d3962376330663561343061332e706e67

GAP

https://camo.qiitausercontent.com/f1b0f5ebf5e574f6eecd31a9e8066bb81b1d35d8/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3133303737312f38386431313561332d663463342d663032312d653062342d6632633737616135326266662e706e67

実装参考

参考ブログ

所感

計算資源や学習対象によって適切なネットワークを選択できるようになりたい!

MobileNetV2のお勉強

f:id:robonchu:20181124123412j:plain

やりたいこと

計算処理が軽いDNNの構築。低スペックのPCでもガンガン認識を回したい。

論文

  1. https://arxiv.org/abs/1704.04861

  2. [1801.04381] MobileNetV2: Inverted Residuals and Linear Bottlenecks

MobileNetsの理解

通常のCNNではチャンネル間の特徴・チャンネル内の特徴(画像内の特徴)をフィルターによってまとめて考えるのに対し、MobileNetsではそれらをdepthwiseとpointwiseの畳み込みに分離し、表現しパラメータを削減している。

また、処理速度と精度を調整するためのwidth multiplierとresolution multiplierというパラメータもうまく設計されている。

https://github.com/Zehaos/MobileNet/raw/master/figures/dwl_pwl.png

https://qiita-image-store.s3.amazonaws.com/0/108729/a461dde5-cf55-4e9b-aea0-f58082335001.png

参考: MobileNets: CNNのサイズ・計算コストの削減手法_翻訳・要約 - MUSCLE PROGRAMMER's BLOG

通常のCNN

https://qiita-image-store.s3.amazonaws.com/0/108729/5e4bb20f-127e-4d9e-10fb-110ba4694360.png

Depthwise Separable Convolution

https://qiita-image-store.s3.amazonaws.com/0/108729/72ca6fe6-f6a0-7dd3-3b24-7aa3aa185ab6.png

実装(TBD)

書き次第掲載予定。Tensorflowで書いてみようかな。

https://raw.githubusercontent.com/joshua19881228/my_blogs/master/Computer_Vision/Reading_Note/figures/Reading_Note_20170719_MobileNet_1.png

V2の理解(TBD)

参考スライド

参考ブログ

参考実装

Tensorflow

Pytorch

所感

軽量なDNNの工夫おもしろい。

低スペックPCで認識を回すために引き続きキャッチアップしよう。

CMakeのお勉強(2)

やりたいこと

cmakeについて調べることが多いし、理解も浅いので、理解を深める

教科書

CMake チュートリアル — Cmake-Tutorial

CMake チュートリアル

チュートリアルでは,一般的なビルドシステムの問題点のうち,CMake を利用することで解決できる事項について段階的に述べていきます

Step1: 最小構成

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cpp)

tutorial.cpp

// 1つの数値の平方根を計算する単純なプログラム
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = sqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}

Step2: ライブラリの追加

add_library(MathFunctions mysqrt.cpp)

新しいライブラリを利用するには,ライブラリをビルドするにように,トップレベルの CMakeLists ファイルに add_subdirectory の呼び出しを追加します. また,MathFunctions/mysqrt.h ヘッダファイルにある関数の宣言を見つけられるように,別のインクルードディレクトリも追加します. 最後の修正は,新しいライブラリを実行ファイルに追加することです. トップレベルの CMakeLists の最後の数行は,次のようになります:

include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)

# 実行ファイルを追加
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial MathFunctions)

ライブラリの作成をオプション形式にするには

以下のように記述する

# 自前の演算関数を使うべきか?
option (USE_MYMATH
        "Use tutorial provided math implementation" ON)

# MathFunctions ライブラリを追加するか?
#
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
  add_subdirectory (MathFunctions)
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)

# 実行ファイルを追加
add_executable (Tutorial tutorial.cxx)
target_link_libraries (Tutorial  ${EXTRA_LIBS})

MathFUnctions をコンパイルして利用するかどうかを決定するために,USE_MYMATHの設定を利用します.

Step3: インストール

インストール規則は,実に簡単です. MathFunctions ライブラリの場合,次の2行を,MathFunctions の CMakeLists ファイルに追加することで, インストールされるライブラリとヘッダファイルを設定します

install (TARGETS MathFunctions DESTINATION bin)
install (FILES MathFunctions.h DESTINATION include)

Step5: ファイルを生成するファイルと,生成されたファイルの追加

生成されたソースファイルをアプリケーションのビルドプロセスに組み込む方法について述べます

// 1つの数値の平方根を計算する単純なプログラム
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main (int argc, char *argv[])
{
  int i;
  double result;

  // 必要な引数を指定するように
  if (argc < 2)
    {
    return 1;
    }

  // 出力ファイルを開く
  FILE *fout = fopen(argv[1],"w");
  if (!fout)
    {
    return 1;
    }

  // 平方根テーブルを持ったソースコードを作成
  fprintf(fout,"double sqrtTable[] = {\n");
  for (i = 0; i < 10; ++i)
    {
    result = sqrt(static_cast<double>(i));
    fprintf(fout,"%g,\n",result);
    }

  // テーブルの最後を0にする
  fprintf(fout,"0};\n");
  fclose(fout);
  return 0;
}

MakeTable 実行ファイルをビルドするために, 適切なコマンドを MathFunctions の CMakeLists ファイルに追加し,それをビルドプロセスの一部としてを実行します.

# まず,テーブルを生成するための実行ファイルを追加
add_executable(MakeTable MakeTable.cxx)

# ソースコードを生成するためのコマンドを追加
add_custom_command (
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
  DEPENDS MakeTable
  )

# インクルードファイルの探索パスに,
# バイナリツリーディレクトリを追加
include_directories( ${CMAKE_CURRENT_BINARY_DIR} )

# メインライブラリを追加
add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h  )

参考:

所感

実際に書いてみないと理解しづらいところも多い。

書きながら勉強してみよう。

CMakeのお勉強(1)

やりたいこと

cmakeについて調べることが多いし、理解も浅いので、理解を深める

教科書

ja/catkin/CMakeLists.txt - ROS Wiki

CMakeLists.txtとは

ファイルCMakeLists.txtは、ソフトウエアパッケージをビルドするためのCMakeビルドシステムへのインプットです。

フォーマット(順序も大事)

  1. 必要な CMake Versionの指定 (cmake_minimum_required)

  2. Package Name (project())

  3. ビルドに必要な他の CMake/Catkin packages を見つける (find_package())

  4. Message/Service/Action の生成 (add_message_files(), add_service_files(), add_action_files())

  5. message/service/action generation の呼び出し (generate_messages())

  6. パッケージのビルドに必要な情報の指定 (catkin_package())

  7. ライブラリや実行ファイルのビルド (add_library()/add_executable()/target_link_libraries())

  8. テストコードのビルド (catkin_add_gtest())

  9. Install ルール (install())

CMake Version

cmake_minimum_required(VERSION 2.8.3)

Package name

project(robot_brain)

Tips: CMakeスクリプトの中で、どこで必要であっても ${PROJECT_NAME} 変数を使って、後からこのプロジェクト名を参照出来ます。

CMake Packages

find_package(catkin REQUIRED COMPONENTS nodelet)

Tips:

  • find_packageにはビルドに必要なコンポーネントだけを指定してください。ランタイムで依存するパッケージを指定するべきでありません。

  • catkin_INCLUDE_DIRSはcatkinのincludeパスだけではなく、nodeletのincludeパスも含みます

参考: CMakeを使ってみた (7) find_packageとpkg_check_modulesによるライブラリ探索 - wagavulin's blog

find_package() は何をしているのか?

find_packageを通してCMakeがパッケージを見つけたら、そのパッケージについての情報を与えるいくつかのCMake環境変数が生成されます。

↓以下環境変数

  1. _FOUND - ライブラリが見つかったかどうか。見つかればtrueをセット、見つからなければ出力されない

  2. INCLUDE_DIRS or INCLUDES - パッケージによってエクスポートされたインクルードパス

  3. LIBRARIES or LIBS - パッケージによってエクスポートされたライブラリ

  4. _DEFINITIONS - 追加のコンパイルフラグ

catkin_package()

catkin_package()はcatkinで提供されたCMakeマクロです。pkg-configとCMakeファイルを生成するのに必要なcatkin固有の情報をビルドシステムに伝えるために必要です。

ex

catkin_package(
   INCLUDE_DIRS include
   LIBRARIES ${PROJECT_NAME}
   CATKIN_DEPENDS roscpp nodelet
   DEPENDS eigen opencv)
  1. INCLUDE_DIRS - このパッケージのためのエクスポートされるinclude パス (i.e. cflags)

  2. LIBRARIES - プロジェクトからエクスポートされるライブラリ

  3. CATKIN_DEPENDS - このプロジェクトが依存している他のcatkinプロジェクト

  4. DEPENDS - このプロジェクトが依存している非catkin CMakeのプロジェクト

  5. CFG_EXTRAS - 追加の設定オプション

ビルドターゲットの指定

ビルドターゲットの指定方法にはいろいろありますが、通常は以下の2つのどちらかです:

  1. Executable Target - 実行可能プログラム

  2. Library Target - 実行可能なターゲットがビルド時または実行時に使用するライブラリ

Include パスと Library パス

ターゲットを指定する前に、ターゲットのためのリソース、特にヘッダファイルおよびライブラリをどこで見つけることができるのかを指定する必要があります。

  1. Include Paths - (一般的にC/C++の)コードをビルドするためのヘッダファイルがどこで見つけられるか

  2. Library Paths - 実行可能なターゲットをビルドするのに必要なライブラリがどこにあるか?

  3. include_directories(, , ..., )

  4. link_directories(, , ..., )

include_directories()

include_directoriesへの引数は、find_package呼び出しによって生成される*_INCLUDE_DIRS変数と、インクルードする必要がある

include_directories(include ${Boost_INCLUDE_DIRS} ${catkin_INCLUDE_DIRS})

一番最初の引数 "include" は、パッケージ内のinclude/ディレクトリがパスの一部でもあることを示しています。

link_directories()

CMakelink_directories()機能は、追加のライブラリパスを追加するために使われることができます。

link_directores(~/my_libs)

例:

  • LINK_DIRECTORIES( ${LINK_DIRECTORIES} /absPath/libtourtre/)

推奨:

  • FIND_LIBRARY(TOURTRE_LIBRARY tourtre /absPath/libtourtre)
  • TARGET_LINK_LIBRARIES(testOVAS ${TOURTRE_LIBRARY})
実行ファイルのターゲット

ビルドすべき実行可能なターゲットを指定するために、CMake関数のadd_executable()を使わなければなりません。

add_executable(myProgram src/main.cpp src/some_file.cpp src/another_file.cpp)

これは、3つのソースファイル src/main.cpp、src/some_file.cppとsrc/another_file.cppからビルドされるmyProgramと呼ばれる実行可能なターゲットをビルドします。

ライブラリターゲット

CMake関数add_library()は、ビルドする際のライブラリを指定するために使います。デフォルトで、catkinは共有ライブラリをビルドします。

add_library(${PROJECT_NAME} ${${PROJECT_NAME}_SRCS})
target_link_libraries

実行可能なターゲットがどのライブラリにリンクするかを指定するために、target_link_libraries_functionを使ってください。これは一般にadd_executable()の呼びだしの後に実行されます。

add_executable(foo src/foo.cpp)
add_library(moo src/moo.cpp)
target_link_libraries(foo moo)  -- これはfooを libmoo.soにリンクする

Tips: リンクすべきディレクトリ情報がfind_package()経由で自動的に取り込まれるので、ほとんどの使用事例においてlink_directories()を使う必要がないことに注意してください。

インストール可能なターゲットを指定する

自分のコードの"make install" を実行できるようにしたいなら、ターゲットがどこに収まるべきかを指定する必要があります.

これはCMake のinstall() 関数を使い、引数を伴って行われます。

  1. TARGETS - どのターゲットをインストールするか

  2. ARCHIVE DESTINATION - 静的ライブラリとDLL (Windows) .lib のスタブ

  3. LIBRARY DESTINATION - 非DLL 共有ライブラリとモジュール

  4. RUNTIME DESTINATION - 実行可能ターゲットと DLL (Windows) 形式の共有ライブラリ

install(TARGETS ${PROJECT_NAME}
  ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
  RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
ヘッダファイルのインストール

ヘッダファイルも"include"フォルダにインストールされ、これはしばしばフォルダ全体のファイルのインストールによって行われます(ファイル名パターンで部分的にフィルタされ、SVNのサブフォルダ群を除きます)。これは以下の様なインストール規則によって行われます:

install(DIRECTORY include/${PROJECT_NAME}/
  DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)
install(DIRECTORY include/
  DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION}
  PATTERN ".svn" EXCLUDE
)
roslaunch ファイルやその他のリソースのインストール

launchファイルといったその他のリソースは、${CATKIN_PACKAGE_SHARE_DESTINATIONにインストールされます

install(DIRECTORY launch/
  DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
  PATTERN ".svn" EXCLUDE)

所感

まだひとつひとつのコマンドが実行された時に内部でどのようにつながったり動いているのかが理解できていない。

引き続き学ぶべし