Multiple Astras: How is their ordering determined?

I’m working on an application that uses multiple Astras connected to the same computer to provide coverage over a larger area. The application needs to be able to keep a consistent order to the Astras so that their relative positions can be saved and looked up, avoiding the need to re-align the cameras in-software every time you use it.

Based on some brief experiments with two Astras, it looks like the numbering is not determined by the order in which the sensors are plugged in (which is good!). With two astras (0 and 1), if I disconnect 0 the numbering down-shifts one place as I would expect, but plugging that camera back in restores the original order. Flipping which ports the devices are connected to also appears to have no effect (which is also good!)

This leads me to the important question: How are the sensors numbered internally by the SDK? Is it based on a unique ID tied to the USB device (like how OpenNI does it with its DeviceURI properties)? Are my experimental results broadly applicable to any Windows machine with multiple Astras, or will other computers change the device ordering somehow?

In my experience, the order is determined by the OS, so when I reboot my computer, the assignment order isn’t always the same.

Hm, that’s frustrating. Hopefully in the not-too-distant future they add some kind of a publicly-accessible unique identifier to each camera in addition to/instead of the automatic numbering.

Hi chrisib,

Thanks for your question. The serial number can be used as the unique identifier for each camera. It can be obatined with the OpenNI Extended API sample code from the Univesal Download Thread. Please try this and see if it can help with your concern.

Is the extended functionality included in the .NET wrapper?

Also, related to this topic: is there an easy function anywhere in the API to enumerate all available Astras? I’m working on Windows using .NET, so I’m somewhat restricted to what’s available through the .NET wrapper.

What I’m doing right now is enumerating all of the USB devices and counting how many have VID=2bc5 and PID=040* to determine n, and then looping from 0 to n-1 and opening device/sensor{n}

This approach works, but it would be nice if there was a static function in the Astra.StreamSet class that returned an IEnumerable of all available stream sets. That way you could just go:

foreach(Astra.StreamSet s in Astra.StreamSet.GetAvailable())
{
    // do whatever it is you need to do here
}

Add to that the ability to easily get a consistent, unique ID for each StreamSet and the ability to open a StreamSet based on such an ID and that would make developing applications that use multiple Astras far more reliable. e.g.:

// contains code for processing camera data and applying offsets/rotations so that
// the depth/colour stream from this camera can be lined up with other
// cameras, allowing us to seam multiple cameras to cover a larger area
class AstraCamera
{
...

private Astra.StreamSet Streams{ get; set;}

// a globally unique, hardware-specific ID that we can 
// save to uniquely identify each Astra
[DataMember]
private string UniqueID {get; set;}

// when deserializing the saved configuration, re-open the Astra so
// that it can provide data
[OnDeserialized]
private void OnDeserialized(StreamingContext sc) {
    Streams = Astra.StreamSet.Open(UniqueID);
    ...
}

// save the camera to an XML file we can deserialize later (e.g. next time we launch)
// the application
public void Save(string filename) {
    UniqueID = Streams.HardwareID; // <-- this gives us the unique ID for each sensor
    using(FileStream fs = new FileStream(filename, FileMode.Create)) {
        DataContractSerializer xml = new DataContractSerializer(this.GetType());
        xml.WriteObject(fs, this);
    }
}
}// end of class

Hi chrisib,

Thanks for the suggestion. The Extended API from the Universal Download Thread is part of the OpenNI SDK. The APIs for Astra SDK is coming soon in our future releases.

Hello Jackson,
Are these APIs now available in the Astra SDK ?

Hi gvimont,

Yes, the serial number API is available through Astra SDK now. Please download the latest release from:

Hello Jackson,

I have the same problem, i have 4 Orbbec Astra sensors and need to open them in the right order accross PC reboots.
You did mention the “serial” API, but where is it?

The C function should be: astra_streamset_open

Please let me know

Regards

Hey @tabulatouch

This is how I get the serial number with the AstraSDK:

char serialnumber[128];
astra_depthstream_get_serialnumber(depthStream,serialnumber,128);

Thank you Ale :wink: !
I figured it out, even if I was hoping for a way to open the right sensor without enumerating them every time.
I just open every available streamset, check the serial number on the depth stream, re-open using the index.
Here is the code (yes, gotos still of use in 2020):

public static int GetSensorIndexFromSerial(string serial, int max_device_count=10)
    {
        int index_found = -1;

        Astra.StreamReader  streamReader=null;
        Astra.StreamSet     streamSet=null;

        // Tries to open up to max_device_count sensors, open its depthstream and get serial code returning index
        for (int i = 0; i < max_device_count; i++)
        {
            streamReader?.Dispose();
            streamSet?.Dispose();

            var connectionString = $"device/sensor{i}";
            streamSet = Astra.StreamSet.Open(connectionString);

            if (streamSet.IsAvailable)
            {
                streamReader = streamSet.CreateReader();
                var depthStream = streamReader.GetStream<Astra.DepthStream>();                    

                if (GetSerialNumber(depthStream, out string serial_number))
                {
                    if (serial_number == serial)
                    {
                        index_found = i;
                        goto exit_get_sensorindexfromserial;
                    }                        
                }                   
            }
            else
                break;
        }

exit_get_sensorindexfromserial:

        streamReader?.Dispose();
        streamSet?.Dispose();

        return index_found;           
    }
1 Like