OpenNI and multiple kinects (avin2 SensorKinect), Ubuntu 10.10

1,449 views
Skip to first unread message

GrrrWaaa

unread,
Feb 13, 2011, 9:31:45 PM2/13/11
to openn...@googlegroups.com
Hi there,

I'm having trouble getting multiple devices (kinect) to work, on Ubuntu 10.10, using the avin2 SensorKinect package. The devices are connected to different USB hubs (as reported by lsusb). 

I've downloaded & installed the unstable OpenNI, NITE and SensorKinect (avin2) packages according to the READMEs. I modified the Sensor-User.xml file with the license key and 640x480 resolution. The Nite sample applications run correctly (if I only have 1 device connected; otherwise they freeze).

I wrote code based on the ROS github to figure out how to enumerate attached devices (see below). 

If I create my context with xn::Context::Init() (as in ROS), it correctly lists two devices, two depth nodes and two image nodes. However, if I try to create a depth generator from them (for example), I get the usual 'Bad parameter' error for not having used a proper configuration XML file. 

On the other hand, if I create the context with xn::Context::InitFromXmlFile(), instead the enumeration results look pretty weird:

device 0 vendor PrimeSense name SensorV2, instance Device1
device 1 vendor PrimeSense name SensorV2, instance
device 2 vendor PrimeSense name SensorV2, instance
depth 0: vendor PrimeSense name SensorV2, instance Depth1 
depth 1: vendor PrimeSense name SensorV2, instance
depth 2: vendor PrimeSense name SensorV2, instance
depth 3: vendor PrimeSense name SensorV2, instance
image 0: vendor PrimeSense name SensorV2, instance
image 1: vendor PrimeSense name SensorV2, instance
image 2: vendor PrimeSense name SensorV2, instance
found 3 device nodes
found 4 depth nodes
found 3 image nodes


If I only create one DepthGenerator from device 0, it works fine. 
If I try to create one from device 1 (whether or not I previously created a device 0), it results in error XN_STATUS_STREAM_OUTPUT_SET_ALREADY_IN_SET ("The set already contains an object of that stream"). 
Device 2 appears to work fine, though it actually connects to the same physical kinect as device 0.
Device 3 results in the 'Bad parameter sent' error. 

I have no idea how to make sense of these behaviors; if anybody here can lend any insight it would be greatly appreciated!

Here's the enumeration code itself:

status = mContext.InitFromXmlFile(initXml.c_str());
if (check("initialization")) return;

// lists of all available nodes:
static xn::NodeInfoList node_info_list;
static xn::NodeInfoList depth_nodes;
static xn::NodeInfoList image_nodes;

// enumerate all devices
status = mContext.EnumerateProductionTrees(XN_NODE_TYPE_DEVICE, NULL, node_info_list);
if (status != XN_STATUS_OK && node_info_list.Begin () != node_info_list.End ()) {
if (check("node list")) return;
}
else if (node_info_list.Begin () == node_info_list.End ()) {
printf("no devices found");
}

for (xn::NodeInfoList::Iterator nodeIt = node_info_list.Begin (); nodeIt != node_info_list.End (); ++nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description = info.GetDescription();
printf("device %d vendor %s name %s, instance %s\n", mDeviceNodes.size(), description.strVendor, description.strName, info.GetInstanceName());
mDeviceNodes.push_back(info);
}

// enumerate depth nodes:
status = mContext.EnumerateProductionTrees(XN_NODE_TYPE_DEPTH, NULL, depth_nodes, NULL);
if (!ok()) {
printf("enumerating depth generators failed. Reason: %s\n", getStatus());
return;
} else {
for (xn::NodeInfoList::Iterator nodeIt = depth_nodes.Begin(); nodeIt != depth_nodes.End(); ++nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description = info.GetDescription();
printf("depth %i: vendor %s name %s, instance %s\n", mDepthNodes.size(), description.strVendor, description.strName, info.GetInstanceName());
mDepthNodes.push_back(info);
}
}

// enumerate image nodes
status = mContext.EnumerateProductionTrees(XN_NODE_TYPE_IMAGE, NULL, image_nodes, NULL);
if (!ok()) {
printf("enumerating image generators failed. Reason: %s\n", getStatus());
return;
} else {
for (xn::NodeInfoList::Iterator nodeIt = image_nodes.Begin(); nodeIt != image_nodes.End(); ++nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description = info.GetDescription();
printf("image %i: vendor %s name %s, instance %s\n", mImageNodes.size(), description.strVendor, description.strName, info.GetInstanceName());
mImageNodes.push_back(info);
}
}
printf("found %d device nodes\n", mDeviceNodes.size());
printf("found %d depth nodes\n", mDepthNodes.size());
printf("found %d image nodes\n", mImageNodes.size());


Creating a depth generator looks like this:


int devicenum = device % mDepthNodes.size();
const xn::NodeInfo& info = mDepthNodes[devicenum];

printf("createDepthStreamForDevice (%i of %i)\n", devicenum, mDepthNodes.size());
printf("creating production tree\n");
status = mContext.CreateProductionTree(const_cast<xn::NodeInfo&>(info));
printf("created production tree\n");
if (!ok()) {
printf("creating depth generator failed. Reason: %s\n", getStatus());
return;
}

// get production node instances
status = info.GetInstance(client.mDepthGenerator);
if (status != XN_STATUS_OK) {
printf("creating depth generator instance failed. Reason: %s\n", getStatus());
return;
}

printf("created depth client \n");

client.mDepthGenerator.GetMetaData(client.mDepthMD);
status = client.mDepthGenerator.StartGenerating();
if (check("Start generating")) return;

grrrwaaa

unread,
Feb 14, 2011, 11:58:59 AM2/14/11
to OpenNI

Suat Gedikli

unread,
Feb 14, 2011, 4:00:09 PM2/14/11
to openn...@googlegroups.com
hi,

if you checkout the ROS driver in the "rewrite" branch, you will see an
example application, which is ROS-independent. Did you try that
application?

Regards,
Suat Gedikli

grrrwaaa

unread,
Feb 18, 2011, 3:08:11 PM2/18/11
to OpenNI
Hi,

I wasn't able to build ROS (calling make complained of missing
directories that appear to be hard paths on your machine - I can send
you the error directly if you wish).

However the following stripped-down program (which basically what the
ROS example is doing), and which is only dependent on OpenNI, shows
the problem. If I initialize the context without an XML file, it
correctly lists two attached devices. This is what the ROS example
does. However when I try to connect to the devices, OpenNI reports
'Bad parameter' errors (as usual for connecting without an XML).
However, if I do use the proper Sample-User.xml file, I get 3 or 4
nodes listed; only the first of which actually connects properly.


#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <XnCppWrapper.h>

using namespace std;

xn::Context context;
XnStatus status;
xn::NodeInfoList device_node_info_list;
xn::NodeInfoList depth_node_info_list;
xn::NodeInfoList image_node_info_list;

int main(int argc, const char * argv[])
{
if (argc > 1) {
status = context.InitFromXmlFile(argv[1]);
} else {
status = context.Init();
}
if (status != XN_STATUS_OK) {
printf("initialization failed. Reason: %s\n", xnGetStatusString
(status));
return -1;
}

// enumerate all devices
printf("devices:\n");
status = context.EnumerateProductionTrees(XN_NODE_TYPE_DEVICE, NULL,
device_node_info_list);
if (status != XN_STATUS_OK && device_node_info_list.Begin () !=
device_node_info_list.End ()) {
printf("enumerating devices failed. Reason: %s", xnGetStatusString
(status));
return -1;
}
for (xn::NodeInfoList::Iterator nodeIt = device_node_info_list.Begin
(); nodeIt != device_node_info_list.End (); ++nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description =
info.GetDescription();
printf("device: vendor %s name %s, instance %s\n",
description.strVendor, description.strName, info.GetInstanceName());
}

// enumerate depth nodes:
printf("depth nodes:\n");
status = context.EnumerateProductionTrees(XN_NODE_TYPE_DEPTH, NULL,
depth_node_info_list, NULL);
if (status != XN_STATUS_OK) {
printf("enumerating depth generators failed. Reason: %s\n",
xnGetStatusString (status));
return -1;
} else {
for (xn::NodeInfoList::Iterator nodeIt =
depth_node_info_list.Begin(); nodeIt != depth_node_info_list.End(); +
+nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description =
info.GetDescription();
printf("depth: vendor %s name %s, instance %s\n",
description.strVendor, description.strName, info.GetInstanceName());
}
}

// enumerate image nodes
printf("image nodes:\n");
status = context.EnumerateProductionTrees(XN_NODE_TYPE_IMAGE, NULL,
image_node_info_list, NULL);
if (status != XN_STATUS_OK) {
printf("enumerating image generators failed. Reason: %s\n",
xnGetStatusString (status));
return -1;
} else {
for (xn::NodeInfoList::Iterator nodeIt =
image_node_info_list.Begin(); nodeIt != image_node_info_list.End(); +
+nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description =
info.GetDescription();
printf("image: vendor %s name %s, instance %s\n",
description.strVendor, description.strName, info.GetInstanceName());
}
}

return 0;
}


RESULTS:

./multiKinectTest ../../Data/Sample-User.xml
devices:
device: vendor PrimeSense name SensorV2, instance Device1
device: vendor PrimeSense name SensorV2, instance
device: vendor PrimeSense name SensorV2, instance
depth nodes:
depth: vendor PrimeSense name SensorV2, instance Depth1
depth: vendor PrimeSense name SensorV2, instance
depth: vendor PrimeSense name SensorV2, instance
depth: vendor PrimeSense name SensorV2, instance
image nodes:
image: vendor PrimeSense name SensorV2, instance
image: vendor PrimeSense name SensorV2, instance
image: vendor PrimeSense name SensorV2, instance

./multiKinectTest
devices:
device: vendor PrimeSense name SensorV2, instance
device: vendor PrimeSense name SensorV2, instance
depth nodes:
depth: vendor PrimeSense name SensorV2, instance
depth: vendor PrimeSense name SensorV2, instance
image nodes:
image: vendor PrimeSense name SensorV2, instance
image: vendor PrimeSense name SensorV2, instance

grrrwaaa

unread,
Feb 18, 2011, 4:25:59 PM2/18/11
to OpenNI
A slight modification to the device enumeration reveals more
information (bus & address):

for (xn::NodeInfoList::Iterator nodeIt = device_node_info_list.Begin
(); nodeIt != device_node_info_list.End (); ++nodeIt) {
const xn::NodeInfo& info = *nodeIt;
const XnProductionNodeDescription& description =
info.GetDescription();
printf("device: vendor %s name %s, instance %s\n",
description.strVendor, description.strName, info.GetInstanceName());
unsigned short vendor_id;
unsigned short product_id;
unsigned char bus;
unsigned char address;
sscanf(info.GetCreationInfo(), "%hx/%hx@%hhu/%hhu", &vendor_id,
&product_id, &bus, &address);
string connection_string = info.GetCreationInfo();
transform (connection_string.begin (), connection_string.end (),
connection_string.begin (), std::towlower);
printf("vendor_id %i product_id %i bus %i address %i connection %s
\n", vendor_id, product_id, bus, address, connection_string.c_str());
}

./multiKinectTest ../../Data/Sample-User.xml
devices:
device: vendor PrimeSense name SensorV2, instance Device1
vendor_id 1118 product_id 686 bus 2 address 6 connection 045e/02ae@2/6
device: vendor PrimeSense name SensorV2, instance
vendor_id 1118 product_id 686 bus 2 address 6 connection 045e/02ae@2/6
device: vendor PrimeSense name SensorV2, instance
vendor_id 1118 product_id 686 bus 1 address 9 connection 045e/02ae@1/9
depth nodes:
depth: vendor PrimeSense name SensorV2, instance Depth1
depth: vendor PrimeSense name SensorV2, instance
depth: vendor PrimeSense name SensorV2, instance
depth: vendor PrimeSense name SensorV2, instance
image nodes:
image: vendor PrimeSense name SensorV2, instance
image: vendor PrimeSense name SensorV2, instance
image: vendor PrimeSense name SensorV2, instance
3 devices, 4 depth nodes, 3 image nodes

./multiKinectTest
devices:
device: vendor PrimeSense name SensorV2, instance
vendor_id 1118 product_id 686 bus 2 address 6 connection 045e/02ae@2/6
device: vendor PrimeSense name SensorV2, instance
vendor_id 1118 product_id 686 bus 1 address 9 connection 045e/02ae@1/9
depth nodes:
depth: vendor PrimeSense name SensorV2, instance
depth: vendor PrimeSense name SensorV2, instance
image nodes:
image: vendor PrimeSense name SensorV2, instance
image: vendor PrimeSense name SensorV2, instance
2 devices, 2 depth nodes, 2 image nodes


FWIW, here is the result of lsusb, which appears to correspond to what
the device enumeration found:

Bus 002 Device 006: ID 045e:02ae Microsoft Corp.
Bus 002 Device 005: ID 045e:02ad Microsoft Corp.
Bus 002 Device 004: ID 045e:02b0 Microsoft Corp.
Bus 002 Device 003: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching
Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 009: ID 045e:02ae Microsoft Corp.
Bus 001 Device 008: ID 045e:02ad Microsoft Corp.
Bus 001 Device 007: ID 045e:02b0 Microsoft Corp.
Bus 001 Device 006: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 001 Device 005: ID 1a40:0101 TERMINUS TECHNOLOGY INC. USB-2.0 4-
Port HUB
Bus 001 Device 004: ID 046d:c31c Logitech, Inc.
Bus 001 Device 003: ID 045e:0083 Microsoft Corp. Basic Optical Mouse
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching
Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Suat Gedikli

unread,
Feb 18, 2011, 4:28:15 PM2/18/11
to openn...@googlegroups.com
Hi,

can you tell me which hard paths and in which files?
thank you.

Suat

> if (status != XN_STATUS_OK&& device_node_info_list.Begin () !=

grrrwaaa

unread,
Feb 19, 2011, 7:28:32 PM2/19/11
to OpenNI
Oh, I think it was because I tried 'make' instead of 'cmake':
make
CMake Error: The source directory "/wg/stor2a/gedikli/ros/
cturtle_trunk/Primesense/ni" does not exist.
cmake instead complains that I don't have a full ROS install:
CMake Error at CMakeLists.txt:2 (include):
include could not find load file:
/core/rosbuild/rosbuild.cmake

I realize this is probably resolvable by checking out the right
version and following the build instructions more carefully, but as I
said, I don't need the whole ROS package, I'm just trying to get two
kinects working with OpenNI unstable branch / avin2 driver.

With more persistence, I've been able to get the two working, but with
depth images only, by not using the Sample-User.xml configuration. If
I try to also get image streams, the 'Bad parameter' error recurs.
That's fine for me - the project I'm working on only needs the depth
streams. Frame-rate appears to be terrible, hopefully I can improve
it.

Thanks for the help, and especially for pointing to the example code
in the ROS rewrite branch (very helpful!)

jmendeth

unread,
Jul 18, 2012, 4:19:38 PM7/18/12
to openn...@googlegroups.com
For curiosity, if you only have one device connected,
can the second program you posted create an ImageGenerator?
(by calling CreateProductionTree)

El dilluns 14 de febrer de 2011 3:31:45 UTC+1, GrrrWaaa va escriure:
Reply all
Reply to author
Forward
0 new messages