JMXおよびIPビデオを介したレゴマインドストームロボットのリモートコントロール

メインのLego Mindstorms EV3コンストラクターモジュールはleJOSファームウェアで動作し、Javaアプリケーションを実行できます。 特に、このOracleはリリースされ、完全なJava SEの別バージョンをサポートしています。



通常のJVMでは、組み込みのJava Management Extensions(JMX)プロトコルを使用して、ロボットアームのリモート制御を実装できました。 ロボットにインストールされたIPカメラからの制御要素、センサー測定値、画像を組み合わせるために、AggreGateプラットフォームで作成された模倣図が使用されます。







ロボット自体は、シャーシとマニピュレーターアームの2つの主要部分で構成されています。 これらは2台の完全に独立したEV3コンピューターによって制御され、すべての調整は管理サーバーを介して実行されます。 コンピューター間の直接接続はありません。



両方のコンピューターは、NETGEAR WNA1100 Wi-Fiアダプターを介して部屋のIPネットワークに接続されています。 ロボットは8つのマインドストームエンジンによって制御されます。そのうち4つは「大」、4つは「小」です。 反転時に障害物で自動的に停止する赤外線および超音波センサー、障害物によるマニピュレーターの回転を停止する2つのタッチセンサー、および肩の位置を視覚化してオペレーターの方向を容易にするジャイロセンサーもインストールされています。



シャーシには2つのエンジンが取り付けられており、それぞれのエンジンが追跡対象のドライブのペアに力を伝達します。 別のエンジンがマニピュレーターアーム全体を360度回転させます。







マニピュレータ自体では、2つのエンジンが「肩」と「前腕」を上下させます。 さらに3つのエンジンがブラシの上げ下げを行い、360度回転させて「指」を握り/広げます。







最も複雑な機械ユニットは「ブラシ」です。 3つの重いエンジンを「肘」領域に運ぶ必要があるため、設計は非常に難しいことがわかりました。







一般に、すべては次のようになります(スケールの一致ボックスはほとんど見つかりませんでした)。







写真を転送するために2つのカメラがインストールされています。











EV3プログラミング



ロボット自体のソフトウェアは、可能な限りシンプルであることが判明しました。 2台のコンピューターのプログラムは非常に似ており、JMXサーバーを起動し、エンジンとセンサーに対応するMBeanを登録し、JMX操作を待機している間スリープ状態になります。



マニピュレータアームのソフトウェアの主要なクラスのコード
public class Arm { public static void main(String[] args) { try { EV3Helper.printOnLCD("Starting..."); EV3Helper.startJMXServer("192.168.1.8", 9000); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); EV3LargeRegulatedMotor motor = new EV3LargeRegulatedMotor(BrickFinder.getDefault().getPort("A")); LargeMotorMXBean m = new LargeMotorController(motor); ObjectName n = new ObjectName("robot:name=MotorA"); mbs.registerMBean(m, n); // Registering other motors here EV3TouchSensor touchSensor = new EV3TouchSensor(SensorPort.S1); TouchSensorMXBean tos = new TouchSensorController(touchSensor); n = new ObjectName("robot:name=Sensor1"); mbs.registerMBean(tos, n); // Registering other sensors here EV3Helper.printOnLCD("Running"); Sound.beepSequenceUp(); Thread.sleep(Integer.MAX_VALUE); } catch (Throwable e) { e.printStackTrace(); } } } public class EV3Helper { static void startJMXServer(String address, int port) { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); try { java.rmi.registry.LocateRegistry.createRegistry(port); JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + address + ":" + String.valueOf(port) + "/server"); Map<String, Object> props = new HashMap<String, Object>(); props.put("com.sun.management.jmxremote.authenticate", "false"); props.put("com.sun.management.jmxremote.ssl", "false"); JMXConnectorServer connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, props, server); connectorServer.start(); } catch (Exception e) { e.printStackTrace(); } } static void printOnLCD(String s) { LCD.clear(); LCD.drawString(s, 0, 4); } }
      
      











センサーとモーターのタイプごとに、MBeanインターフェースが作成され、それを実装するクラスが、leJOS APIに含まれるクラスへのすべての呼び出しを直接委任します。



インターフェイスコードの例
 public interface LargeMotorMXBean { public abstract void forward(); public abstract boolean suspendRegulation(); public abstract int getTachoCount(); public abstract float getPosition(); public abstract void flt(); public abstract void flt(boolean immediateReturn); public abstract void stop(boolean immediateReturn); public abstract boolean isMoving(); public abstract void waitComplete(); public abstract void rotateTo(int limitAngle, boolean immediateReturn); public abstract void setAcceleration(int acceleration); public abstract int getAcceleration(); public abstract int getLimitAngle(); public abstract void resetTachoCount(); public abstract void rotate(int angle, boolean immediateReturn); public abstract void rotate(int angle); public abstract void rotateTo(int limitAngle); public abstract boolean isStalled(); public abstract void setStallThreshold(int error, int time); public abstract int getRotationSpeed(); public abstract float getMaxSpeed(); public abstract void backward(); public abstract void stop(); public abstract int getSpeed(); public abstract void setSpeed(int speed); }
      
      











MBean実装コード例
 public class LargeMotorController implements LargeMotorMXBean { final EV3LargeRegulatedMotor motor; public LargeMotorController(EV3LargeRegulatedMotor motor) { this.motor = motor; } @Override public void forward() { motor.forward(); } @Override public boolean suspendRegulation() { return motor.suspendRegulation(); } @Override public int getTachoCount() { return motor.getTachoCount(); } @Override public float getPosition() { return motor.getPosition(); } @Override public void flt() { motor.flt(); } @Override public void flt(boolean immediateReturn) { motor.flt(immediateReturn); } // Similar delegating methods skipped }
      
      











奇妙なことに、ここでプログラミングが終了します。 サーバー側とオペレーターワークステーションでは、1行のコードも書かれていません。



サーバー接続



ロボットはAggreGate IoTプラットフォームサーバーによって直接制御されます。 インストールされた無料バージョンのAggreGate Network ManagerにはJMXプロトコルドライバーが含まれており、最大10台のJMXホストに接続できます。 EV3ブリックごとに1つずつ-2つ接続する必要があります。



まず、設定でJMXサーバーの起動時に指定されたURLを指定して、JMXデバイスアカウントを作成する必要があります。



JMXデバイスの接続プロパティ






その後、デバイスプロファイルに追加するアセット(この場合はMBean)を選択します。



MBeanの選択






そして、数秒後、MBeanのすべてのポーリングされたプロパティの現在の値を調べて変更します。



デバイスのスナップショット






forward()やstop()など、MBeanを手動で呼び出すことで、さまざまな操作をテストすることもできます。



操作のリスト






次に、センサーのポーリング期間を構成します。 制御サーバーはロボットとのローカルネットワークに配置されているため、高いポーリング頻度(1秒あたり100回)が使用され、障害物などに対して停止したときに回転を停止するかどうかを決定するサーバーです。 もちろん、このソリューションは産業用ではありませんが、1つのアパートメントのフレームワーク内で適切に機能するWi-Fiネットワークでは、非常に適切であることが証明されました。



ポーリング期間






オペレーターインターフェース



次に、オペレーターインターフェイスの作成に進みます。 これを行うには、まず新しいウィジェットを作成し、それに必要なコンポーネントをスローします。 最終的な作業バージョンでは、次のようになります。







実際、インターフェイス全体は、さまざまなグリッドレイアウトにグループ化されたボタン、スライダー、インジケーターを備えた複数のパネルと、カメラから画像をブロードキャストする2つの大きなビデオプレーヤーで構成されています。



インターフェイスエディターの内部ビュー
全体の形式:





コンテナパネルを表示したビュー:







現在、ASUTPshnikiが言うように、それは「ニーモニック図を復活させる」ままです。 このために、インターフェイスのグラフィックコンポーネントのプロパティとメソッドをサーバーオブジェクトのプロパティとメソッドに接続する、いわゆるバインディングが使用されます。 EV3コンピューターは既にサーバーに接続されているため、ロボットのMBeanはサーバーオブジェクトにもなります。



オペレーターインターフェイス全体には約120のバインディングが含まれ、そのほとんどは同じタイプです。







同じタイプのバインディングの半分は、ニーモニックダイアグラムにあるボタンをクリックすることで制御を実装します。 美しく、テストには便利ですが、ロボットの実際の動きや商品の動きにはまったく適していません。 このグループのバインディングのアクティベーターは、さまざまなボタンのmousePressedおよびmouseReleasedイベントです



バインディングの後半では、最初にキーボード制御ボタンを押すことにより、キーボードからロボットを制御できます。 これらのバインディングはkeyPressedおよびkeyReleasedイベントに応答し、各バインディングの状態で、応答するボタンコードが書き込まれます。



すべてのコントロールバインディングは、さまざまなMBeanのforward()backward()、およびstop()メソッドを呼び出します。 イベントの配信は非同期で行われるため、 forward() / backward()関数の呼び出しと、その後のstop()の呼び出し混同さないことが重要です。 このため、1つのMBeanのメソッドを呼び出すバインディングが同じキューに追加されます。



バインディングの2つの別個のグループは、エンジンの初期速度と加速を設定し(現在、モデルを使用してサーバー側に実装されているため、これらのバインディングは無効になっています)、速度および加速スライダーを移動するときに速度/加速を変更します。



モーター速度と加速度のバインディング






他のすべてのバインディングは、タッチセンサーがアクティブになったときに模倣図の一部を強調表示し、スケールでセンサーによって測定されたオブジェクトまでの距離を表示し、さまざまなサービス機能を実行します。



その他のバインディング






上記のJMXデバイスとウィジェットのアカウントに加えて、サーバーにはロボットの制御に関与する別のオブジェクトがあります。 これは、タッチセンサーの1つがトリガーされたときにエンジンを停止するモデルです。 これもバインディングの助けを借りて行われます。バインディングとウィジェットのバインディングの違いは、モデルバインディングがサーバーで処理され、サーバーオブジェクトの一部のプロパティを他のプロパティにバインドすることです。



モデルバインディングの制御






ウィジェットとモデルをセットアップした後、ウィジェットを起動し、キーボードコントロールを有効にして楽しんでください:






All Articles