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

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

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)

所感

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

引き続き学ぶべし

telloの画像でtiny yolo and v3 を試してみる

f:id:robonchu:20181009211731p:plain

やりたいこと

安い割に性能がなかなか良い中国製 Toy Drone "tello"のカメラを使って、yoloをまわす。

今回はpytorchでやってみる。

Shanghai Maker Carnivalのための準備 !

pytorchのインストール

python2.7のCPUバージョン

  1. pip install http://download.pytorch.org/whl/cpu/torch-0.4.1-cp27-cp27mu-linux_x86_64.whl

  2. pip install torchvision

pipのエラーが出たら以下で対処。いつのまにこんなことに。。。

python2.7 GPUバージョン(CUDA 8.x)

  1. pip install http://download.pytorch.org/whl/cu80/torch-0.4.1-cp27-cp27mu-linux_x86_64.whl

  2. pip install torchvision

CUDA8.0 and cuDNN6 のインストール

Telloをpythonで操作するための設定

ffmpegのインストール

  1. git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

  2. ./configure --disable-static --enable-shared --disable-x86asm

  3. make -j 4

  4. sudo make install

PyAvのインストール

  1. sudo pip install av==0.5.2

  2. パスの設定

    1. export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:/usr/local/lib:$LD_LIBRARY_PATH

Tellopy

以下に従ってイントール

  1. pip install tellopy

画像の取得や処理は以下のスクリプトを実行

  1. WIFIでtelloとPCをつなぐ

  2. cd TelloPy/tellopy/examples/

  3. python video_effect.py

処理を早くしたいときは以下の対策

こうするとtelloの画像が取得できる

yolo v2 and 3 by Pytorch

上記を参考に実行。

  1. yolo v2 by web cam

    1. python demo.py cfg/tiny-yolo-voc.cfg tiny-yolo-voc.weights
  2. yolo v3 by image

    1. python detect.py cfg/yolov3.cfg yolov3.weights data/dog.jpg

pytorchのバージョンの問題でエラーが発生。以下で対処。

The actual solution is changing 

conv_model.weight.data.copy_(torch.from_numpy(buf[start:start+num_w])); start = start + num_w

to

conv_model.weight.data.copy_(torch.reshape(torch.from_numpy(buf[start:start+num_w]),(conv_model.weight.shape[0],conv_model.weight.shape[1], conv_model.weight.shape[2],conv_model.weight.shape[3]))); start=start + num_w

tello画像を使ってyoloを回す

GitHub - marvis/pytorch-yolo2: Convert https://pjreddie.com/darknet/yolo/ into pytorch のdemo.pyの入力にGitHub - hanyazou/TelloPy: DJI Tello drone controller python packageのvideo_effect.pyで取得した画像を入れる。

f:id:robonchu:20181009215019j:plain

f:id:robonchu:20181009215151p:plain

所感

明後日から初めての中国。。。

Let's Enjoy !!!

参考

Google Test C++の使い方(初級)

f:id:robonchu:20181007164810p:plain

やりたいこと

C++のテストがしたい。

Google Testがいい感じという噂。

教科書

  1. 入門ガイド — Google Test ドキュメント日本語訳

  2. 超入門編 — Google Mock ドキュメント日本語訳

  3. クックブック — Google Mock ドキュメント日本語訳

  4. 上級ガイド — Google Test ドキュメント日本語訳

入門まとめ

基本的なアサーション

致命的なアサーション 致命的ではないアサーション 検証内容

ASSERT_TRUE(condition); EXPECT_TRUE(condition); condition が true

ASSERT_FALSE(condition); EXPECT_FALSE(condition); condition が false

ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

簡単なテスト

プロダクトコード

int Factorial(int n); // nの階乗を返す

テストコード

// 0 の階乗をテスト
TEST(FactorialTest, HandlesZeroInput) {
  EXPECT_EQ(1, Factorial(0));
}

// 正の数の階乗をテスト
TEST(FactorialTest, HandlesPositiveInput) {
  EXPECT_EQ(1, Factorial(1));
  EXPECT_EQ(2, Factorial(2));
  EXPECT_EQ(6, Factorial(3));
  EXPECT_EQ(40320, Factorial(8));
}

テストフィクスチャ:複数のテストで同じデータ設定を使う

プロダクトコード

template <typename E> // E は要素の型
class Queue {
public:
  Queue();
  void Enqueue(const E& element);
  E* Dequeue(); // queue が空の場合は NULL を返します.
  size_t size() const;
...
};

テストのフィクスチャ

class QueueTest : public ::testing::Test {
 protected:
  virtual void SetUp() {
    q1_.Enqueue(1);
    q2_.Enqueue(2);
    q2_.Enqueue(3);
  }

  // virtual void TearDown() {}

  Queue<int> q0_;
  Queue<int> q1_;
  Queue<int> q2_;
};

このフィクスチャとTEST_F() を利用したテストコード

TEST_F(QueueTest, IsEmptyInitially) {
  EXPECT_EQ(0, q0_.size());
}

TEST_F(QueueTest, DequeueWorks) {
  int* n = q0_.Dequeue();
  EXPECT_EQ(NULL, n);

  n = q1_.Dequeue();
  ASSERT_TRUE(n != NULL);
  EXPECT_EQ(1, *n);
  EXPECT_EQ(0, q1_.size());
  delete n;

  n = q2_.Dequeue();
  ASSERT_TRUE(n != NULL);
  EXPECT_EQ(2, *n);
  EXPECT_EQ(1, q2_.size());
  delete n;
}

テストの呼び出し

テストを定義したら,RUN_ALL_TESTS() でテストを実行できる

#include "this/package/foo.h"
#include "gtest/gtest.h"

namespace {

// テスト対象となるクラス Foo のためのフィクスチャ
class FooTest : public ::testing::Test {
 protected:
  // 以降の関数で中身のないものは自由に削除できます.
  //

  FooTest() {
    // テスト毎に実行される set-up をここに書きます.
  }

  virtual ~FooTest() {
    // テスト毎に実行される,例外を投げない clean-up をここに書きます.
  }

  // コンストラクタとデストラクタでは不十分な場合.
  // 以下のメソッドを定義することができます:

virtual void SetUp() {
  // このコードは,コンストラクタの直後(各テストの直前)
  // に呼び出されます.
}

virtual void TearDown() {
  // このコードは,各テストの直後(デストラクタの直前)
  // に呼び出されます.
}

// ここで宣言されるオブジェクトは,テストケース内の全てのテストで利用できます.
};

// Abc を行う Foo::Bar() メソッドをテストします.
TEST_F(FooTest, MethodBarDoesAbc) {
  const string input_filepath = "this/package/testdata/myinputfile.dat";
  const string output_filepath = "this/package/testdata/myoutputfile.dat";
  Foo f;
  EXPECT_EQ(0, f.Bar(input_filepath, output_filepath));
}

// Xyz を行う Foo をテストします.
TEST_F(FooTest, DoesXyz) {
  // Foo の Xyz を検査
}

}  // namespace

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

Mockまとめ

わからないことがあったとき

基本ステップ

  1. 簡単なマクロを使ってモック化したいインタフェースを記述します.これが,モッククラスの実装に展開されます.

  2. モックオブジェクトを作成し,直感的な構文を利用して Expectation と 動作を規定します.

  3. モックオブジェクトを利用するコードを実行します.Google Mock は,Expectation 違反が起こると即座にそれをキャッチします.

使うための準備

C++ ソースファイル内で, “gtest/gtest.h” と “gmock/gmock.h” を #include するだけで準備は終わり。

モック理解のためのサンプル

class Turtle {
  ...
  virtual ~Turtle() {}
  virtual void PenUp() = 0;
  virtual void PenDown() = 0;
  virtual void Forward(int distance) = 0;
  virtual void Turn(int degrees) = 0;
  virtual void GoTo(int x, int y) = 0;
  virtual int GetX() const = 0;
  virtual int GetY() const = 0;
};

モックの定義

  1. Turtle から MockTurtle クラスを派生させます.

  2. Trutle の仮想関数を調べて,引数の数を数えます.

  3. 派生クラスの public セクションに,MOCK_METHODn();(const メソッドをモック化する場合は, MOCK_CONST_METHODn();)を書きます.ここで n は,引数の数を表しますが,これを数え間違えると,コンパイルエラーで注意されます. 関数のシグネチャを調べて,その関数名をマクロの1番目の引数に,残りを2番目の引数にします.

  4. これを,モック化したい仮想関数全てに対して繰り返します.

MOCK_METHOD0 のように最後の数字は引数の数を指定。

#include "gmock/gmock.h"  // Google Mock はこのヘッダに.
class MockTurtle : public Turtle {
 public:
  ...
  MOCK_METHOD0(PenUp, void());
  MOCK_METHOD0(PenDown, void());
  MOCK_METHOD1(Forward, void(int distance));
  MOCK_METHOD1(Turn, void(int degrees));
  MOCK_METHOD2(GoTo, void(int x, int y));
  MOCK_CONST_METHOD0(GetX, int());
  MOCK_CONST_METHOD0(GetY, int());
};

モックの使い方

  1. モックを制限無く利用できるように,Google Mock の名前をテスト用の名前空間からインポートします

  2. モックオブジェクトを作成します.

  3. その Expectation を設定します

  4. モックを利用したコードを実行します.Google Test のアサーションを利用して結果のチェックを行っても良いでしょう.モックメソッドが期待よりも多く呼び出される,または引数が誤っている,などの場合は,即座にエラーが起こります.

  5. モックがデストラクトされると,その全ての Expectation が満足されたかどうかを Google Mock が自動的に検証します.

#include "path/to/mock-turtle.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::AtLeast;                     // #1

TEST(PainterTest, CanDrawSomething) {
  MockTurtle turtle;                          // #2
  EXPECT_CALL(turtle, PenDown())              // #3
      .Times(AtLeast(1));

  Painter painter(&turtle);                   // #4

  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
}                                             // #5

int main(int argc, char** argv) {
  // 以下の行は,テスト開始前に Google Mock (と Google Test)
  // を初期化するために必ず実行する必要があります.
  ::testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}

Exceptionの作り方

Expectation を設定するために EXPECT_CALL() マクロを使う。

このマクロには2つの引数があり、1番目はモックオブジェクトで,2番目はメソッドと引数。

using ::testing::Return;...
EXPECT_CALL(turtle, GetX())
    .Times(5)
    .WillOnce(Return(100))
    .WillOnce(Return(150))
    .WillRepeatedly(Return(200));

turtle オブジェクトの GetX() メソッドが5回呼ばれ,最初は 100 を返し,次に 150,それ以降は 200 を返す,という動作のテスト。

所感

unittestに似てる。書きながら使えるようになろう~

RPLIDAR A1をROSで動かしてみる

やりたいこと

低価格Lidar RPLIDAR A1を授かったので、ROSで動かしてみる

教科書

実行手順

びっくりするくらいシンプル。素晴らしい。

  1. git clone https://github.com/Slamtec/rplidar_ros.git

  2. catkin_make

  3. source devel/setup.bash

  4. ポートに権限付与

    1. ls -l /dev | grep ttyUSB

    2. sudo chmod 666 /dev/ttyUSB0

  5. roslaunch rplidar_ros view_rplidar.launch

このlaunchを立ち上げると、こんな感じ ↓

f:id:robonchu:20180915091225p:plain

ノードだけ立ち上げるときは

  1. roslaunch rplidar_ros rplidar.launch

出力されているTopicは

  • scan (sensor_msgs/LaserScan) : it publishes scan topic from the laser.

How to install rplidar to your robot

rplidar rotate with clockwise direction . The first range come from the front ( the tail with the line).

f:id:robonchu:20180915091416p:plain

所感

とてもシンプル!ありがたい!!

次はルンバで自律移動にチャレンジ。どのSLAMの手法を使おう!?

gmappingかKarto SLAMがよさげかな。。。

参考 :

GPD pocketにUbuntu16.04 & ROS install

f:id:robonchu:20180912232540p:plain

超小型でなかなかスペックが良い♪

やりたいこと

Windows10が入っているGPDにUbuntu16.04とROSをインストール。

ざっくりまとめ。

Ubuntuインストールのための準備

以下はすべてGPD上で実施

  1. BIOSの変更

    1. 2017/06/28版のZipファイルをGPD Pocket/BIOS - GPD Wikiから取得。2017/06/28版でないとUbuntuは動かないらしい。

    2. Zipを解答し、update_win.batをGPD上で管理者権限で実行。詳細は以下を参考。

    3. msinfoでBIOSバージョンが正しくかわっているか確認。

  2. ISOファイルのダウンロード

    1. 第3版 ubuntu-16.04.1-desktop-amd_0809_2.iso をGPD Pocket/OS/Ubuntu - GPD Wikiから取得
  3. UltraISOのインストール

    1. ダウンロード UltraISO 9.7.1.3519 日本語 – Vessoft
  4. 2017/06/28版のZip内のUbuntu安装说明.pdfGoogle翻訳のファイルから翻訳を利用して翻訳しておく

ISOイメージの作り方

Ubuntu安装说明.pdfを参考。中国語なので、Google翻訳したものを見るとわかりやすい。

  1. ブート用USBをさす。

  2. UltraISOを開き、ファイルを開くからISOファイルを選択、読み込み。

  3. 上部タブのブートを選択し、イメージの書き込みをクリック。

  4. 書き込み設定がUSB-HDD+になっていることを確認し、USBに書き込み実行。

Ubuntuのインストール

  1. ブータブルUSBをさして、再起動し、Fn + F7を複数回打ち込む。

  2. f:id:robonchu:20180912233938p:plainのような画面がでてくるので、UEFIを選択。

  3. Try Ubuntu without installingを選択。

  4. Gpartedでパーティションを作成。ルートとswap。

    1. Ubuntu 16.04 インストール(UEFI) その2 - UEFIのPCにUbuntu 16.04をインストールする(パーティションの作成 〜 ブートローダーの設定) - kledgebを参考
  5. Ubuntu install アイコンを選択。

  6. ドライバを入れる項目はチェック無しで実行。インストールはそれ以外を選択し、上記作成パーティションにインストール。

  7. 終了したら再起動!

画面が90度回転している時

Ubuntuのシステム設定のディスプレイで回転させる。

ROSのインストール

以下の手順をコピペで完了!

これでGPD pocketでROS KINETICが動いた〜↓

f:id:robonchu:20180912235727j:plain

所感

小さい割にスペックいいし、Ubuntu動くし、これからいろいろ試したい! 小さいロボットにもギリ載せれそう。

中国語の資料つらかった。。。