We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I am currently trying to setup a LAN between two computers, to send motion tracking data from one location to another. My code appears to work for a random length of time (anything from 2 seconds up to a minute) I either get one of two errors on different lines of code: StringIndexOutofBoundsException: String index out of range: -1 OR ArrayIndexOutofBounds: 1 I have commented in the code which lines I am getting the errors on.
I really have no idea why this is happening - could it be something to do with the rate at which the data is being sent i.e. frameRate? Or am I doing something wrong when parsing the strings into arrays?
There doesn't seem to be any correlation between the data that it crashes on, all I can think of at the moment is that it is something to do with the data not communicating quickly enough? I tried it on a frameRate of 10, and it seemed to work for longer, but I'm not sure if that was just a coincidence. The data continues to be generated and sent from the server but the client stops responding.
Any help would be greatly appreciated.
This is the client code (the one it crashes on that needs work):
import processing.net.*;
Client c;
String input;
String inputB;
String data[];
float xArr[];
float yArr[];
void setup()
{
size(displayWidth, displayHeight);
background(204);
stroke(0);
frameRate(10); // Slow it down a little
// Connect to the server's IP address and port
c = new Client(this, "192.168.0.2", 61514); // Replace with your server's IP and port
}
void draw()
{
// Receive data from server
if (c.available() > 0) {
input = c.readString();
println("Input");
println(input);
inputB = input.substring(0, input.indexOf("\n")); // Only up to the newline - this is where the first error happens
data = split(inputB, '#'); // Split values into an array
println("Data");
printArray(data);
xArr = float(split(data[0], ":"));
yArr = float(split(data[1], ":")); //this is where the second error happens (if it gets past the first one)
for(int i = 0; i < yArr.length ; i++){
strokeWeight(4);
point(xArr[i],yArr[i]);
}
println("Arrays");
println(xArr);
println(yArr);
}
//println(input);
//println(data);
}
This is the server code:
//setting up the server
import processing.net.*;
Server s;
Client c;
String input;
int data[];
//imports Kinect lib
import SimpleOpenNI.*;
//defines variable for kinect object
SimpleOpenNI kinect;
//declare variables for mapped x y values
float x, y;
//declare variable for number of people
float peopleNum = 0;
//initialise other variables that we might need
int userId;
float inches;
int count = 0;
//set up arrays for all values - current x/y, previous x/y, depth
float[] oldXVals;
float[] newXVals;
float[] oldYVals;
float[] newYVals;
float[] storeDepth;
void setup() {
//set the display size to full screen
size(displayWidth, displayHeight);
//declares new kinect object
kinect = new SimpleOpenNI(this);
//enable depth image
kinect.enableDepth();
//enable user detection
kinect.enableUser();
frameRate(10);
//set background to white
background(255);
//initialise starting array lengths
oldXVals = new float[20];
newXVals = new float[20];
oldYVals = new float[20];
newYVals = new float[20];
storeDepth = new float[20];
//start a simple server on a port
s = new Server(this, 61514); // Start a simple server on a port
}
void draw() {
//updates depth image
kinect.update();
//draws depth image - if we don't need this comment out
//image(kinect.depthImage(),0,0,displayWidth,displayHeight);
//array to store depth values
int[] depthValues = kinect.depthMap();
//access all users currently available to us
IntVector userList = new IntVector();
kinect.getUsers(userList);
//sets variable peopleNum to the number of people currently detected by the kinect
peopleNum = userList.size();
//change the length of the array to the number of people currently present
newXVals = new float[int (peopleNum)];
newYVals = new float[int (peopleNum)];
storeDepth = new float[int (peopleNum)];
//for every user detected, do this
for (int i = 0; i<userList.size (); i++) {
//get the userId
userId = userList.get(i);
//declare PVector position to store x/y position
PVector position = new PVector();
//get the position
kinect.getCoM(userId, position);
kinect.convertRealWorldToProjective(position, position);
//calculate depth
//find the position of the center of mass *640 to give us a number to find in depth array
int comPosition = int(position.x) + (int(position.y) * 640);
//locate it in the depth array
int comDepth = depthValues[comPosition];
//calculate distance in inches
inches = comDepth / 25.4;
//map x and y coordinates to full screen
x = map(position.x, 0, 640, 0, displayWidth);
y = map(position.y, 0, 480, 0, displayHeight);
//store current values for each user in arrays
newXVals[i] = x;
newYVals[i] = y;
//store depth values in array for each user (just the current values)
storeDepth[i] = inches;
//DRAW THINGS HERE
//To draw with only the current values, use newXVals and newYVals
//i corresponds to position in array
//setting these parameters means there is no "drop off" at the edges
if (newXVals[i] >= 50 && newXVals[i] <= width - 50) {
if (newYVals[i] >= 50 && newYVals[i] <= height - 50)
//setting this parameter means that if a person is too close (less than 35 inches), they are ignored
if (storeDepth[i] >= 35) {
strokeWeight(4);
point(newXVals[i], newYVals[i]);
}
}
//prints each userId with its corresponding x/y values
//println("User: " + userId + " xPos: " + x + " yPos: " + y + " depth: " + inches);
//prints the number of people present continuously
//println("There are " + numPeople + " people present");
}
if(newXVals.length >= 1 && newYVals.length >= 1){
String[] newXValsString = nfc(newXVals, 1);
//println(newXValsString);
String joinedXVals = join(newXValsString, ":");
String[] newYValsString = nfc(newYVals, 1);
//println(newYValsString);
String joinedYVals = join(newYValsString, ":");
s.write(joinedXVals + "#" + joinedYVals + "\n");
println(joinedXVals + "#" + joinedYVals + "\n");
}
//copy new value arrays to old value arrays
arrayCopy(newXVals, oldXVals);
arrayCopy(newYVals, oldYVals);
}
Answers
well, indexOf returns -1 if it doesn't find the character in the string and -1 is an invalid value for substring.
so, assign the value of the indexOf to a local variable and check it before using it in the substring.
if the inputB doesn't have a # in it then split won't result in two elements in the data array. you can check this before trying to access the second element
both of these can and should be avoided with better error checking. or, indeed, any error checking. don't just use values without checking they are valid.
you print the values out, so it should be able to check the above is happening, try and find out when it happens. i would suggest, though, using
println("[" + input + "]");
so that you can see the whitespaceSeems obvious now, thanks!!