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が彼の答えで提案し、より良い問題を追跡するためにやった
、両方のマシンでUDPパケットが失われているように見えます(PCのログには、途中で送信が停止しないというメッセージが表示されます)。ここでは、同じコードを実行している両方のマシンからのログです:
私の最初の考えは "ガベージコレクション"です。したがって、jconsoleを使用してアプリケーションのヒープ使用状況を監視したり、GCログをアクティブにして、VMのメジャーGCがアプリケーションの「フリーズ」と相関するかどうかを調べることができます。別の入力スレッドを使用すると、生産性が低下し、GCチューニングを行う必要があります。 –
GCチューニングの方法はありますか?私はJavaのエキスパートではありません –