杰瑞科技汇

ROS下如何用Python操控Kinect?

Of course! Using a Kinect with ROS and Python is a classic and powerful combination for robotics, computer vision, and 3D perception. This guide will walk you through the entire process, from setting up the hardware to writing Python scripts to access the Kinect's data.

ROS下如何用Python操控Kinect?-图1
(图片来源网络,侵删)

Overview of the Tools

  1. ROS (Robot Operating System): Provides the communication framework (topics, services) and many standard tools for robotics.
  2. Kinect Sensor: The hardware that captures RGB images, depth data, and (in older models) body skeleton information.
  3. Python: The programming language we'll use to write our ROS nodes. It's excellent for rapid prototyping and leveraging libraries like OpenCV and NumPy.
  4. OpenNI & NITE (The "Old" Way): Historically, this was the primary driver for Kinect on Linux. It's largely deprecated but you might still find tutorials for it. We will NOT use this method.
  5. libfreenect2 (The "New" & Recommended Way): This is the modern, high-performance, and actively maintained open-source driver for the Kinect v2. It's the standard for ROS integration today.

Step 1: Hardware and Software Prerequisites

Hardware

  • A Microsoft Kinect for Windows v2 sensor.
  • A USB 3.0 port. The Kinect v2 requires the higher bandwidth of USB 3.0 and will not work with USB 2.0.
  • A power supply for the Kinect (it comes with a special splitter cable that plugs into a wall outlet and the USB port).

Software

  • Ubuntu 20.04 LTS (or 18.04). This guide is tailored for Ubuntu 20.04.
  • ROS Noetic Ninjemys. This is the ROS version for Ubuntu 20.04.
  • A working Python 3 environment (python3, pip3).

Step 2: Installation

We'll follow the standard ROS installation process for the libfreenect2 driver.

Install System Dependencies

Open a terminal and install the necessary libraries for libfreenect2 and its ROS wrapper.

# Update your package list
sudo apt-get update
# Install required system libraries
sudo apt-get install -y \
    libusb-1.0-0-dev \
    pkg-config \
    libglfw3-dev \
    libgl1-mesa-dev \
    libglu1-mesa-dev \
    libtbb2 \
    libtbb-dev \
    libturbojpeg0-dev \
    libjpeg-turbo8-dev
# Install the ROS driver package
# Replace 'ros-noetic-' with 'ros-melodic-' if you are on Ubuntu 18.04
sudo apt-get install -y ros-noetic-libfreenect2 ros-noetic-freenect2-launch

Install libfreenect2 from Source (Recommended for Performance)

The version in the Ubuntu repositories can be outdated. Compiling from the official source is highly recommended.

# Create a workspace for building
mkdir -p ~/ros_kinect_ws/src
cd ~/ros_kinect_ws/src
# Clone the libfreenect2 repository
git clone https://github.com/OpenKinect/libfreenect2.git
cd libfreenect2
# Create a build directory
mkdir build
cd build
# Compile the library
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
make -j4
sudo make install
sudo make install_rules

Note: The sudo make install_rules step is important to set up the correct udev rules so your computer recognizes the Kinect.

ROS下如何用Python操控Kinect?-图2
(图片来源网络,侵删)

Test the Driver (Before ROS)

It's a good idea to make sure the driver works on its own.

# Plug in your Kinect v2 to a USB 3.0 port and connect its power.
# Run the viewer
Protonect -l 1

You should see two windows pop up: one for the RGB image and one for the depth image. If you see this, the hardware and driver are working perfectly! Close the viewer with Ctrl+C.


Step 3: Running the ROS Node

The ros-noetic-freenect2-launch package we installed provides an easy way to launch the Kinect driver as a ROS node.

Source Your ROS Workspace

Make sure your ROS environment is active.

ROS下如何用Python操控Kinect?-图3
(图片来源网络,侵删)
source /opt/ros/noetic/setup.bash

Launch the Kinect Node

The launch file will start the driver, which will publish the sensor data as ROS topics.

# Navigate to your workspace
cd ~/ros_kinect_ws
# Run the launch file
roslaunch freenect2.launch

You should see output indicating that the node has started. The Kinect is now publishing data!

Check the Published Topics

In a new terminal, run:

rostopic list

You should see topics like:

  • /camera/rgb/image_raw (The RGB image)
  • /camera/depth/image_raw (The depth image)
  • /camera/ir/image_raw (The infrared image)
  • /camera/depth/camera_info (Intrinsics for the depth camera)
  • /camera/rgb/camera_info (Intrinsics for the RGB camera)
  • /freenect2/device (System status of the device)

Let's inspect one of the image topics:

# See the message type
rostopic type /camera/rgb/image_raw
# Output: sensor_msgs/Image
# View the image using rqt_image_view
rqt_image_view

In the rqt_image_view window, you can select the /camera/rgb/image_raw or /camera/depth/image_raw topics to see the live feed.


Step 4: Writing a Python Subscriber Node

This is where we access the Kinect data in our own Python script. We will create a simple node that subscribes to the RGB and depth topics and displays them side-by-side using OpenCV.

Create a Python Script

Create a new file in your src folder.

cd ~/ros_kinect_ws/src
touch kinect_subscriber.py

Write the Code

Paste the following code into kinect_subscriber.py. The comments explain each part.

#!/usr/bin/env python3
import rospy
import cv2
import numpy as np
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
class KinectSubscriber:
    def __init__(self):
        """
        Initializes the KinectSubscriber node.
        """
        rospy.init_node('kinect_subscriber_node', anonymous=True)
        # Create a CvBridge object to convert ROS images to OpenCV format
        self.bridge = CvBridge()
        # Subscribe to the RGB and Depth image topics
        self.rgb_sub = rospy.Subscriber("/camera/rgb/image_raw", Image, self.rgb_callback)
        self.depth_sub = rospy.Subscriber("/camera/depth/image_raw", Image, self.depth_callback)
        # Initialize image storage
        self.rgb_image = None
        self.depth_image = None
        rospy.loginfo("Kinect Subscriber Node Started. Waiting for images...")
    def rgb_callback(self, data):
        """
        Callback function for the RGB image topic.
        Converts the ROS Image message to an OpenCV image and stores it.
        """
        try:
            # Convert ROS Image message to a NumPy array (OpenCV format)
            self.rgb_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
        except Exception as e:
            rospy.logerr(f"Could not convert RGB image: {e}")
    def depth_callback(self, data):
        """
        Callback function for the Depth image topic.
        Converts the ROS Image message to an OpenCV image and stores it.
        The depth image is a 16-bit single-channel image where each pixel is the depth in millimeters.
        """
        try:
            # Convert ROS Image message to a NumPy array
            self.depth_image = self.bridge.imgmsg_to_cv2(data, "16UC1")
            # For visualization, we often scale the depth image to 8-bit
            # Normalize the depth values to 0-255 for display
            if self.depth_image is not None:
                # Clip values to a reasonable range (e.g., 0 to 5 meters = 5000 mm)
                depth_clipped = np.clip(self.depth_image, 0, 5000)
                # Scale to 8-bit
                self.depth_image_display = cv2.convertScaleAbs(depth_clipped, alpha=255.0/5000.0)
        except Exception as e:
            rospy.logerr(f"Could not convert Depth image: {e}")
    def run(self):
        """
        The main loop of the node.
        It displays the RGB and Depth images in a single window.
        """
        rate = rospy.Rate(10) # 10 Hz
        while not rospy.is_shutdown():
            # Check if both images have been received
            if self.rgb_image is not None and self.depth_image_display is not None:
                # Resize images to the same size for display
                h, w = self.rgb_image.shape[:2]
                depth_resized = cv2.resize(self.depth_image_display, (w, h))
                # Concatenate the images horizontally
                combined_image = np.hstack((self.rgb_image, depth_resized))
                # Display the combined image
                cv2.imshow('Kinect RGB and Depth Feed', combined_image)
            # Check for 'q' key press to exit
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
            rate.sleep()
        # Clean up
        cv2.destroyAllWindows()
if __name__ == '__main__':
    try:
        subscriber = KinectSubscriber()
        subscriber.run()
    except rospy.ROSInterruptException:
        pass

Make the Script Executable

chmod +x ~/ros_kinect_ws/src/kinect_subscriber.py

Create a Launch File for Your Node

It's best practice to launch your custom nodes with a launch file. Create kinect_v2.launch in your src folder.

<launch>
    <!-- First, launch the official freenect2 driver -->
    <include file="$(find freenect2_launch)/launch/freenect2.launch" />
    <!-- Then, launch our custom Python subscriber node -->
    <node name="kinect_subscriber_node" pkg="ros_kinect_ws" type="kinect_subscriber.py" output="screen" />
</launch>

Note: The pkg="ros_kinect_ws" assumes you have added your workspace to your catkin workspace list. If not, you can use type="$(find ros_kinect_ws)/src/kinect_subscriber.py".

Build and Run

Your workspace needs to be built so ROS can find your new script.

# Go to the root of your workspace
cd ~/ros_kinect_ws
# Build the workspace (catkin_make is for catkin workspaces)
catkin_make
# Source the workspace setup file
source devel/setup.bash

Now, you can run everything with a single command:

roslaunch ros_kinect_ws kinect_v2.launch

A window titled "Kinect RGB and Depth Feed" should appear, showing the live feed from your Kinect on the left and the corresponding depth map on the right. Press q in the window to stop the node.

分享:
扫描分享到社交APP
上一篇
下一篇