ROS + OpenNI2 + NiTE2

After weeks banging my head with OpenNI version 1.5.4 that comes with my ROS fuerte installation, I finally come to the conclusion that OpenNI 1.5.4 is highly frustrating, difficult to use, and has very low code readability. Or maybe it is just me.

It is time to migrate to OpenNI2, the latest version of the library that has been completely hauled with new architecture, with (much) better code readability. And another good thing about this release is that this will not mess the other version of OpenNI, so we can still work with both version in the same time.

The installation process is pretty straight forward. We can get the installation files after registering on OpenNI website. Then just simply run the install script from each folder.

Then, to use OpenNI2 and NiTE2 with ROS, we need to add some parameters to the CMakeLists.txt of our ROS project/package to link them with the libraries. Here’s mine:

cmake_minimum_required(VERSION 2.4.6)
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)

# Change two lines below according to your installation
#
set(OPENNI2_DIR /home/ariandy/src/OpenNI-Linux-x64-2.2/)
set(NITE2_DIR /home/ariandy/src/NiTE-Linux-x64-2.2/)
rosbuild_init()

#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

link_directories(${OPENNI2_DIR}/Redist)
include_directories(${OPENNI2_DIR}/Include)

link_directories(${NITE2_DIR}/Redist)
include_directories(${NITE2_DIR}/Include)

rosbuild_add_executable(testing src/main.cpp)
target_link_libraries(testing OpenNI2 NiTE2)

Now grab any sample program codes from the OpenNI2 or NiTE2 and put it inside our ROS package for testing. It should compile just fine.

There’s still one issue though. NiTE2 uses machine learning method for the human recognition and also skeleton fitting, which relies heavily on training data. It keeps the training data on NiTE2 folder inside NiTE-Linux-*/Samples/Bin folder. And somehow, when NiTE2 initializes it will look for the training data relative to the path (e.g. your executable is at /home/user, then it will look for /home/user/NiTE2/*). That is a bummer, since we can run ROS executable (node) regardless of the path and this NiTE2 thing defeats the purpose. Workaround is by navigating first to NiTE-Linux-*/Samples/Bin/ or NiTE-Linux-*/Redist/ then do rosrun your_package your_node, otherwise it won’t find the training data.

Running roscore and Launching ROS nodes as Background Process

I access my ROS running robot wirelessly using secure shell (SSH). To run my program, I have to first run all the startup scripts such as roscore and my robot’s driver. It’s kind of tedious to open a lot of shells just to keep this services on. And I can’t simply run this on background by using & operator because sometimes I need to check the node’s output.

So to keep it simple and neat, I made simple script to run roscore and robot driver on background, but still be able to check the outputs of this two (e.g. error messages).

First thing first, I like to have my own bin folder, to keep my own scripts.

cd ~
mkdir bin
echo "export PATH=$PATH:/home/ariandy/bin" >> ~/.bashrc
source ~/.bashrc

Then all this scripts will be kept inside this folder. If you need to run roscore and some nodes as a startup script, it will be better if you keep this scripts in /usr/local/bin/ folder.

#!/bin/bash
# file: youbot-roscore.sh

source /opt/ros/fuerte/setup.bash
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:/home/ariandy/youbot_driver:/home/ariandy/applications:/home/ariandy/ros_stacks

roscore

This is for my node:

#!/bin/bash
# file: youbot-oodl.sh

source /opt/ros/fuerte/setup.bash
export ROS_PACKAGE_PATH=$ROS_PACKAGE_PATH:/home/ariandy/youbot_driver:/home/ariandy/applications:/home/ariandy/ros_stacks

# this is my driver
roslaunch youbot_oodl youbot_oodl_driver.launch
# or your own node/launch script
#roslaunch {your_package} {your_thing}

The main tool for our topic is linux’ “screen“. Install it first if you don’t have it.

#!/bin/bash
# file: run-youbot-ros-startup.sh

echo "running roscore daemon.."
screen -dmS roscore youbot-roscore.sh
sleep 2
echo "running youbot oodl daemon"
screen -dmS oodl youbot-oodl.sh
echo "done. view with screen -ls"

The format is screen -dmS [any_name] [your_script]. The -dm argument will tell screen to run this session as a daemon. Then we use -S argument to give the session a name, so it will be easier for later. Please note that if your_script is not located on system path folder (e.g. /usr/bin/, /usr/local/bin/, etc.), you have to give the full path for the screen argument.

roscore needs some time (1-2 seconds) to reach its full operational state. That is why I give 2 seconds delay (with sleep 2) before running my node.

With this done, then we can run the things on the background:

ariandy@youbot$ run-youbot-ros-startup.sh 
running roscore daemon..
running youbot oodl daemon
done. view with screen -ls

To view what are the running sessions, call screen -ls

There are screens on:
	9285.oodl	(05/08/2013 05:01:50 PM)	(Detached)
	9224.roscore	(05/08/2013 05:01:49 PM)	(Detached)
2 Sockets in /var/run/screen/S-ariandy.

The format is [pid].[name]. Use this name if you want to go to each session: screen -r name.

When we’re inside the screen session, Ctrl-C will send a signal to the program we are running inside screen, makes it quitting and then the screen session closes. We don’t want this. What we want is to go back to our original shell session, and put the screen session back as background process. We do that by using key combination Ctrl-A-D, that is while holding Ctrl, press A, then press D.