RTM-Lua

View the Project on GitHub Nobu19800/RTM-Lua

LÖVE上で動作するRTCの作成方法

概要

このページではゲームエンジンLÖVE上で動作する上で動作するRTCを作成して、以下のようにPython版サンプルコンポーネントのジョイスティックコンポーネントと接続して物体を操作するシステムの作成を行います。

LÖVEの入手

以下からLÖVEを入手してください。

※LÖVEの新しいバージョンで色が描画されない不具合があります。問題が発生した場合はLÖVEの0.10.2を入手してください。

LÖVEにOpenRTM Lua版をインストール

LÖVEを展開したフォルダにOpenRTM Lua版の各ファイルをコピーします。

以下からOpenRTM Lua版ファイル一式(OpenRTM Lua x.y.z Lua5.1 64bit(もしくは32bit))をダウンロードしてください。 32bit版のLÖVEを使用する場合は32bit版、64bit版のLÖVEを使用する場合は64bit版を使用します。

OpenRTM Lua版からLÖVEにファイルをコピーします。

openrtm-lua-x.y.z-x64-lua5.1\luaフォルダをlove-11.1.0-win64\以下にコピーしてください。

love2d-1

次にopenrtm-lua-x.y.z-x64-lua5.1\clibs\以下のファイルを全てlove-11.1.0-win64\以下にコピーしてください。

love2d-2

RTC作成

RTC BuilderによるRTCの基本的な作成手順は以下のページを参考にしてください。

上のページの作成手順に従って、以下の仕様のRTCを作成してください。

基本プロファイル

   
モジュール名 LOVESample

アクティビティ

onExecuteを有効にしてください。

インポート

   
ポート名 in
データ型 TimedFloatSeq

LOVESample.luaの編集

LOVESample.luaに物理オブジェクトを設定するためのsetObject関数を追加します。

LOVESample.new = function(manager)
	local obj = {}
  (省略)
	function obj:setObject(objects)
		self._objects = objects
	end

LOVESample.luaのonExecute関数を編集します。

	function obj:onExecute(ec_id)
		if self._inIn:isNew() then
			local data = self._inIn:read()
			self._objects.ball.body:applyForce(data.data[1], 0)
			if data.data[2] > 100 then
				self._objects.ball.body:setPosition(650/2, 650/2)
				self._objects.ball.body:setLinearVelocity(0, 0)
			end
		end
		return self._ReturnCode_t.RTC_OK
	end

InPortのデータを読み込んで、左右の操作でボールに力を加える。 上に動かした場合はボールの位置、速度を初期化する。

編集したLOVESample.lualove-11.1.0-win64\lua\以下にコピーしてください。

love2d-3

新規ゲームの作成

適当な場所にフォルダ(今回はLOVESampleGameフォルダ)を新規作成してください。 その中にmain.luaを作成してください。

今回はPhysicsのチュートリアルのソースコードを変更したものを作成します。

まず、初期化時に一度だけ呼び出されるlove.load()関数を編集します。

LÖVEは内部でLuaSocketをロードするため、全て無効化します。

function love.load()
    package.preload["mime.core"] = nil
    package.preload["socket.ftp"] = nil
    package.preload["socket.headers"] = nil
    package.preload["socket.url"] = nil
    package.preload["socket.smtp"] = nil
    package.preload["socket.http"] = nil
    package.preload["socket.core"] = nil
    package.preload["socket.tp"] = nil
    package.preload["mime"] = nil
    package.preload["socket"] = nil

    local openrtm = require "openrtm"


    local mgr = openrtm.Manager
    mgr:init({"-o","exec_cxt.periodic.type:OpenHRPExecutionContext","-o","manager.components.precreate:LOVESample","-o","manager.components.preconnect:LOVESample0.in?port=rtcname://localhost/TkJoyStick0.pos","-o","manager.components.preactivation:LOVESample0,rtcname://localhost/TkJoyStick0","-o","corba.step.count:4"})
    mgr:activateManager()
    mgr:runManager(true)
    
    -- チュートリアルのコード
    love.physics.setMeter(64) --the height of a meter our worlds will be 64px
    (省略)
    love.window.setMode(650, 650) --set the window dimensions to 650 by 650
    -------------------------------------------------------------------------
    
    
    local comp = mgr:getComponent("LOVESample0")
    comp:setObject(objects)
end

基本は上記のコードのLOVESampleの部分を変更すると、他のRTCにも適用できるようになります。

mgr:init関数の引数について説明します。 -oオプションの後にパラメータを指定します。

実行コンテキストの指定をしています。 LÖVE上ではRTCをステップ実行したいのでOpenHRPExecutionContextという実行コンテキストを指定します。

起動時に生成するRTC名を指定します。

起動時に接続するポートを指定します。 この場合はLOVESample0というRTCのinというデータポートを、TkJoyStick0というRTCのposというポートに接続します。

ただし、TkJoyStick0は別プロセスで起動しているため、rtcname形式による指定が必要になります。 rtcname形式はネームサーバーからRTCを取得する方法です。rtcname://アドレス/RTC名.ポート名で指定します。

起動時にアクティブ化するRTCを指定します。

ORBをステップ実行するときのみ有効なオプションです。 指定回数だけORBをステップ実行します。ORBから処理要求がない場合は、要求があるまで待ちます。 preconnect等で外部のRTCと接続する場合に必要です。

love.update関数は以下のように編集します。

function love.update(dt)
    world:update(dt)
    
    local openrtm = require "openrtm"
    local mgr = openrtm.Manager
    mgr:step()

    local comp = mgr:getComponent("LOVESample0")
    local ec = comp:get_owned_contexts()[1]
    ec:tick()
end

love.draw関数はチュートリアルのコードと同じです。

動作確認

ネームサーバー起動

事前にネームサーバーの起動が必要です。

※OpenRTM-aist 1.2以降ではRT System Editorにネームサーバー起動ボタンがあるため、手順が簡単になっています。

TkJoyStickコンポーネントの起動

TkJoyStickコンポーネントを入手して、TkJoyStickComp.exeを実行してください。

RTC起動

LOVESampleGameフォルダをlove.exeにドラッグアンドドロップするとゲームを開始します。

love2d-4

RTSystem作成

起動時にポートの接続、アクティブ化をオプションで設定しているため、RT System Editorでの操作は不要ですが、念のためRT System Editorによる操作手順も説明します。

まずRTCの起動に成功している場合は、以下のようにネームサービスビューにRTCが表示されます。

love2d-5

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

love2d-6

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

love2d-7

TkJoyStick0posのOutPortを、LOVESample0inのInPortにドラックアンドドロップしてください。 これで通信ができるようになります。

love2d-8

※ステップ実行をしている側のRTC(今回はLOVESample0)のconnect関数を呼び出すと接続に失敗します。必ず、今回の場合はTkJoyStick0posを選択してドラックアンドドロップしてください。

All Activateボタンを押すとTkJoyStick0からデータが送信されるため操作ができるようになります。

love2d-9

注意事項

今回はInPortのみを使用しましたが、OutPortを使用する場合についてはデータ転送の際に以下のようにoil.main関数で実行する必要があります。 また、サービスポートのプロバイダ側についても同じです。 oil.main関数で実行する必要があるのは、今回のようにORBをステップ実行した時のみです。

oil.main(function()
	self._outOut:write()
end)