2017-01-11 4 views
0

Unity C#アプリケーションを実行しているPCでネットワーク経由で他のマシンに数ミリ秒ごとにUDPパケットを送信しています(Windows 7上の2 KUKAロボット同じJavaプログラム、i5プロセッサーを搭載しているので、かなり強力です)。 Javaプログラムはこれらのパケットを受信し、その内容(ロボット位置、 '#'で区切られた7つの値の配列でコード化されている)を解析し、移動して再度読み取ることになっています。問題は、PCが0.02秒ごとに1の割合でパケットを送信すると(これは0.03以上では起こらない、ハードウェアの限界ですか?)、Javaプログラムは受信した約1000パケットでフリーズします986など)を8-10秒間押してから、もう一度再開します。それが2000年に到着したときに同じことを、そして3000
プログラムはでフリーズ:私は直接ロボット上にPCを接続しますが、何も変わっていない、ネットワークスイッチを疑わJavaプログラムが約1000 UDPを受信した後に10秒間フリーズDatagramPacketsが再び再開

serverSocket.receive(receivedPacket); // receives the array of Bytes 

。奇妙なことは、2台のロボットのために同時に起こることで、PCが疑わしいと思った。しかし、私の同僚が、C#プログラムがパケットを送信するリアルタイムでコンソールを表示し始めたとき、Javaプログラムがフリーズしたときにフリーズせず、これらのパケットが失われたように見えました。
私はSOに関する多くの疑いのあるバッファを探しました。そのため、UDPポートを待ち受け、パケットをメモリ上のキューに格納すると、メインのJavaプログラムはそのスレッドから読み込みます。それは実行可能なトラックのように見えますか? ご提案は大歓迎です。

P.S.ここでは、コードです:


package readers; 

import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.SocketException; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class MyProgram { 
    // Network variables 
    public static DatagramSocket serverSocket; 
    private static DatagramPacket receivedPacket; 

    // Received data variables 
    private static byte[] aReceivedData = new byte[1024]; 
    private static String sReceivedData; 
    private static String sAxesInformationReceived; 
    private static Double[] dAxesInformationReceived = new Double[7]; 

    // ******** MAIN *************************************** 
    public static void main(String[] args) throws Exception { 
     int mFramecount =0; 
     int mPort = 30004; //default value 
     int mTimeout = 20*1000; //default value 
     int mFramelimit = (15 * 1000); //default value 

     // Create UDP server socket 
     try { 
      serverSocket = new DatagramSocket(mPort); 
      serverSocket.setReuseAddress(true); 
      serverSocket.setSoTimeout(mTimeout); 
     } catch (SocketException e) 
     { System.err.println("socket bind fail"); closeSocket();e.printStackTrace(); return; } 

     // Receive the UDP packet 
     try { 
      receivedPacket = new DatagramPacket(aReceivedData, aReceivedData.length); 
      serverSocket.receive(receivedPacket); // receive the array of Bytes 
     } catch (Exception e) { closeSocket(); return; } 
     //Clear Buffer 
     for (int i = 0; i < 7; i++) { 
      if(dAxesInformationReceived[i] == null) 
      { 
       dAxesInformationReceived[i] = 0.0; 
      } 
     } 


     // <<<<<<<<<<<WHILE <<<<<<<<<<<<<<<<<<<< 
     while (true) {   

      //Clear Buffer 
      for(int i=0; i < aReceivedData.length; i++) 
      { 
       aReceivedData[i]=0; 
      } 


      // Decoding and Parsing received values 
      try { 

       receivedPacket = new DatagramPacket(aReceivedData, aReceivedData.length); 
       serverSocket.receive(receivedPacket); // receive the array of Bytes 

       byte[] byteData = new byte[receivedPacket.getLength()]; 
       System.arraycopy(receivedPacket.getData(), receivedPacket.getOffset(), byteData, 0, receivedPacket.getLength()); 
       sReceivedData = new String(byteData, "UTF-8"); 
       Pattern pattern = Pattern.compile("@(.*?)@"); // RegEx 
       Matcher matcher = pattern.matcher(sReceivedData); 
       System.out.println("Data: '" + sReceivedData + "', || length: " + byteData.length + "|| Frame count="+ mFramecount ++); 

       /* 
       * mFramecount++; 
         if (mFramecount %100 == 0) { 
          System.out.println("Data: '" + sReceivedData + "', || length: " + byteData.length + "|| Frame count="+ mFramecount); 
         } 
       */ 

       if (matcher.find()) { 
        sAxesInformationReceived = matcher.group(1); 
        String[] sAxesValuesInStringArray = sAxesInformationReceived.split("#"); 
        if (sAxesValuesInStringArray.length != 7) { 
         System.err.println("[UnityControl] invalide number of axis"); 
         break; 
        } 
        for (int i = 0; i < 7; i++) { 
         dAxesInformationReceived[i] = Double.parseDouble(sAxesValuesInStringArray[i]); 
        } 
       } else { 
        System.err.println("[UnityControl] invalid format"); 
        break; 
       } 
      } catch (Exception e) { 
       System.err.println("[UnityControl] socket exception"); 
       e.printStackTrace(); 
       break; 
      } 



      /* THIS PART IS USING THE ROBOT's API */ 
      // Change destination according to the received position 
      JointPosition framePos = new JointPosition(
        Math.toRadians(dAxesInformationReceived[0]), 
        Math.toRadians(dAxesInformationReceived[1]), 
        Math.toRadians(dAxesInformationReceived[2]), 
        Math.toRadians(dAxesInformationReceived[3]), 
        Math.toRadians(dAxesInformationReceived[4]), 
        Math.toRadians(dAxesInformationReceived[5]), 
        Math.toRadians(dAxesInformationReceived[6])); 

      try { 
       if(runtime.setDestination(framePos)<0) 
        break; // break when error planning robot motion 
      } 
      catch(Exception e) 
      { 
       System.err.println("Runtime exeption"); 
       break; 
      } 

      if(mFramecount >= mFramelimit) break; 


     } 
     // LOOP BACK 
    } 

    //********************************************************************** 
    static void closeSocket() { 
     if (serverSocket != null) { 
      serverSocket.disconnect(); 
      serverSocket.close(); 
      System.out.println("[UnityControl] socket closed"); 

     } 
    } 

} 

私は、私はその最後にパケットの数を追加したものを@EJPが彼の答えで提案し、より良い問題を追跡するためにやった

screenshot

、両方のマシンでUDPパケットが失われているように見えます(PCのログには、途中で送信が停止しないというメッセージが表示されます)。ここでは、同じコードを実行している両方のマシンからのログです:

Log two machines

+0

私の最初の考えは "ガベージコレクション"です。したがって、jconsoleを使用してアプリケーションのヒープ使用状況を監視したり、GCログをアクティブにして、VMのメジャーGCがアプリケーションの「フリーズ」と相関するかどうかを調べることができます。別の入力スレッドを使用すると、生産性が低下し、GCチューニングを行う必要があります。 –

+0

GCチューニングの方法はありますか?私はJavaのエキスパートではありません –

答えて

0

という問題が世界を止めるというものを作っているあなたGC(ガベージコレクション)である確率が高いです。世界のアプリケーションを停止し、使用されていないオブジェクトからメモリをクリーンアップしてください:)。プログラムのPIDを取得し、jconsoleを接続してメモリの状況を確認できます。

さらにメモリを設定すると役立つ可能性があります。 javaの-Xms1024m -Xmx1024m -Xms設定された初期のJavaヒープサイズ -Xmxは最大Javaヒープサイズに

を設定し、あなたが多くのスレッドを使用している場合は、スレッドを作成するので、メモリ、時間がかかる可能性がある - あなたは、スレッドを使用することができますプール。

不幸なことに、私はコードなしでさらにあなたを助けることができません。

+0

私は自分のプログラムのメインから起動したRunnableを1つだけ使用していました。擬似コードは非常に簡単です: '(真)しながら{ - UDPパケット のを待ちます - 値 をパース - 受信した位置 にロボットを動かし}' 私はそれの私の質問にコードを追加することができ –

+0

を支援今、私は同じスレッド内のすべてを一括して、問題が構成されます。 –

+0

あなたは本当にいくつかのコードを投稿する必要があります。それを理解しようとする方がはるかに簡単です。 –

0

あなたは必要以上に多くのゴミを作り出しています。あなたはまったくbyteArrayを必要とする、またはSystem.arraycopy()ません:あなたはまた、Patternに同じ正規表現を再コンパイル維持する必要はありません

sReceivedData = new String(receivedPacket.getData(), 0, receivedPacket.getLength(), "UTF-8"); 

受信前にバイト配列を0にする必要もありません。

NB DatagramSocketを構築して(従ってそれに結合する)、の後にsetReuseAddress()を呼び出すことは、完全な時間の無駄である。

+0

私はあなたが言ったことをしましたが、問題はまだそこにあります。質問に受信機のログのスクリーンショットを追加しました。 –

+0

ここでは、単純なプロトコルをデコードするために、 'String'、正規表現、' Pattern'、 'Matcher'が本当に必要ないことを指摘します。バイト配列を直接処理するだけです。予期されるヘッダーと予告編があることを確認してから、無視して内容を確認してください。 – EJP

+0

あなたはそれが過度だと思いますか? ありがとう、私はそれを試してみます。 –

関連する問題