Luaのトランスコンパイラです。ロゴがダサいのが特徴です。
Luaは言語仕様が小さいため非常に軽量に動作するという特徴がありますが、クラス、配列のようなものを定義したい場合は全てテーブルを駆使してトリッキーなコードを記述する必要があります。
MoonScriptは以下のように、他のオブジェクト指向言語と近い形式でクラスや継承を記述できます。
class BaseClass
new: (v1) =>
self.v1 = v1
print_func: =>
print(self.v1)
class SubClass extends BaseClass
new: (v1,v2) =>
super v1
self.v2 = v2
print_func: =>
super!
self.v2 += 1
print(self.v2)
test_func = (bc) ->
bc\print_func!
obj = SubClass(1,2)
test_func(obj)
test_func(obj)
test_func(obj)
見た目はLuaとだいぶ違いますが、このコードをLuaに変換して実行しています。
+=
、-=
等の演算子->
による関数定義\
記号で関数名を区切るlocal
を使わなくてもローカル変数になる他にもいろいろと違いはあるのですが、それについては以下のサイトなどを参考にしてください。
OpenRTM LuaのMoonScript用ラッパーライブラリを使用します。
OpenRTM Lua版にMoonScriptの実行環境も含めてあります。
以下のコマンドでモジュール検索パスを設定する必要があります。 パスはOpenRTM Luaを展開したフォルダによって適宜変更してください。
> set LUA_PATH=openrtm-lua-0.3.0(x86)\\lua\\?.lua;openrtm-lua-0.3.0(x86)\\moon\\lua\\?.lua > set LUA_CPATH=openrtm-lua-0.3.0(x86)\\clibs\\?.dll;openrtm-lua-0.3.0(x86)\\moon\\clibs\\?.dll;
その後、以下のコマンドでRTCが起動できます。 ファイル名は適宜変更してください。
> lua openrtm-lua-0.3.0(x86)/moon/bin/moon test.lua
LuaRocksでインストールします。
$ sudo luarocks install moonscript
以下のコマンドで実行します。
$ moon test.lua
サンプルを例に、RTC作成方法を説明します。
以下のようにモジュールのロードを行います。
openrtm_ms = require "openrtm_ms"
以下のようにRTCの仕様を定義したテーブルを作成します。
consolein_spec = {
["implementation_id"]:"ConsoleIn",
["type_name"]:"ConsoleIn",
["description"]:"Console input component",
["version"]:"1.0",
["vendor"]:"Sample",
["category"]:"example",
["activity_type"]:"DataFlowComponent",
["max_instance"]:"10",
["language"]:"MoonScript",
["lang_type"]:"script"}
RTCをクラスで定義します。
class ConsoleIn extends openrtm_ms.RTObject
-- コンストラクタ
-- @param manager マネージャ
new: (manager) =>
super manager
(省略)
-- 初期化時のコールバック関数
-- @return リターンコード
onInitialize: =>
(省略)
-- アクティブ状態の時の実行関数
-- @param ec_id 実行コンテキストのID
-- @return リターンコード
onExecute: (ec_id) =>
(省略)
アウトポート、インポート、サービスポートをonInitialize関数で追加します。
new: (manager) =>
super manager
-- データ格納変数
self._d_out = openrtm_ms.RTCUtil.instantiateDataType("::RTC::TimedLong")
-- アウトポート生成
self._outOut = openrtm_ms.OutPort("out",self._d_out,"::RTC::TimedLong")
-- 初期化時のコールバック関数
-- @return リターンコード
onInitialize: =>
-- ポート追加
@addOutPort("out",self._outOut)
return self._ReturnCode_t.RTC_OK
データの出力を行う場合は、self._d_out
に送信データを格納後、self._outOut
のwrite関数を実行します。
-- 出力データ格納
self._d_out.data = 1
-- データ書き込み
self._outOut\write()
new: (manager) =>
super manager
-- データ格納変数
self._d_in = openrtm_ms.RTCUtil.instantiateDataType("::RTC::TimedLong")
-- インポート生成
self._inIn = openrtm_ms.InPort("in",self._d_in,"::RTC::TimedLong")
-- 初期化時のコールバック関数
-- @return リターンコード
onInitialize: =>
-- ポート追加
@addInPort("in",self._inIn)
return self._ReturnCode_t.RTC_OK
openrtm_ms.RTCUtil.instantiateDataType
関数により、データを格納する変数を初期化できます。
openrtm_ms.OutPort.new("out",self._d_out,"::RTC::TimedLong")
のように、データ型は文字列で指定する必要があります。
入力データを読み込む場合は、self._inIn
のread
関数を使用します。
-- バッファに新規データがあるかを確認
if self._inIn\isNew()
-- データ読み込み
data = self._inIn\read()
print("Received: ", data)
print("Received: ", data.data)
プロバイダ側のサービスポートを生成するためには、まずプロバイダのクラスを定義します。
class MyServiceSVC_impl
-- コンストラクタ
new: () =>
(省略)
echo: (msg) =>
(省略)
get_echo_history: () =>
(省略)
set_value: (value) =>
(省略)
get_value: () =>
(省略)
get_value_history: () =>
(省略)
onInitialize関数内でポートの生成、登録を行います。
new: (manager) =>
super manager
-- サービスポート生成
self._myServicePort = openrtm_ms.CorbaPort("MyService")
-- プロバイダオブジェクト生成
self._myservice0 = MyServiceSVC_impl()
-- 初期化時のコールバック関数
-- @return リターンコード
onInitialize: =>
-- サービスポートにプロバイダオブジェクトを登録
self._myServicePort\registerProvider("myservice0", "MyService", self._myservice0, "idl/MyService.idl", "IDL:SimpleService/MyService:1.0")
-- ポート追加
@addPort(self._myServicePort)
return self._ReturnCode_t.RTC_OK
self._myServicePort\registerProvider("myservice0", "MyService", self._myservice0, "../idl/MyService.idl", "IDL:SimpleService/MyService:1.0")
のように、IDLファイル名、インターフェース名を文字列で指定する必要があります。
コンシューマ側のサービスポートを追加するには、以下のようにonInitialize関数内でポートの生成、追加を行います。 self._myServicePort\registerConsumer("myservice0", "MyService", self._myservice0, "../idl/MyService.idl")
のようにIDLファイル名を文字列で指定する必要があります。
new: (manager) =>
super manager
-- サービスポート生成
self._myServicePort = openrtm_ms.CorbaPort("MyService")
-- コンシューマオブジェクト生成
self._myservice0 = openrtm_ms.CorbaConsumer("IDL:SimpleService/MyService:1.0")
-- 初期化時のコールバック関数
-- @return リターンコード
onInitialize: =>
-- サービスポートにコンシューマオブジェクトを登録
self._myServicePort\registerConsumer("myservice0", "MyService", self._myservice0, "idl/MyService.idl")
-- ポート追加
@addPort(self._myServicePort)
return self._ReturnCode_t.RTC_OK
オペレーションを呼び出す場合は、CorbaConsumerの_ptr
関数でオブジェクトリファレンスを取得して関数を呼び出します。
self._myservice0\_ptr()\set_value(val)
コンフィグレーションパラメータの設定には、まずRTCの仕様にコンフィグレーションパラメータを追加します。
configsample_spec = {
(省略)
["conf.default.int_param0"]:"0",
["conf.default.int_param1"]:"1",
["conf.default.double_param0"]:"0.11",
["conf.default.double_param1"]:"9.9",
["conf.default.str_param0"]:"hoge",
["conf.default.str_param1"]:"dara",
["conf.default.vector_param0"]:"0.0,1.0,2.0,3.0,4.0"}
onInitialize関数で変数をバインドします。 値は_value
というキーに格納されます。
new: (manager) =>
super manager
self._int_param0 = {_value:0}
self._int_param1 = {_value:1}
self._double_param0 = {_value:0.11}
self._double_param1 = {_value:9.9}
self._str_param0 = {_value:"hoge"}
self._str_param1 = {_value:"dara"}
self._vector_param0 = {_value:{0.0, 1.0, 2.0, 3.0, 4.0}}
-- 初期化時のコールバック関数
-- @return リターンコード
onInitialize: =>
-- コンフィギュレーションパラメータを変数にバインドする
@bindParameter("int_param0", self._int_param0, "0")
@bindParameter("int_param1", self._int_param1, "1")
@bindParameter("double_param0", self._double_param0, "0.11")
@bindParameter("double_param1", self._double_param1, "9.9")
@bindParameter("str_param0", self._str_param0, "hoge")
@bindParameter("str_param1", self._str_param1, "dara")
@bindParameter("vector_param0", self._vector_param0, "0.0,1.0,2.0,3.0,4.0")
print("\n Please change configuration values from RTSystemEditor")
return self._ReturnCode_t.RTC_OK
onExecuteコールバックなどを定義する場合についても、関数を定義して処理を記述します。
onExecute: (ec_id) =>
io.write("Please input number: ")
data = tonumber(io.read())
-- 出力データ格納
self._d_out.data = data
-- 出力データにタイムスタンプ設定
openrtm_ms.setTimestamp(self._d_out)
-- データ書き込み
self._outOut\write()
return self._ReturnCode_t.RTC_OK
以下のようにRTCの登録、生成関数を定義します。
-- ConsoleInコンポーネントの生成ファクトリ登録関数
-- @param manager マネージャ
ConsoleInInit = (manager) ->
prof = openrtm_ms.Properties({defaults_map:consolein_spec})
manager\registerFactory(prof, ConsoleIn, openrtm_ms.Factory.Delete)
-- ConsoleInコンポーネント生成
-- @param manager マネージャ
MyModuleInit = (manager) ->
ConsoleInInit(manager)
comp = manager\createComponent("ConsoleIn")
manager = openrtm_ms.Manager
manager\init(arg)
manager\setModuleInitProc(MyModuleInit)
manager\activateManager()
manager\runManager()