Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rs2::pipeline can't open T265 given the serial number #3434

Closed
dorian3d opened this issue Mar 8, 2019 · 17 comments
Closed

rs2::pipeline can't open T265 given the serial number #3434

dorian3d opened this issue Mar 8, 2019 · 17 comments
Labels
T260 series Intel® T265 library

Comments

@dorian3d
Copy link
Contributor

dorian3d commented Mar 8, 2019

Required Info
Camera Model T265
Firmware Version 0.0.18.5129
Operating System & Version Ubuntu 16
Kernel Version (Linux Only) 4.15.0-43-generic
Platform PC
SDK Version 2
Language C++
Segment others

Issue Description

I have a T265 plugged in the laptop and followed the multicam example to open it given its serial number. Like this:

rs2::pipeline pipe;
rs2::config cfg;
cfg.enable_device(serial_number);
cfg.enable_stream(RS2_STREAM_POSE, RS2_FORMAT_6DOF);
pipe.start(cfg);

But I always get a No device connected exception.


Full example:

#include <iostream>
#include <iomanip>
#include <string>
#include <thread>
#include <librealsense2/rs.hpp>

void print_info(rs2::device& dev);

int main() {
    rs2::device dev = [] {
        rs2::context ctx;
        std::cout << "waiting for device..." << std::endl;
        while (true) {
            for (auto&& dev : ctx.query_devices())
                return dev;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }();
    print_info(dev);

    rs2::pipeline pipe;
    rs2::config cfg;
    std::string serial_number = dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
    std::cout << "opening pipeline for " << serial_number << std::endl;
    cfg.enable_device(serial_number);
    cfg.enable_stream(RS2_STREAM_POSE, RS2_FORMAT_6DOF);
    if (!pipe.start(cfg)) return 1;

    while (true) {
        auto frames = pipe.wait_for_frames();
        auto f = frames.first_or_default(RS2_STREAM_POSE);
        auto pose_data = f.as<rs2::pose_frame>().get_pose_data();
        std::cout << "\r" << "Device Position: " << std::setprecision(3) << std::fixed << pose_data.translation.x << " "
                  << pose_data.translation.y << " " << pose_data.translation.z << " (meters)";
    }
}

void print_info(rs2::device& dev) {
    std::cout << "device found:" << std::endl;
    std::cout << dev.get_info(RS2_CAMERA_INFO_NAME) << " "
              << dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER) << " "
              << dev.get_info(RS2_CAMERA_INFO_PRODUCT_ID) << std::endl;

    auto sensors = dev.query_sensors();
    for (rs2::sensor& sensor : sensors) {
        std::cout << "sensor " << sensor.get_info(RS2_CAMERA_INFO_NAME) << std::endl;
        for (rs2::stream_profile& profile : sensor.get_stream_profiles()) {
            std::cout << "  stream " << profile.stream_name() << std::endl;
        }
    }
}

Output:

waiting for device...
device found:
Intel RealSense T265 845412110806 0B37
sensor Tracking Module
  stream Fisheye 1
  stream Fisheye 2
  stream Gyro
  stream Accel
  stream Pose
opening pipeline for 845412110806
terminate called after throwing an instance of 'rs2::error'
  what():  No device connected
Aborted (core dumped)
@dorodnic dorodnic added the T260 series Intel® T265 library label Mar 12, 2019
@RealSenseCustomerSupport
Copy link
Collaborator


Hi @dorian3d,
This is indeed an issue there because query_devices locks the tracking module. Refer to below.
#3339

@chunyang-zhang
Copy link

@dorian3d Did you solve the problem now? I also encountered this problem, for D435i

rs2::pipeline pipe_d435;
rs2::config cfg_d435;
cfg_d435.enable_device(D435_SerialNumber);
cfg_d435.enable_stream(RS2_STREAM_DEPTH,640,480,RS2_FORMAT_Z16, 60);
cfg_d435.enable_stream(RS2_STREAM_COLOR,640,480,RS2_FORMAT_BGR8,60);
pipe_d435.start(cfg_d435);

it works fine, but for T265

rs2::pipeline pipe_t265;
rs2::config cfg_t265;
cfg_t265.enable_device(T265_SerialNumber);
cfg_t265.enable_stream(RS2_STREAM_POSE, RS2_FORMAT_6DOF);
pipe_t265.start(cfg_t265);

failed

output:
terminate called after throwing an instance of 'rs2::error'
what(): No device connected
Aborted (core dumped)

@dorodnic , how to solve this problem? thanks

@dorian3d
Copy link
Contributor Author

I see the issue still exists in master and development. I switched to rs::device. If you need to specify the serial number, this workaround may help:

rs2::device get_device(const std::string& serial_number) {
    rs2::context ctx;
    while (true) {
        for (auto&& dev : ctx.query_devices())
            if (std::string(dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER)) == serial_number)
                return dev;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

@macmason
Copy link

@dorian3d can you clarify what you mean by "I switched to rs::device"? I'm seeing this problem as well (using 234b1dde60d20f18868d3720b8b88b4bdf7882df, aka develop after #3515 was merged). I can enumerate mulitple devices without trouble, but when I do:

rs2::pipeline p;
rs2::config c;

// Loop over the results of query_devices and find the T265
c.enable_stream(RS2_STREAM_POSE, RS2_FORMAT_6DOF);
c.enable_device(serial number);
rs2::pipeline_profile profile = p.start(c);

That last line throws Exception: No device connected.. Looping N times reliably fails on every loop.

Is there another way to make this go?

@dorian3d
Copy link
Contributor Author

@macmason I meant to use the low level API (rs2::device) instead of the high level API (rs2::pipeline). For example, the snippet of my previous comment will give you the rs2::device of a specific serial number camera. Depending on your code, you may use this device instead of the pipeline. If that change is not possible in your program, you may want to wait until a fix is ready.

@macmason
Copy link

@dorian3d thanks, but how do I pull imagery from just-a-device? Even the pure C examples construct a pipeline.

(Apologies for hijacking the bug; is there a better place for these sorts of questions?)

@dorian3d
Copy link
Contributor Author

@macmason, if you only have a T265 device connected to the pc, you don't need to provide the serial number, setting the stream in config should be enough:

c.enable_stream(RS2_STREAM_POSE, RS2_FORMAT_6DOF);
rs2::pipeline_profile profile = p.start(c);

If you do need to specify the serial number, try something along this line:

rs2::device get_device(const std::string& serial_number) {
    rs2::context ctx;
    while (true) {
        for (auto&& dev : ctx.query_devices())
            if (std::string(dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER)) == serial_number)
                return dev;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main() {
    // get the device given the serial number
    std::string serial_number = ...;
    auto device = get_device(serial_number);

    // open the profiles you need, or all of them
    auto sensor = device.first<rs2::sensor>();
    sensor.open(sensor.get_stream_profiles());

    // start the sensor providing a callback to get the frame
    sensor.start([](rs2::frame f) {
        if (f.get_profile().stream_type() == RS2_STREAM_POSE) {
            auto pose_frame = f.as<rs2::pose_frame>();
        } else if (f.get_profile().stream_type() == RS2_STREAM_FISHEYE && f.get_profile().stream_index() == 1) {
            // this is the first fisheye imager
            auto fisheye_frame = f.as<rs2::video_frame>();
        } else if (f.get_profile().stream_type() == RS2_STREAM_FISHEYE && f.get_profile().stream_index() == 2) {
            // this is the second fisheye imager
            auto fisheye_frame = f.as<rs2::video_frame>();
        }
    });

    std::this_thread::sleep_for(std::chrono::seconds(10));

    // and stop
    sensor.stop();
}

@macmason
Copy link

Thanks!

I'm closer, but still no luck. The result of

auto profiles = sensor_.get_stream_profiles();
for (auto&& profile : profiles) {
  std::cout << "profile: " << profile.stream_type() << std::endl;
}

does the right thing:

profile: Fisheye
profile: Fisheye
profile: Gyro
profile: Accel
profile: Pose

(two cameras, one gyro, one accel, one pose).

However, when I actually start with the callback, I get callbacks for every profile except pose. Maybe that's because it's a "composite" stream (so to speak) and that requires a pipeline? Which doesn't work with multiple cameras plugged in just yet...

Thoughts? @dorodnic is this related to the unload_tracking_module discussed in #3339? My code above is in a for (auto&& dev : ctx.query_devices()) { ... } loop. However, adding ctx.unload_tracking_module() after the loop doesn't help; instead, I start seeing:

02:59:09.407 [5866] [E] Device-BC70: No more frame buffers (1), dropping frame

at a fairly high rate.

@macmason
Copy link

After a further experiment, moving all of the sensor start and callback code entirely out of the loop (with our without unlooad_tracking module) produces the same result. (Which makes sense.)

@dorian3d
Copy link
Contributor Author

Hi @macmason. It's strange you don't get any pose data. I am trying to reproduce your set up. Let me know if this helps.

I connected a T265 and a D400series camera to a laptop with Ubuntu 16.04. I am running the following minimal working example with librealsense master branch version. I am able to get fisheye images and pose data from the T265, both by providing the serial number or by letting the application find the T265 device. To find the T265 device, I query devices and return the first one that contains T265 in the name.

Code:

#include <iostream>
#include <iomanip>
#include <cstring>
#include <string>
#include <thread>
#include <librealsense2/rs.hpp>

rs2::device get_device(const std::string& serial_number = "") {
    rs2::context ctx;
    while (true) {
        for (auto&& dev : ctx.query_devices()) {
            if (((serial_number.empty() && std::strstr(dev.get_info(RS2_CAMERA_INFO_NAME), "T265")) ||
                std::strcmp(dev.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER), serial_number.c_str()) == 0))
                return dev;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main() {
    // get the device given the serial number
    std::cout << "Waiting for device..." << std::endl;
    std::string serial_number = ""; // serial number or empty
    auto device = get_device(serial_number);

    std::cout << "Device with serial number " << device.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER) << " got" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // open the profiles you need, or all of them
    auto sensor = device.first<rs2::sensor>();
    sensor.open(sensor.get_stream_profiles());

    // start the sensor providing a callback to get the frame
    sensor.start([](rs2::frame f) {
        if (f.get_profile().stream_type() == RS2_STREAM_POSE) {
            auto pose_frame = f.as<rs2::pose_frame>();
            auto pose_data = pose_frame.get_pose_data();
            std::cout << "pose " << pose_data.translation << std::endl;
        } else if (f.get_profile().stream_type() == RS2_STREAM_FISHEYE) {
            // this is one of the fisheye imagers
            auto fisheye_frame = f.as<rs2::video_frame>();
            std::cout << "fisheye " << f.get_profile().stream_index() << ", "
                      << fisheye_frame.get_width() << "x" << fisheye_frame.get_height() <<  std::endl;
        }
    });

    std::this_thread::sleep_for(std::chrono::seconds(10));

    // and stop
    sensor.stop();
}

@RealSenseCustomerSupport
Copy link
Collaborator


Please update to librealsense 2.19.2 and refer to rs-multicam example.

@dorian3d
Copy link
Contributor Author

dorian3d commented Apr 1, 2019

Working great in 2.19.2!

@mickeyouyou
Copy link
Contributor

mickeyouyou commented Jun 25, 2019

sorry still No device connected in fireware 2.21.0.

System:Ubuntu 18.04

but thanks to @dorian3d . your solution is ok

@zwn
Copy link

zwn commented Feb 7, 2020

It is not working for me in pyrealsense 2.32.1:

ctx = rs.context()
dl = ctx.query_devices()
serial_number = dl[0].get_info(rs.camera_info.serial_number)
print("Serial number:", serial_number)
pipeline = rs.pipeline(ctx)
cfg = rs.config()
cfg.enable_device(serial_number)
cfg.enable_stream(rs.stream.pose, rs.format.six_dof, 200 )
pipeline.start(cfg)

returns

Serial number: 0000929122110084
Traceback (most recent call last):
  File "pose-fps.py", line 59, in <module>
    main()
  File "pose-fps.py", line 30, in main
    pipeline.start(cfg)
RuntimeError: No device connected

If I comment out the cfg.enable_device(serial_number) it works ok.

I need to set the serial number to be able to work in multicam scenario.

@zwn
Copy link

zwn commented Feb 7, 2020

I can confirm that it indeed works with version 2.19.2 so this is a regression. I going to file this as a new issue then.

@zwn
Copy link

zwn commented Feb 7, 2020

I've found there is already an issue #5614 referring to this problem. I did more testing and the problem seems to be isolated to version 2.32.1. Version 2.31.0 works.

@CeccAnd
Copy link

CeccAnd commented Oct 26, 2020

Hello,

sorry for my ignorance but where could I find such rs2::pipeline. I need for pose jumping turning off of my T265.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T260 series Intel® T265 library
Projects
None yet
Development

No branches or pull requests

8 participants