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

Mechanism to specify camera by device path #713

Closed
mikepurvis opened this issue Apr 3, 2019 · 6 comments
Closed

Mechanism to specify camera by device path #713

mikepurvis opened this issue Apr 3, 2019 · 6 comments

Comments

@mikepurvis
Copy link
Contributor

mikepurvis commented Apr 3, 2019

Per the work done on #18, it's possible to start a Realsense driver instance targeted at a specific physical camera by serial number. The serial numbers are different from the USB serials, but can be mapped like so:

$ rs-enumerate-devices | grep "Physical Port"
    Physical Port                 :  /sys/devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/video4linux/video0
$ cat /sys/bus/usb/devices/usb2/2-3/serial
814113021314

In principle, it is possible to wrap this serial-number-reading logic in a script that is called from roslaunch, eg <param name="serial_no" command="path/to/find_realsense_serial usb2/2-3" />. However, this can be a problem because the whole roslaunch has to wait on the camera path becoming available at startup time— either that or serial number discovery is something which has to run at system commissioning time and be re-run any time a camera is swapped out. Neither of these options are ideal.

Our preferred path would be for there to be a secondary param similar to serial_no like dev_path, which allows the device path to be specified directly to the driver, and it's part of its initial connect/reconnect loop to simply wait for the device to appear before attempting to read the serial from it and initialize the rest of the driver.

If this proposed direction is acceptable, I can prepare a pull request.

@stwirth
Copy link
Contributor

stwirth commented Apr 3, 2019

Just for reference, openni2_camera offers several methods on how to identify the device: serial number, vendor/id, USB bus + port number (see relevant code section here). It would be nice if the realsense driver could do something similar.

An example use case is having a fleet of robots with multiple cameras each. To associate the cameras in software, each robot now needs to know which serial number each camera has (e.g. forward looking is #123456789, backward looking is #987654321) whereas they could easily be identified through the bus they are on. Being able to use that bus information as identifier would make the serial number association step superfluous, the configuration would be given through the hardware setup.

@mikepurvis
Copy link
Contributor Author

Ah cool, they do it with a single identifying URI-like string (passed with the device_id parameter) that has multiple possible interpretations depending on the presence of certain magic characters like #, @, /, falling back to just a 1:1 match against the serial numbers of present devices. That makes a lot of sense and would be an easy thing to just copy.

@mikepurvis
Copy link
Contributor Author

For now I'm going to handle this on my side with a wrapper script and a spin loop; when there's some concrete guidance from upstream about what they'll be willing to merge, I'll look into contributing a more holistic solution.

@mikepurvis
Copy link
Contributor Author

For interested parties, here's a wrapper which may allow you to manage with the current state of affairs until we get more guidance:

import os, re, rospy, sys, subprocess, time
from catkin.find_in_workspaces import find_in_workspaces


def get_serial_mapping():
    enumerate_output = subprocess.check_output(['rs-enumerate-devices'])
    last_serial = None
    serial_mapping = {}

    for line in enumerate_output.splitlines():
        m = re.match(r'\s*Serial Number\s*:\s*([^ ]*?)$', line)
        if m:
            last_serial = m.group(1)
        m = re.match(r'\s*Physical Port\s*:\s*[^ ]*?usb[0-9]+/([0-9.-]+)/', line)
        if m:
            serial_mapping[m.group(1)] = last_serial

    return serial_mapping


def main():
    rospy.init_node('realsense_launcher')
    usb_dev = rospy.get_param('~usb_dev', '')
    if usb_dev:
        while True:
            serial_mapping = get_serial_mapping()
            if usb_dev in serial_mapping:
                serial = serial_mapping[usb_dev]
                rospy.loginfo('Found RealSense device with serial %s on usb dev %s' %
                              (serial, usb_dev))
                rospy.set_param('~serial_no', serial)
                break

            rospy.loginfo('Found %d RealSense devices, still looking for usb dev %s' %
                          (len(serial_mapping), usb_dev))
            time.sleep(1)

    rospy.loginfo('Now invoking nodelet process for RealSense.')
    nodelet_ex = find_in_workspaces(project='nodelet', path='nodelet')[0]
    os.execv(nodelet_ex, [nodelet_ex] + sys.argv[1:])

if __name__ == '__main__':
    main()

Should be pretty self explanatory, but basically just launch this in place of the nodelet, don't set ~serial_no and instead set ~usb_dev to a value like 4-1.

@doronhi
Copy link
Contributor

doronhi commented Oct 24, 2019

Thanks for showing the way.
Option added in #964, based on #960.

@mikepurvis
Copy link
Contributor Author

Great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants