ロギ犬でもわかる翼型dxfファイルの作り方

前書き

これは慶應ロ技研アドベントカレンダー2019 その1の11日目の記事です。

こんにちは。飛行ロボコン班班長の豆腐さんど(@tohu_sand)です。今年は翼型解析とかの解説をしたかったのですが、技術&時間不足のため超簡単な内容となります。

この記事で解説するのは翼型dxfファイルの作り方です。dxf (Drawing Exchange Format) Autodesk社によって開発された図面フォーマットであり、ベクタ形式で形状データを表現することができます。その名のとおり互換可能な形式であり、内部データが公開されているため様々なCADソフトで使うことができます。

ロ技研飛行ロボコン班では、主翼切り出しに用いるベニヤ製の型を作るのにレーザー加工を行っており、dxfはもっぱらレーザー加工用データとして使われています。機械に頼るのは大切です。

翼型dxfを作るにあたっていくつか方法がありますが、本記事ではFusion360を用いる方法と、SolidWorksを用いる方法を紹介します。元になる翼型はインターネットに落ちてるものを使うことにします。「ロギ犬でもわかる」レベルで易しい内容なので画像マシマシの記事になっちゃった。

続きを読む “ロギ犬でもわかる翼型dxfファイルの作り方”

Mbedでマルチスレッド

これはロ技研アドベントカレンダー13日目の記事です。

今年は部員がたくさん増えたので、カレンダーが2つになりました。

はじめに

こんにちは、tokkyo13です。最近寒いですね。こんなに寒いのに、お布団から出るという行為に賃金が発生しないのはおかしいと思うんですよ。

さて、今日はmbedでマルチスレッドを使う話です。知っているとマイコンのプログラミングも幅が広がると思います。それでは行ってみましょう。

マルチスレッドって何?

マルチスレッドとは簡単に言うと複数の処理を並列で実行する仕組みのことです。単純なプログラムだと、実行の流れは1つだけで、ループや関数呼び出しを除けば、基本的に上から順に実行されます。この実行の流れを2つ以上に増やすのがマスチスレッドです。プログラムを実行してるCPUが分身の術を使って、複数の処理を同時に実行するようなイメージで考えてくれればいいと思います。マルチスレッドに対して単純なプログラムのことをシングルスレッドと呼んだりもします。

余談ですが、『暗殺教室』という漫画に「殺せんせー」というキャラクターが登場します。殺せんせーは高速移動をしながら、その残像を使って独立した動きをする分身を作り出します。あれがまさにマルチスレッドです、と言えばピンとくる人がいるかも知れませんね。

RTOS on Mbed

Mbedでは、RTOS (Real-time operating system) の機能が提供されています。RTOSについての細かい話はしませんが、RTOSの機能を使ってマルチスレッドが実現できます。

RTOSの提供する機能の使い方は、Mbedのウェブサイトに詳しく書かれています。今日はこれらの中から、

  • スレッド
  • 相互排他

の2つを扱ってみようと思います。

RTOSの使い方

これから、ソースコードを示したりしますので、コンパイルの方法について紹介します。

オンラインコンパイラの場合は、テンプレートとしてRTOS basic example.を選択して、main.cppを書き換えればOKです。

PlatformIOを使う場合は、まずProject Examplesからmbed-rtosを選択します。次に、インポートされたプロジェクトファイルの中にあるplatformio.iniというファイルを、使用するマイコン用に書き換えます。NucleoF446REの場合は、次のように書き込めばOKです。あとは、srcフォルダ下のmain.cppを書き換えましょう。

[env:nucleo_f446re]
platform = ststm32
framework = mbed
board = nucleo_f446re
build_flags = -DPIO_FRAMEWORK_MBED_RTOS_PRESENT

以下、NucleoF446RE用のプログラムを想定してプログラム例を示します。

スレッド

下にあるのが、1つのLEDを2秒周期で点滅させるプログラムです。

#include "mbed.h"

DigitalOut led1(A0);

int main()
{
    while (true)
    {
        led1 = !led1;
        wait(1);
    }
}

これにスレッドを1つ加えて、1秒周期で点滅するLEDを1つ追加してみましょう。次のようなプログラムになります。

#include "mbed.h"

DigitalOut led1(A0);
DigitalOut led2(A1);
Thread thread; // threadという名前のスレッドを宣言

void led2_thread() // 追加したスレッドが実行する用の関数
{
    while (true)
    {
        led2 = !led2;
        wait(1);
    }
}

int main() // main は必ず実行されるスレッド
{
    thread.start(led2_thread); // thread に led2_thread 関数の実行を開始させる

    while (true)
    {
        led1 = !led1;
        wait(0.5);
    }

    thread.join(); // thread の終了を待つ
}

使い方は上のプログラムを見ればだいたい分かると思いますが、説明します。

  1. まず、増やしたい数だけスレッドを宣言します。(5行目)
  2. 次に、増やしたスレッドが実行する関数を記述します。(7行目)
  3. 次に、メインのスレッド内で、新しいスレッドを開始します。(18行目)
  4. 増やしたスレッドの終了を待ってからメインのスレッドを終了する場合 (26行目)

メインのスレッドというのは、main関数から始まって順に実行されていく処理の流れのことです。また、4. についてですが、上のプログラムは無限ループなので、スレッドは終了しません。join()は、増やしたスレッドの終了を待ち、タイミングを揃えるときなどに使います。

これを実行すると、次の動画のようになります。

https://platform.twitter.com/widgets.js

相互排除

上で紹介したプログラムは、各スレッドが自分専用のLEDを持っていました。しかし、1つのLEDしか使えなかったらどうなるでしょう。次のプログラムは、1つのLEDを0.6秒周期で点滅させようとするスレッドと、0.2秒周期で点滅させようとするスレッドが競合状態になっている例です。

#include "mbed.h"

DigitalOut led1(A0);
Thread thread;

void led2_thread()
{
    while (true)
    {
        led1 = !led1;
        wait(0.1);
    }
}

int main()
{
    thread.start(led2_thread);

    while (true)
    {
        led1 = !led1;
        wait(0.3);
    }

    thread.join();
}

これを実行すると、次の動画のように、なんだかおかしな挙動になります。面白いですね。

https://platform.twitter.com/widgets.js

このような競合を防ぐには、LEDへのアクセスが可能なスレッドを1つに絞る必要があります。そのために使われるのが、相互排除です。相互排除を実現する機能として、ミューテックス(Mutex)という機能が提供されています。Mutexは、簡単に言うとアクセス権のようなもので、取得したり返却したりできます。アクセス権を取得することを「ロック」といい、アクセス権を返すことを「アンロック」といいます。

では、Mutexを使って先程のプログラムを書き換えましょう。

#include "mbed.h"

DigitalOut led1(A0);
Thread thread;
Mutex mutex; // ミューテックスの宣言

void led2_thread()
{
    while (true)
    {
        mutex.lock(); // ミューテックスをロック
        for (int i = 0; i < 6; i++) // 0.2秒周期で3回点滅
        {
            led1 = !led1;
            wait(0.1);
        }
        mutex.unlock(); // ミューテックスをアンロック
        wait(0.5);
    }
}

int main()
{
    thread.start(led2_thread);

    while (true)
    {
        mutex.lock(); // ミューテックスをロック
        for (int i = 0; i < 6; i++) // 0.6秒周期で3回点滅
        {
            led1 = !led1;
            wait(0.3);
        }
        mutex.unlock(); // ミューテックスをアンロック
        wait(0.5);
    }

    thread.join();
}

LEDの点滅プログラムは都合上、3回点滅して0.5秒間待つようにしています。この0.5秒の間に他のスレッドがLEDへのアクセス権を奪えるようにです。

結果、LEDは0.2秒周期の点滅と0.6秒周期の点滅を交互に実行するようになります。その様子は次の動画のようになります。

https://platform.twitter.com/widgets.js

この様に、Mutexは限られたリソース(今回の場合LED)を一時的に独占したいときに利用します。限られたリソースを使う前にロック、使い終わったらアンロックです。

おわりに

この記事で説明したのは、RTOSの機能のごく一部です。マルチスレッドや同期実行に興味が湧いた人はMbedのウェブサイトを読んで、サンプルプログラムを実行してみると良いと思います。

「統計的学習の基礎」の基礎

慶應ロ技研 Advent Calendar 2018 その1 10日目

こんにちは、研究室配属で失敗がありました、mt_caretです。

さて、前回のアドベントカレンダーではロボットに大変関係があるということで Haskellについて書きました。今年は同様にロボットに大変関係があるトピックということで統計的学習についての駄文です。

まずは、統計的学習とは何かについて考えると、何らかの変数Yとそれらに何らかの関係を持った変数X = (X1, X2, ⋯, Xp)を考えた時、次のようなモデルを考えてみます。

Y = f(X) + ε

fはなんらかの関数であり、εXと独立かつ期待値0の誤差項とします。1 適当なXを与えられた時のYを推定したいとすると、fを上手く近似したさえあれば推定値 = (X)が得られる、ということになります。

ここで、推定値は真値Yにどれだけ近づけることができるか検討してみるために、一旦Xを固定して、最小二乗誤差のあらゆるデータセット𝒯に関する期待値E[(Y − )2]を計算して見ましょう。

つまり、最小二乗誤差の期待値はfの期待値の差の二乗からなるバイアス項、 のヴァリアンス項、そしてεの分散の3つの項に分解することができました。この前者2つの項が所謂Bias-Variance Tradeoffに出てくるものに相当するわけです。

この導出が手元の本2だと「自明」としてカバーされておらず、しばらく導出できなくて云々唸ってようやくできたので記事のネタにしようと思い検索したところ、ウィキペディアに載っていました

ということで、ウィキペディアはちゃんと確認しよう!

追記: WordPress.comでMarkdown+LaTeXで数式を書こうとしたら地獄を見た。もう絶対使いたくない。


  1. 交絡等によりXεが成り立たない場合は、このモデルは上手く成立しなくなります。
    • An Introduction to Statistical Learning
    • The Elements of Statistical Learning