Code: Select all
/*
* Created by SharpDevelop.
* User: leith
* Date: 11/19/2007
* Time: 2:20 PM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using OptiTrack;
namespace FIEMCOptiTrack
{
/// <summary>
/// Description of Server2D.
/// </summary>
///
public class CameraFrameJob{
public CameraFrameJob(){}
public FIEIPC.PostalSystem postalSystem;
public FIEMCMessaging.CameraFrame camFrame;
public System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter;
public void DoJob(object info){
FIEIPC.Message mes = new FIEIPC.Message();
mes.Type = (int)FIEMCMessaging.MessageTypes.CameraFrame;
System.IO.MemoryStream ms = new System.IO.MemoryStream();
lock (formatter){
formatter.Serialize(ms, this.camFrame);
}
mes.Data = ms.ToArray();
this.postalSystem.SendMessage(mes);
}
}
public class Server2D
{
private int port;
public Server2D(int port)
{
this.port = port;
}
public void Start(){
FIEIPC.PostalSystem postalSystem = new FIEIPC.PostalSystem();
postalSystem.Listen(this.port);
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
OptiTrack.NPCameraCollectionClass cameras = new NPCameraCollectionClass();
cameras.Enum();
cameras.Synchronize();
foreach (NPCamera cam in cameras){
InitCamera(cam);
}
FIEMCMessaging.CameraFrame camFrame = new FIEMCMessaging.CameraFrame();
bool closeRequested = false;
while (!closeRequested){
int frames = 0;
int points = 0;
foreach (NPCamera cam in cameras){
OptiTrack.NPCameraFrame frame = null;
frame = cam.GetFrame(0);
while (frame != null){
if (frame.IsEmpty){
// TODO: handle empty frame
} else if (frame.IsCorrupt){
// TODO: handle corrupt frame
} else if (frame.IsGreyscale){
// TODO: handle greyscale frame
} else {
// frame is normal
camFrame.BlipCollection.Clear();
foreach (NPObject trkobj in frame){
FIEMCMessaging.Blip blip = new FIEMCMessaging.Blip();
blip.area = (double)trkobj.Area;
blip.height = trkobj.Height;
blip.width = trkobj.Width;
blip.rank = (double)trkobj.Rank;
blip.score = (double)trkobj.Score;
blip.x = (double)trkobj.X;
blip.y = (double)trkobj.Y;
camFrame.BlipCollection.Add(blip);
}
camFrame.id = frame.Id;
camFrame.timestamp = (double)frame.TimeStamp;
camFrame.freq = (double)frame.TimeStampFrequency;
camFrame.serial = cam.SerialNumber;
frames++;
points = points + frame.Count;
CameraFrameJob job = new CameraFrameJob();
job.postalSystem = postalSystem;
job.camFrame = camFrame;
job.formatter = formatter;
System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(job.DoJob));
}
frame.Free();
frame = null;
frame = cam.GetFrame(0);
}
FIEIPC.Message inmes = postalSystem.GetMessage();
while (inmes != null){
//deal with requests here
switch (inmes.Type){
case (int)FIEMCMessaging.MessageTypes.CloseRequest:
closeRequested = true;
break;
}
inmes = postalSystem.GetMessage();
}
}
}
postalSystem.Stop();
}
private void InitCamera(NPCamera cam){
cam.SetLED(0, true);
cam.SetLED(1, true);
cam.SetLED(2, false);
cam.Open();
cam.Start();
}
}
}
To diagnose this, I moved my serialization code to a worker thread at first, thinking it was my slow code getting in the way. However when that didn't work, I started commenting out lines until I found that it was specifically the lines that call the NPObject properties that are the culprits.
furthermore, I've run this piece of code both as a thread within a consumer application, and as its own process, wrapped in its own exe (both with a consumer app connected and without). The communication is via network socket in both cases. The consumer app does not call the naturalpoint sdk at all. And no matter the config, the NPObject accessors are the difference.
Granted, those property accessors are being called WAY more often than anything else in the NaturalPoint SDK and anything else that is coming through COM, so it could be that its a general SDK performance problem or a general COM performance problem rather than being specific to the NPObject object.
So I'm kinda stumped as to where to go now. My next approach would be to go with c++ directly in hopes of jumping over a .netCOM bottleneck that may or may not be there, but I'd rather not go that route. What do you guys think is the performance issue here? What kind of potential solutions do you see?