このページではWEBアプリサーバーOpenResty上で動作するRTCを作成して、以下のようにPython版サンプルコンポーネントのジョイスティックコンポーネントと接続してWEBブラウザ上でジョイスティックの位置を表示するシステムの作成を行います。
従来はWEBブラウザ上でRTCのデータを表示等をする場合は、以下のようにRTCとWEBサーバーで通信を行う必要がありましたが、

WEBサーバー上でRTCを起動することで、以下のように構成が簡単になります。

この構成にする事によって、従来の方法では難しかったWEBブラウザでの操作のタイミングでOutPortからデータを送信する、サービスポートの操作を呼び出すという事が容易に実現できます。
※このような使い方を見たわけではありませんが、OpenRTM-aist Python版+Twisted(もしくはDjango)でも同じ構成は可能かもしれません。
以下からopenresty-1.13.6.1-win32.zipをダウンロードして適当な場所に展開してください。
以下のサイトを参考にしてディレクトリを作成する。
rtc-server
|
|----conf
| |----mime.types
| |----nginx.conf
|
|----logs
| |----access.log
| |----error.log
|
|----luahooks
| |----image.lua
|
|
|----public
| |----images
| |----index.html
| |----sample.html
| |----test.gif
nginx.confには以下のように記述してください。
worker_processes 1;
events {
worker_connections 1024;
accept_mutex_delay 100ms;
}
http {
sendfile on;
tcp_nopush on;
include mime.types;
default_type text/html;
index index.html;
#
# log settings
#
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log logs/access.log main;
#
# lua global settings
#
lua_package_path '$prefix/luahooks/?.lua;;';
lua_check_client_abort on;
lua_code_cache on;
#
# initialize script
#
#init_by_lua_file luahooks/init.lua;
#
# public
#
server {
listen 1080;
root public/images;
#
# content handler
#
location /index.html {
default_type text/html;
content_by_lua_file luahooks/image.lua;
}
}
}
test.gifには以下のような画像を用意してください。

sample.htmlには以下のように記述してください。
rtc-serverのフォルダにOpenRTM Lua版の各ファイルをコピーします。
以下から32bit用のOpenRTM Lua版ファイル一式(OpenRTM Lua x.y.z LuaJIT 32bit)をダウンロードしてください。
OpenRTM Lua版からOpenRestyにファイルをコピーします。
openrtm-lua-x.y.z-x86-LuaJIT\luaフォルダを、rtc-server以下にコピーしてください。

openrtm-lua-x.y.z-x86-LuaJIT\lua\idlフォルダを、rtc-server以下にコピーしてください。

openrtm-lua-x.y.z-x86-LuaJIT\clibsフォルダを、rtc-server以下にコピーしてください。

lua51.dllの上書きが必要なため、openrtm-lua-x.y.z-x86-LuaJIT\bin\lua51.dllをopenresty-1.13.6.1-win32\以下にコピーしてください。

データはJSON形式で取得しますが、Lua CJSONはこちらでdllを用意していないのでビルドしてください。
以下からソースコードをダウンロードしてCMake、Visual Studioでビルドしてください。
Visual Stduio 2017の場合はビルド時にエラーが出ます。 CMakeLists.txtの以下の部分を削除してからビルドしてください。
add_definitions(-Dsnprintf=_snprintf)

RTC BuilderによるRTCの基本的な作成手順は以下のページを参考にしてください。
上のページの作成手順に従って、以下の仕様のRTCを作成してください。
| モジュール名 | OpenRestySample |
onExecuteを有効にしてください。
| ポート名 | in |
| データ型 | RTC::TimedFloatSeq |
データを格納する変数、取得する関数を定義します。
OpenRestySample.new = function(manager)
local obj = {}
(省略)
obj.input_data = {0,0}
function obj:getData()
return self.input_data
end
OpenRestySample.luaのonExecute関数を以下のように編集してください。
function obj:onExecute(ec_id)
if self._inIn:isNew() then
local data = self._inIn:read()
self.input_data[1] = data.data[1]
self.input_data[2] = data.data[2]
end
return self._ReturnCode_t.RTC_OK
end
入力データはgetData関数で取得できます。
編集したOpenRestySample.luaをrtc-server\luaにコピーしてください。

image.luaの編集image.luaに以下のように記述してください。
package.path = package.path..";./lua/?.lua"
package.cpath = package.cpath..";./clibs/?.dll"
local oil = require "oil"
local openrtm = require "openrtm"
local OpenRestySample = require "OpenRestySample"
local cjson = require "cjson"
local args = ngx.req.get_uri_args()
local command = tostring( args.command )
if command == "start" then
local f = io.open("public/images/sample.html", "r")
local content = f:read("*all")
f:close()
local MyModuleInit = function(manager)
OpenRestySample.Init(manager)
local comp = manager:createComponent("OpenRestySample")
end
if oil.corba == nil then
oil.corba = {}
oil.corba.idl = {}
end
local manager = openrtm.Manager
manager:init({"-o","logger.enable:NO","-o","exec_cxt.periodic.type:OpenHRPExecutionContext"})
manager:setModuleInitProc(MyModuleInit)
manager:activateManager()
manager:runManager(true)
ngx.say(content)
elseif command == "update" then
local x = 0
local y = 0
local manager = openrtm.Manager
manager:step()
local comp = manager:getComponent("OpenRestySample0")
local ec = comp:get_owned_contexts()[1]
ec:tick()
local data = comp:getData()
x = data[1]
y = data[2]
ngx.say(cjson.encode({x=x,y=y}))
end
クエリパラメータcommandがstartの場合はRTCを起動します。
commandがupdateの場合はRTCのステップ処理を更新して入力データを取得します。
JSON形式によりサーバークライアントでデータのやり取りを行います。
事前にネームサーバーの起動が必要です。
※OpenRTM-aist 1.2以降ではRT System Editorにネームサーバー起動ボタンがあるため、手順が簡単になっています。
TkJoyStickコンポーネントを入手して、TkJoyStickComp.exeを実行してください。
openresty-1.13.6.1-win32以下のディレクトリを環境変数PATHに設定してください。
rtc-serverの上のディレクトリで以下のコマンドを実行するとWEBサーバーが起動します。
> nginx.exe -p ./
Google Chrome等のWEBブラウザからhttp://localhost:1080/index.html?command=startにアクセスするとRTCが起動します。
まずRTCの起動に成功している場合は、以下のようにネームサービスビューにRTCが表示されます。

Open New System Editorボタンを押してシステムダイアグラムを表示してください。

ネームサービスビューからシステムダイアグラムにRTCをドラックアンドドロップしてください。

TkJoyStick0のposのOutPortを、OpenRestySample0のinのInPortにドラックアンドドロップしてください。

※ステップ実行をしている側のRTC(今回はOpenRestySample0)のconnect関数を呼び出すと接続に失敗します。必ず、今回の場合はTkJoyStick0のposを選択してドラックアンドドロップしてください。
これで通信ができるようになります。
All Activateボタンを押すとTkJoyStick0からデータが送信されるためWEBブラウザ上の画像が動くようになります。

imahe.luaのmanager:init関数の引数を以下のように変更してください。
manager:init({"-o","logger.enable:NO","-o","exec_cxt.periodic.type:OpenHRPExecutionContext", "-o", "manager.components.preconnect:OpenRestySample0.in?port=rtcname://localhost/TkJoyStick0.pos", "-o", "manager.components.preactivation:OpenRestySample0,rtcname://localhost/TkJoyStick0","-o","corba.step.count:4"})
-oオプションでパラメータの設定ができます。
"-o", "manager.components.preconnect:OpenRestySample0.in?port=rtcname://localhost/TkJoyStick0.pos"起動時に接続するポートを指定します。 この場合はOpenRestySample0というRTCのinというデータポートを、TkJoyStick0というRTCのposというポートに接続します。
ただし、TkJoyStick0は別プロセスで起動しているため、rtcname形式による指定が必要になります。 rtcname形式はネームサーバーからRTCを取得する方法です。rtcname://アドレス/RTC名.ポート名で指定します。
"-o","manager.components.preactivation:OpenRestySample0,rtcname://localhost/TkJoyStick0"起動時にアクティブ化するRTCを指定します。
"-o","corba.step.count:4"ORBをステップ実行するときのみ有効なオプションです。 指定回数だけORBをステップ実行します。ORBから処理要求がない場合は、要求があるまで待ちます。 preconnect等で外部のRTCと接続する場合に必要です。
今回はInPortのみを使用しましたが、OutPortを使用する場合についてはデータ転送の際に以下のようにoil.main関数で実行する必要があります。
また、サービスポートのプロバイダ側についても同じです。
oil.main関数で実行する必要があるのは、今回のようにORBをステップ実行した時のみです。
oil.main(function()
self._outOut:write()
end)