c89

でしぷろんと構成員として2015年冬にコミックマーケットC89に参加しました.
頒布した本は以下の でしぷろノート 2冊になります.
Note1の方を主に担当しました.

詳しくはこちら

note001

note002

khr3_gr001_with_matlab.md

KHR3-HV & GR001 with MATLAB




1.今回の目標

Matlab(2014a)から直接ロボットを制御する.

但し(まずは)

  1. Matlab本体から(Simlinkにはつながない)
  2. 有線接続
  3. 全関節の角度制御のみ

想定するOS

  • Ubuntu Linux (14.04)
  • Windows 8
  • (OSX)

2.方針

以前製作したライブラリrsxを拡張します.




3.拡張例 (C++ と Python)





既にC++とPython向けの拡張行っているので,これと同様に拡張します.
C言語で記述されたdpservoを利用する上位レイヤを用意することで実現します.

4.C言語とMatlabの連携

MatlabからC言語で実装されたライブラリを利用する手段には大きく2通り存在します.

  1. 共有ライブラリをロード&実行する汎用関数を利用する ( *1)
  2. MATLABが読み込める形式の共有ライブラリ(MEXファイル)を作成する ( *2)

1.の方法は特に追加の作業なしにC言語と連携出来ますが、手順が煩雑です。
今回はより利用手順が簡単な2.の方法をとります.

*1 : http://jp.mathworks.com/help/matlab/using-c-shared-library-functions-in-matlab-.html

*2 : http://jp.mathworks.com/help/matlab/ref/mex.html


5.librsxのMEX拡張





こんな感じになります.




MEXファイル1つに付き1関数しか実装出来ないためAPIの数だけMEXファイルを作成します.
また複数のMEXファイルが共通のハードウェアリソース(シリアルデバイス)を使用します.
このままだとAPIを実行する度にそれらの初期化等を行わなければなりません、
これを回避するためにdpsproxyという層を設けています.

6.C言語におけるMATLAB連携(1/2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* 
* MATLAB連携のためのヘッダファイルを読み込みます.
*/

#include "mex.h"
#include "matrix.h"

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {

/*
* 引数の数と型をチェック
* 期待値と一致しない場合にはエラーとする.
*/

if (nrhs < 1 || !mxIsChar(prhs[0])) {
mexErrMsgIdAndTxt(
"dps_proxy:EINVAL",
"dps_assign ics|rsx(string)");
return;
}

/* 次ページに続く */

6.C言語におけるMATLAB連携(2/2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {

/* 前ページから */

/*
* 引数の解釈
*/

int num = mxGetNumberOfElements(prhs[0]);
char name[num + 1];
if (mxGetString(prhs[0], name, num + 1) != 0) {
mexErrMsgIdAndTxt("dps_proxy:ERR","");
}

/*
* proxy関数の呼び出し
*/

errno_t eno = dps_proxy_assign(name);

/*
* エラーチェック
*/

if (eno != EOK) {
mexPrintf("The input string is: %s\n", name);
mexErrMsgIdAndTxt("dps_proxy:ERR","");
}

return;
}

7.ビルド手順 Linux

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// required package
// -- MATLAB (MEXコンパイラのため)
> git clone https://github.com/takarakasai/rsx.git
> cd rsx
> mkdir build
> cd build
> cmake ..
> ccmake ..
CMAKE_INSTALL_PREFIX: 任意のインストールディレクトリ
ENABLE_MATLAB_API : ON
HR_SERIAL_AUTO_READ_ECHO_DATA : ON (ローカルエコー有の場合)
HR_SERIAL_AUTO_READ_ECHO_DATA : OFF (ローカルエコー無の場合)
> make
> make install

7.ビルド手順 Windows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// required package
// -- MATLAB (MEXコンパイラのため)
// -- mingw-w64 : http://mingw-w64.org/
// -- gnumex : http://gnumex.sourceforge.net/
// -- git(2.7.1) : https://git-for-windows.github.io/
// -- cmake(3.4.1) : https://cmake.org/download/
> git clone https://github.com/takarakasai/rsx.git
> cd rsx
> . setup_mingw.sh <<<< Windows ではこれが必要です
> mkdir build
> cd build
> cmake ..
> ccmake ..
CMAKE_INSTALL_PREFIX: 任意のインストールディレクトリ
ENABLE_MATLAB_API : ON
HR_SERIAL_AUTO_READ_ECHO_DATA : ON (ローカルエコー有の場合)
HR_SERIAL_AUTO_READ_ECHO_DATA : OFF (ローカルエコー無の場合)
> make
> make install

※ 必要に応じてPATHを通してください.
※ WindowsもしくはMATLABが32bitの場合にはMinGWも32bit環境を用意する必要があります
(http://www.mingw.org/).
私は試したことありませんがおそらく以下のpkgがMinGW上で必要となるはずです.
mingw-base mingw-gcc mingw32-gmp(dev) msys-ligbmp(dev)


7.起動手順 Linux/Windows

Linux の場合

1
2
> cd ${インストールディレクトリ}
> LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:../lib matlab

Windows の場合

1
2
3
MATLAB起動後にインストールディレクトリ以下のlib/mexを
MATLABのPATHに追加してください
(これであっているはず...)

7.1 実行手順 KHR3-HV (1関節だけ)

実行手順はポート名を除きLinux/Windowsで共通です.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
% サーボ通信プロトコルを指定
>> dps_assign('ics')
% サーボIDを登録
>> dps_add_servo(uint8(1))
id:1
% UARTポートオープン(通信速度 115200[bps])
% Linux例 : /dev/ttyUSB0
>> dps_open('ttyUSB','0',int32(115200))
dev:ttyUSB port:0 baudrate:115200
file open : /dev/ttyUSB0
% Windows例 : COM0
>> dps_open('COM','0',int32(115200))
dev:COM port:0 baudrate:115200
file open : COM0
% Servo ON
>> dps_set_state(uint8(1), 'on')
id:01 state:on
% 30度に指定
>> dps_set_goal(uint8(1), 30.0)

7.2 実行手順 KHR3-HV (複数関節)

実行手順はポート名を除きLinux/Windowsで共通です.

1
2
3
4
5
6
7
8
9
% 前ページの続き
% ID:6~10のサーボを登録
>> dps_set_servo(uint8([6, 7, 8, 9, 10]))
5 : 06 07 08 09 10
% ID:1,6~10のサーボをON
>> dps_set_states('on')
% ID:1,6~10のサーボを駆動
>> dps_set_goals([20.0, 0.0, 0.0, 0.0, 0.0, 0.0])
id:all : 20.000000 -30.000000 0.000000 0.000000 0.000000 0.000000 0.000000

7.3 実行手順 KHR3-HV (offset設定)

実行手順はポート名を除きLinux/Windowsで共通です.

1
2
3
4
5
% 前ページの続き
>> dps_set_offset(uint8(1), 10.0)
id:01 oangle:10.0
>> dps_set_offsets([10.0, 0.0, 0.0, 0.0, 0.0, 0.0])
6 : 10.0 0.0 0.0 0.0 0.0 0.0

※ 極性の設定は今後対応予定です (mex対応するの忘れてた…).


7.1実行手順 GR001

実行手順はポート名を除きLinux/Windowsで共通です.

1
2
3
% サーボ通信プロトコルを指定
>> dps_assign('rsx')
% 以下はKHR3-HVの場合と同じです

8.1 まとめ

  1. MATLABでGR001とKHR3-HVを動作させる為のMEXファイルを作成しました
  2. WindowsとLinuxで動作することを確認しました(OSXでも多分動く)



controll GR001 with Python on Edison/PC.

今回の目標

EdisonもしくはPC上のpython環境からGR001を制御する.
これを実現するために以前C言語で作成した通信ライブラリrsxをpythonから利用できる様に拡張します.
拡張したライブラリを利用してpython環境からGR001を制御します.

※ :ライブラリの利用のみを行う場合には# 1.を飛ばしてください.


1. python用通信ライブラリ(rsxpy)のビルド/実行環境を構築

今回はEdison上でビルドします.
boost-pythonがビルドに必要で、ipythonが実行環境として便利なので
これらをインストールします.

1
2
3
4
> sudo apt-get install libboost-python-dev
130[MB]ほど消費されます.
> sudo apt-get install ipython
6.0[MB]ほど消費されます.

2. ライブラリの取得

以前作成したRS301/RS302サーボ向けの通信ライブラリを修正するため
通信ライブラリrsxを取得します.

1
2
3
> git clone git@github.com:takarakasai/rsx.git
> cd rsx
> git checkout feature/for_edison

3. ライブラリ内部の説明

rsxをpythonから利用するためのライブラリrsxpyに拡張します。
これにはboost_pythonを利用します.


3.1 全体構成

rsxpy向けに新たに用意したソースコードは以下のとおりです。
boost_pythonはC++のテンプレートライブラリなので、一旦C++によるラッパ(rsxpp)を作成して
boost_pythonにてpython向けのAPIを作成していきます.

1
2
3
4
./rsx/h/rsxpp/rsxpp.h                   // rsxライブラリのC++ラッパ
./rsx/python/sample/rsx_servo_state.py // pythonによるサンプルプログラム
./rsx/python/src/rsxpy.cc // python向けのラッパクラスの実装
./rsx/python/src/rsxpy.h // python向けのラッパクラスのヘッダ

3.2 C++によるラッパクラスの作成

ここではrsxppというクラスを作成します.

1
2
3
4
5
6
7
8
9
-- h/rsxpp/rsxpp.h
// C言語で作成した通信ライブラリrsxを利用するためrsx.hを読み込みます.
// またシリアル通信向けのEnumを扱えるようにするためhr_serial.hも読み込みます.
extern "C" {
#include "rsx.h"
#include "serial/hr_serial.h"
}

// (略)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
-- h/rsxpp/rsxpp.h
// (略)

// ラッパクラスを定義します.
// rsxライブラリを利用するために必要なrsx構造体を
// DEPSERVO_DECLというマクロを利用してメンバ変数として定義します.
// これをクラスのコンストラクタ内から初期化するようにします.
class rsxpp
{
public:
rsxpp(void) {
DPSERVO_INIT(servo_inst, RSX_INIT);
servo = (rsx*)(&servo_inst);
}

// (略)

// ここにrsxライブリが用意している通信APIを一通りラップする関数を用意します.
// 紙面の都合上全ては記載しませんが、
// ロングパケットでデータを送信するAPIについて以下に例を示します.
errno_t lpkt_mem_write_all
(uint8_t id[/*num*/], uint8_t num ,
uint8_t start_addr, uint8_t size, uint8_t data[/*size*/]) {
ECALL(rsx_lpkt_mem_write_all(servo, id, num, start_addr, size, data));
return EOK;
}

// (略)

protected:
DPSERVO_DECL(servo_inst, kNUM_OF_JOINTS, kMAX_PKT_SIZE, RSX_DECL);
rsx *servo;
}
```

---

## 3.3 Pythonで公開するためのクラスの作成

rsxppクラスを継承したrsxpyクラスを作成します.
rsxppクラスではrsxライブラリのAPIをそのままラップしていますが、
rsxpyクラスではpythonから利用することを考えて、
pythonで扱いやすい型の変数を引数や返り値にしています.

```c++
-- python/src/rsxpy.h
// C++によるラッパクラスrsxppを利用するためのヘッダを読み込みます.
// boost_pythonを利用するためヘッダを読み込みます.
#include "rsxpp.h"
#include "boost/python.hpp"
...
class rsxpy : public dp::rsxpp<kRSXPY_NUM_OF_JOINTS, kRSXPY_MAX_PKT_SIZE> {
...
// ここにrsxppライブリが用意している通信APIを一通りラップする関数を用意します.
// 紙面の都合上全ては記載しませんが、ロングパケットでデータを送信するAPIについて以下に例を示します.
errno_t lpkt_mem_write (bp::list &in_id, uint8_t start_addr, size_t size, bp::list &in_data) {
GET_C_ARRAY(uint8_t, num, id/*[num]*/, in_id);
GET_C_ARRAY_2D(uint8_t, num, size, data/*[num][size]*/, in_data);

ECALL(base::lpkt_mem_write(id, num, start_addr, size, (uint8_t**)data));
return EOK;
}
...
}

3.3 boost_pythonによるAPIの公開

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- h/rsxpp/rsxpp.cc
...
// rs30xの仮想アドレスをpythonに定数として公開するため
include "mmap/rs30x.h"
...
// boost_pythonのおまじないコードです.
BOOST_PYTHON_MODULE( rsxpy ) {
using namespace dp;

// シリアル通信の通信レートを定数として公開します.
boost::python::enum_<hr_baudrate>("HR_BAUDRATE")
.value("HR_B9600" , HR_B9600 )

// 以下定数の公開処理が続きます.
...

// ここからrsxpyクラスをpythonのrsxpyクラスとして公開します.
boost::python::class_<rsxpy>("rsxpy")
// rsxpyクラスの各公開関数をpythonのrsxpyクラスの関数として公開します.
.def("open", &rsxpy::open)
...
.def("lpkt_mem_write", &rsxpy::lpkt_mem_write)
...
;
}

3 . ライブラリのビルド

1
2
3
4
5
6
7
> m  kdir build
> c make ..
> c cmake ..
// PYTHON_API : OFF --> ON に変更します.
// gとcを押下してmakefileを生成します.
// qを押下してccmakeを抜けます.
> make

3. 実行

pythonのインタプリタを起動します.
ipythonだと関数や定数はタブ補完してくれます.

1
2
3
4
5
6
7
8
9
10
11
12
> cd python
> ipython
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
Type "copyright", "credits" or "license" for more information.

IPython 1.2.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.

object? -> Details about 'object', use 'object??' for extra details.

In [1]:

ipythonのインタプリタから通信APIを叩いていきます.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// ライブラリを読み込んで、通信クラスをインスタンス化します.
IN[*]: import rsxpy
IN[*]: rsx = rsxpy.rsxpy()

// 通信ポートを開きます.
IN[*]: rsx.open("ttyMFD", "1", rsxpy.HR_BAUDRATE.HR_B460800, rsxpy.HR_PARITY.HR_PAR_NONE)
// PCから直接GR001を制御する場合には下記の様に第12引数を読み替えてください.
IN[*]: rsx.open("ttyUSB", "0", rsxpy.HR_BAUDRATE.HR_B460800, rsxpy.HR_PARITY.HR_PAR_NONE)

IN[*]: ids = range(1,21)

// サーボをONにします.
IN[*]: rsx.lpkt_mem_write_all(ids, rsxpy.RSX_RS30X_MEM_ADDR.RSX_RAM_TRQ_ENABLE, [1])

// 各関節の角度を取得します.
IN[*]: ang = list()
IN[*]: for id in ids :
IN[*]: ang.append(rsx.lpkt_mem_read_int16(id, rsxpy.RSX_RS30X_MEM_ADDR.RSX_RAM_PRESENT_POS_L, 1)[0])
IN[*]:

// 1番と4番関節の角度を30度変化させます.
IN[*]: ang[1] += 30 * 10;
IN[*]: ang[4] += 30 * 10;
IN[*]: rsx.lpkt_mem_write_int16(ids, rsxpy.RSX_RS30X_MEM_ADDR.RSX_RAM_GOAL_POS_L, 1, ang)

// サーボをOFFします.
IN[*]: rsx.lpkt_mem_write_all(ids, rsxpy.RSX_RS30X_MEM_ADDR.RSX_RAM_TRQ_ENABLE, [0])

rs485-with-Intel-Edison

Intel EdisonでGR001とRS485で通信




1.今回の目標

  • Intel EdisonでGR001とRS485で通信する.

  • 複数の構成が考えられるので代表的なものを試す.

  • できれば通信時間等の比較をしてみる.


2.実施する構成

  1. USB-RS232C変換ケーブル + RS232C-RS485変換コネクタを使用する

  2. USB-RS485変換コネクタを使用する

  3. RS232C-RS485変換ICを使用する.

*通信速度は115200[bps]で行います.


3.想定する環境

break out board

  • henry board

OS

  • ubilinux + xenomai3.0.0

library

  • cmake
  • cmake-ncurses-gui

4.コードのビルドと実行

全身のサーボの目標角度の更新と現在角度の取得を繰り返し行い。
その間に消費される時間を測定します.

1
2
3
4
5
6
7
8
9
10
11
> mkdir work
> cd work
> git clone git@github.com:takarakasai/rsx.git
> mkdir -p rsx/build
> cd rsx/build
> camke ..
> ccmake ..
ここで4.に示すコンフィグを行います.
> make
> ./sample/rsx_latency_test tty*** *
ここで4.に示すttyUSB/ttyMFD 0/1の値を指定します.

4.実施形態


4.1 実施形態1 (USB-RS232C + RS232C-RS485)

1
+--------+  USB  +------------+ RS232C +------------+ RS485 +-------+
| Edison |=======| USB-RS232C |========|RS232C-RS485|=======| GR001 |
+--------+       +------------+        +------------+       +-------+



4.1.1 サーボON中の現在角度取得 (Echo:On)

  • 1軸あたり約3.0[msec]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
file open : /dev/ttyUSB0
auto echo read latency : 000000000001996.318[usec]
read latency : 000000000000899.985[usec]
Model Number L:10 H:30
Firmware Version:05
auto echo read latency : 000000000001928.862[usec]
read latency : 000000000000941.456[usec]
auto echo read latency : 000000000001975.050[usec]
read latency : 000000000000959.415[usec]
auto echo read latency : 000000000001979.356[usec]
read latency : 000000000000939.320[usec]
auto echo read latency : 000000000002017.731[usec]
read latency : 000000000000928.883[usec]
auto echo read latency : 000000000001944.446[usec]
read latency : 000000000001006.780[usec]
auto echo read latency : 000000000001927.463[usec]
read latency : 000000000000954.515[usec]
auto echo read latency : 000000000002015.670[usec]
read latency : 000000000000936.443[usec]
auto echo read latency : 000000000001963.297[usec]

4.1.1 サーボON中の現在角度取得 (Echo:Off)

  • 1軸あたり約3.0[msec], Echoなしとあまり変わらない。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
file open : /dev/ttyUSB0
read latency : 000000000002938.702[usec]
Model Number L:10 H:30
Firmware Version:05
read latency : 000000000002889.709[usec]
read latency : 000000000002944.792[usec]
read latency : 000000000002939.965[usec]
read latency : 000000000002937.811[usec]
read latency : 000000000002943.545[usec]
read latency : 000000000002945.761[usec]
read latency : 000000000002950.890[usec]
read latency : 000000000002932.800[usec]
read latency : 000000000002945.314[usec]
read latency : 000000000002970.654[usec]
read latency : 000000000002937.247[usec]
read latency : 000000000002954.433[usec]
read latency : 000000000002910.236[usec]
read latency : 000000000002951.315[usec]
read latency : 000000000002956.522[usec]
read latency : 000000000002945.080[usec]

4.1.2 目標角度更新+現在角度取得 (Echo:On)

  • 1回あたり約2200[msec],遅い…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@ubilinux:/home/kasai/rsx/build# ./sample/rsx_latency_test ttyUSB 0
file open : /dev/ttyUSB0
Model Number L:10 H:30
Firmware Version:05
write read latency : 000000002209018.433[usec]
write read latency : 000000002209550.048[usec]
write read latency : 000000002215498.369[usec]
write read latency : 000000002210337.490[usec]
write read latency : 000000002214434.746[usec]
write read latency : 000000002210338.889[usec]
write read latency : 000000002208474.912[usec]
write read latency : 000000002213613.604[usec]
write read latency : 000000002207402.759[usec]
write read latency : 000000002223359.310[usec]
write read latency : 000000002214373.243[usec]
write read latency : 000000002209397.254[usec]
write read latency : 000000002215453.894[usec]
write read latency : 000000002221349.023[usec]
write read latency : 000000002213387.381[usec]
write read latency : 000000002226612.283[usec]
write read latency : 000000002229343.842[usec]
write read latency : 000000002207545.825[usec]
write read latency : 000000002218341.943[usec]
write read latency : 000000002221342.090[usec]

4.1.2 目標角度更新+現在角度取得 (Echo:Off)

  • 1回あたり約66[msec], Echoなしとだいぶ変わる.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@ubilinux:/home/kasai/rsx/build# ./sample/rsx_latency_test ttyUSB 0 
file open : /dev/ttyUSB0
Model Number L:10 H:30
Firmware Version:05
write read latency : 000000000066007.243[usec]
write read latency : 000000000065416.549[usec]
write read latency : 000000000065517.149[usec]
write read latency : 000000000065456.895[usec]
write read latency : 000000000065402.658[usec]
write read latency : 000000000065359.403[usec]
write read latency : 000000000065491.657[usec]
write read latency : 000000000065477.599[usec]
write read latency : 000000000065335.568[usec]
write read latency : 000000000065364.201[usec]
write read latency : 000000000065544.980[usec]
write read latency : 000000000065445.083[usec]
write read latency : 000000000065318.323[usec]
write read latency : 000000000065438.933[usec]
write read latency : 000000000065735.271[usec]
write read latency : 000000000065654.119[usec]
write read latency : 000000000065327.452[usec]
write read latency : 000000000065310.521[usec]
write read latency : 000000000065388.858[usec]
write read latency : 000000000065337.072[usec]
----- end -----

4.2 実施形態2 (USB-RS485)

1
+--------+  USB  +----------+ RS485 +-------+
| Edison |=======| USB-RS485|=======| GR001 |
+--------+       +----------+       +-------+



4.2.0 実施形態2 (USB-RS485) 準備

  • 今回使用する変換コネクタはCH340+MAX485の構成なので,ch341なドライバが必要.
  • Edison標準のLinuxイメージにはこれがないのでドライバの導入が必要.
  • 標準でサポートしているのでカーネルコンフィグをいじってドライバをビルドする.参考
  1. インストール場所はこんな感じ
1
2
3
4
hroot@ubilinux:home/kasai/rsx/build# find /lib/modules/3.10.17-yocto-standard | grep ch341.ko$
/lib/modules/3.10.17-yocto-standard/kernel/drivers/usb/serial/ch341.ko
hroot@ubilinux:home/kasai/rsx/build# cat /lib/modules/3.10.17-yocto-standard/modules.dep | grep ch341
kernel/drivers/usb/serial/ch341.ko:
  1. ドライバをロードすると/dev/ttyUSB*として認識する
1
2
3
4
5
6
7
8
root@ubilinux:/home/kasai/rsx/build# dmesg | grep ch341
//ロードしていないので何も表示されない
root@ubilinux:/home/kasai/rsx/build# modprobe ch341
root@ubilinux:/home/kasai/rsx/build# dmesg | grep ch341
[ 4594.146533] usbcore: registered new interface driver ch341
[ 4594.146684] usbserial: USB Serial support registered for ch341-uart
[ 4594.146773] ch341 1-1:1.0: ch341-uart converter detected
[ 4594.149669] usb 1-1: ch341-uart converter now attached to ttyUSB0

4.2.1 サーボON中の現在角度取得 (Echo:Off)

  • 1軸あたり4.0-5.0[msec]程度の時間が消費されるようです.
  • ばらつきがあります.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
file open : /dev/ttyUSB0
read latency : 000000000004025.258[usec]
Model Number L:10 H:30
Firmware Version:05
read latency : 000000000004837.597[usec]
read latency : 000000000004894.456[usec]
read latency : 000000000004113.485[usec]
read latency : 000000000004768.715[usec]
read latency : 000000000004956.296[usec]
read latency : 000000000004102.266[usec]
read latency : 000000000004829.400[usec]
read latency : 000000000004925.636[usec]
read latency : 000000000004913.047[usec]
read latency : 000000000004939.229[usec]
read latency : 000000000004973.907[usec]
read latency : 000000000004061.789[usec]
read latency : 000000000004838.127[usec]
read latency : 000000000004946.335[usec]
read latency : 000000000004037.351[usec]
read latency : 000000000004833.191[usec]

4.2.2 目標角度更新+現在角度取得 (Echo:Off)

  • 1軸あたり100[msec]程度の時間が消費されるようです.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
root@ubilinux:/home/kasai/rsx/build# ./sample/rsx_latency_test ttyUSB 0
file open : /dev/ttyUSB0
Model Number L:10 H:30
Firmware Version:05
write read latency : 000000000099950.036[usec]
write read latency : 000000000098789.981[usec]
write read latency : 000000000099444.884[usec]
write read latency : 000000000098239.896[usec]
write read latency : 000000000099361.530[usec]
write read latency : 000000000100248.693[usec]
write read latency : 000000000100436.427[usec]
write read latency : 000000000101202.667[usec]
write read latency : 000000000100670.694[usec]
write read latency : 000000000100652.687[usec]
write read latency : 000000000101576.298[usec]
write read latency : 000000000100529.411[usec]
write read latency : 000000000101556.370[usec]
write read latency : 000000000101491.546[usec]
write read latency : 000000000100395.651[usec]
write read latency : 000000000099471.337[usec]
write read latency : 000000000095471.131[usec]
write read latency : 000000000099132.585[usec]
write read latency : 000000000101567.170[usec]
write read latency : 000000000101641.469[usec]
----- end -----

4.3 実施形態3 (RS232C-RS485)

1
+--------+  uart  +------------+ RS485 +-------+
| Edison |========|RS232C-RS485|=======| GR001 |
+--------+        +------------+       +-------+





フリスクケースあり (左)
フリスクケースなし (右)

4.3 実施形態2´ (RS232C-RS485)

1
+--------+
| Edison |
+--------+
    || uart 
+--------+  uart  +------------+ RS485 +-------+
|自作基板|========|RS232C-RS485|=======| GR001 |
+--------+        +------------+       +-------+


=>


4.3.0 uart <-> RS485 変換IC

ISL32603E

-半二重通信用のICで1.8[V]で駆動.256~460[Kbps]までいける.
(※ 保証はできませんが私の環境では115[Kbps]でも動作しました.).

-パッケージはSOIC(1.27[mm])もしくはMSOP(0.5[mm])になるので表面実装が必要.

[1]
[2]
[3]


[1] http://www.incom.co.jp/var/assets/storage/images/companies/node_1664/product/node_118235/1662980-2-jpn-JP/RS-485-ISL3260x_square250.jpg

[2] http://www.eleki-jack.com/KitsandKids2/assets_c/2010/11/LTSP20620020-thumb-400x493.jpg

[3] http://akizukidenshi.com/img/goods/L/P-06863.jpg

購入場所
mouser
or
digikey

仕様書


4.3.1 サーボON中の現在角度取得

  • 1軸あたり2.5[msec]程度の時間が消費されるようです.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
file open : /dev/ttyMFD1
auto echo read latency : 000000000002568.977[usec]
read latency : 000000000000154.489[usec]
Model Number L:10 H:30
Firmware Version:05
auto echo read latency : 000000000002389.956[usec]
read latency : 000000000000153.327[usec]
auto echo read latency : 000000000002391.869[usec]
read latency : 000000000000150.943[usec]
auto echo read latency : 000000000002416.129[usec]
read latency : 000000000000161.699[usec]
auto echo read latency : 000000000002291.760[usec]
read latency : 000000000000161.488[usec]
auto echo read latency : 000000000002269.892[usec]
read latency : 000000000000165.285[usec]
auto echo read latency : 000000000002278.397[usec]
read latency : 000000000000163.622[usec]
auto echo read latency : 000000000002203.704[usec]
read latency : 000000000000164.331[usec]
auto echo read latency : 000000000002218.209[usec]

4.3.2 目標角度更新+現在角度取得

  • 1回あたり57[msec]程度の時間が消費されるようです.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@ubilinux:/home/kasai/rsx/build# ./sample/rsx_latency_test ttyMFD 1
file open : /dev/ttyMFD1
Model Number L:10 H:30
Firmware Version:05
write read latency : 000000000056354.259[usec]
write read latency : 000000000056687.984[usec]
write read latency : 000000000056654.634[usec]
write read latency : 000000000056597.344[usec]
write read latency : 000000000056777.629[usec]
write read latency : 000000000056968.642[usec]
write read latency : 000000000056450.153[usec]
write read latency : 000000000056666.476[usec]
write read latency : 000000000056631.691[usec]
write read latency : 000000000056884.130[usec]
write read latency : 000000000056841.407[usec]
write read latency : 000000000056458.870[usec]
write read latency : 000000000056554.745[usec]
write read latency : 000000000056651.169[usec]
write read latency : 000000000056691.800[usec]
write read latency : 000000000056875.255[usec]
write read latency : 000000000056446.435[usec]
write read latency : 000000000056648.150[usec]
write read latency : 000000000056814.218[usec]
write read latency : 000000000057273.610[usec]

5 結果まとめ





USB-RS232-RS485USB-RS485uart-RS232-RS485
現在角度取得 3.0[msec]4-5.0[msec] 2.5[msec]
目標角度更新と現在角度取得67.0[msec] 100.0[msec]57.0[msec]

6 考察

通信遅延要因

シリアル通信ドライバ

  • 速度優先の設定になっていない (setserial /dev/tty* low_latency)
  • バッファ処理による遅延
  • ユーザ-カーネル間の遷移に関連する遅延(通信データ, コンテキストスイッチ)

==> RTDM対応のシリアル通信ドライバを作成すれば改善する可能性あり.

その他

  • サーボに設定できる通信遅延時間が長く設定されている (0.1 - 12.850[msec])

==> 最小値(0.1[msec])に設定されていた


おわり




xenomai-3.0 on ubilinux with Intel Edison

1.今回の目標

Intel Edison向けUbilinuxのカーネルをxenomaiカーネルに置き換える.


2.方針

Ubilinuxのカーネルソースは公開されていないので,Edison向けYocto linuxのソースを落としてきてXenomaiパッチをあててビルドします.
Yoctoのビルドシステムを使用することになるので,手動でパッチあてて即ビルドというわけにはいかないです.
なので,Yocto linux向けのXenomaiパッチを作成してYoctoのビルドコンフィグに設定してビルドするです.


3.準備

まずEdisonにUbilinuxの環境を作成します.

1
2
3
4
5
6
> wget http://www.emutexlabs.com/files/ubilinux/ubilinux-edison-150309.tar.gz
> tar zxvf ubilinux-edison-150309.tar.gz$
> cd toFlash
ここで一旦Edisonに接続されているUSBケーブルを取り外します
> ./flashall.sh
EdisonにUSBケーブルを接続します.

4.作業手順


4.1 作業ディレクトリ作成

適当に作業用ディレクトリを作成します.
以降はこの下で作業を行います.

1
2
> mkdir work
> cd work

4.2 ソースコードの準備

Yocto LinuxとXenomaiのソース一式を取得して展開

1
2
3
4
> wget http://downloadmirror.intel.com/25028/eng/edison-src-ww25.5-15.tgz
> tar zxvf edison-src-ww25.5-15.tgz$
> wget https://xenomai.org/downloads/xenomai/stable/xenomai-3.0.tar.bz2
> bzip2 -dc xenomai-3.0.tar.bz2$ | tar xvf -

Git から取得しても良いです.

1
2
3
4
5
6
7
8
9
10
11
> git clone git://git.yoctoproject.org/meta-intel-edison
> cd meta-intel-edison
> git checkout ww05-15
> cd ..
> mkdir edison-src
> mv meta-intel-edison edison-src/

> git clone git://git.xenomai.org/xenomai-3.git
> cd xenomai-3
> git checkout v3.0
> cd ..

4.3 一旦ビルドする

Yoctoのビルドシステムではビルドコマンドしないとソースコードを落としてくれないのでビルドします.
と書いたもののバージョンが一致するカーネルをkernel.orgから持ってきても良さそうです. ビルドすると34GBほど消費されます.

1
2
3
4
5
6
> cd edison-src
> ln -s meta-intel-edison/utils/Makefile.mk Makefile
> make setup
> cd edison-src/out/linux64
> source poky/oe-init-build-env
> bitbake edison-image

4.4 パッチ作成

ビルド終わると以下のディレクトリにカーネルソースが取得されています.
out/linux64/build/tmp/work/edison-poky-linux/linux-yocto/3.10.17-r0/linux/
ので、xenomaiパッチをあてます.
*edison用のディストリは皆32bitなので注意.

diff -Narup linux linux_xeno

1
2
3
4
5
6
> cp -rf edison-src/out/linux64/build/tmp/work/edison-poky-linux/linux-yocto/3.10.17-r0/linux/ ./linux.org
> cp -rf edison-src/out/linux64/build/tmp/work/edison-poky-linux/linux-yocto/3.10.17-r0/linux/ ./linux.xeno
> xenomai-3/scripts/prepare-kernel.sh \
--linux=linux.xeno \
--ipipe=xenomai-3/kernel/cobalt/arch/x86/patches/ipipe-core-3.10.32-x86-6.patch \
--arch=x86

これだとエラーが出るのでなくなるまで修正します.
修正が終わったらパッチを作成します.

1
> diff -Narup linux.org linux_xeno > xenomai-3.0-3.10.17.patch

4.5 パッチの組み込み

作成したパッチをYoctoのビルドに組み込みます.
これには特定の場所にパッチを配置して、bitbakeの設定ファイルに記述を追加する必要があります.

1
2
3
4
5
6
7
> mv xenomai-3.0-3.10.17.patch edison-src/meta-intel-edison/meta-intel-edison-bsp/recipes-kernel/linux/files/
> vi edison-src/meta-intel-edison/meta-intel-edison-bsp/recipes-kernel/linux/linux-yocto_3.10.bbappend
... 略 ...
SRC_URI += "file://defconfig"
SRC_URI += "file://upstream_to_edison.patch" <<<< edison向けのパッチ
SRC_URI += "file://xenomai-3.0-3.10.17.patch" <<<< 追加.xenomaiパッチ
... 略 ...

4.6 カーネルコンフィグ

Yoctoのビルドシステムを使ってカーネルのコンフィグをいじります.
Xenomaiを使い物にするには,CPUをぶん回したりするので以下を参考に設定します。
https://xenomai.org//2014/06/configuring-for-x86-based-dual-kernels/

1
> bitbake virtual/kernel -c menuconfig

設定が終わったらYoctoのビルドシステムが指定する所定の場所に配置します.

1
cp edison-src/build/tmp/work/edison-poky-linux/linux-yocto/3.10.17-r0/linux-edison-standard-build/.config ../../../meta-intel-edison/meta-intel-edison-bsp/recipes-kernel/linux/files/defconfig

4.7 ビルド

Xenomaiパッチを当てたカーネルをビルドします.

1
2
3
4
5
6
> bitbake edison-image
> ls edison-src/out/linux64/build/tmp/deploy/images/edison
...
bzImage--3.10.17-r0-edison-YYYYMMDDHHMMSS.bin
edison-image-edison-YYYYMMDDHHMMSS.hddimg
...

4.8 インストール

vmlinuz と必要あれば/lib/modulesなどをコピーします.

1
2
3
4
5
6
7
8
9
10
> mkdir ext4
> sudo mount -o loop edison-image-edison-YYYYMMDDHHMMSS.rootfs.ext4 ext4
> ls ext4
bin boot dev etc home lib lost+found media mnt opt proc run sbin sketch sys tmp usr var
> scp -rf ext4/lib/modules/3.10.17-yocto-standard root@${edison_ip}:/lib/modules/

> mkdir hddimg
> sudo mount -o loop edison-image-edison-YYYYMMDDHHMMSS.hddimg hddimg
ldlinux.c32 ldlinux.sys syslinux.cfg vmlinuz
> scp -rf hddimg/vmlinuz root@${edison_ip}:/boot/vmlinuz.xeno

wlan at ubilinux with edison

ubilinux な edison で wlan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
> wpa_passphrase koya ${your_wpa_passwd} > koya-wlan.conf
> cp ./koya-wlan.conf /etc/wpa_supplicant/
> vi /etc/network/interfaces
auto wlan0
iface wlan0 inet dhcp
# For WPA
+ wpa-conf /etc/wpa_supplicant/koya-wlan.conf
- wpa-ssid test
- wpa-psk pass
+ #wpa-ssid test
+ #wpa-psk pass
# For WEP
#wireless-essid Emutex
#wireless-mode Managed
#wireless-key s:passwordk

> ifdown wlan0
nternet Systems Consortium DHCP Client 4.2.2
Copyright 2004-2011 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/wlan0/78:4b:87:a8:f0:e9
Sending on LPF/wlan0/78:4b:87:a8:f0:e9
Sending on Socket/fallback
DHCPRELEASE on wlan0 to 192.168.11.1 port 67

> ifup wlan0
Internet Systems Consortium DHCP Client 4.2.2
Copyright 2004-2011 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/wlan0/78:4b:87:a8:f0:e9
Sending on LPF/wlan0/78:4b:87:a8:f0:e9
Sending on Socket/fallback
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 8
DHCPDISCOVER on wlan0 to 255.255.255.255 port 67 interval 13
DHCPREQUEST on wlan0 to 255.255.255.255 port 67
DHCPOFFER from 192.168.11.1
DHCPACK from 192.168.11.1
bound to 192.168.11.11 -- renewal in 76747 seconds.

> iwconfig wlan0
wlan0 IEEE 802.11abgn ESSID:"koya"
Mode:Managed Frequency:2.412 GHz Access Point: 4C:E6:76:3E:BE:A1
Bit Rate=54 Mb/s Tx-Power=31 dBm
Retry long limit:7 RTS thr:off Fragment thr:off
Encryption key:off
Power Management:on
Link Quality=56/70 Signal level=-54 dBm
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:14 Invalid misc:1 Missed beacon:0