[ros-users] Integrating ROS node subscriber with X-Plane plu…

Top Page
Attachments:
Message as email
+ (text/plain)
+ (text/html)
Delete this message
Reply to this message
Author: Clayton Morrison
Date:  
To: ROS Userslist
CC: Tom Walsh, Ian Fasel
Subject: [ros-users] Integrating ROS node subscriber with X-Plane plugin
Hi,

Brief description: I'm attempting to integrate a simple ROS node with the X-Plane ( http://www.x-plane.com/ ) flight simulator plugin facility (in C++). I want to add to the plugin a subscriber that will listen on a topic and when a message arrives, send a command to X-Plane. Whenever I get to the point of calling ros::init() the plugin crashes (well, X-Plane crashes, which I assume is from the plugin). (I did look through the archives -- I'm obviously new here -- but couldn't find anything related to my issue addressed; apologies in advance if I just missed it!)

Some immediate hunches (but not sure how to verify/fix) and questions:
(1) xplane is a 32bit application. Could my build process (described below) be inadvertently using 64bit versions of compiled ROS libs?
(2) I am calling ros::init() in a non-main fn, so I'm using the version based on map<string,string>. I'm sending in an empty map b/c I have no params to remap. Am I doing this wrong? (source for XP_ROS_Plugin.cpp below; I did verify in an separate, non-X-Plane-related build that I can use ros::init() in this way without crashing...)
(3) Generally: how does one go about debugging a setup like this (on mac, ros inside a plugin inside another app)? How can I get more details about what is going on when ros::init() is called?


Any help/suggestions/pointers are appreciated. Details below.


Platform: Mac OS X Snow Leopard
gcc: i686-apple-darwin10-gcc-4.2.1
ROS: cturtle (I'm just using ros core for now, given known problems with other packages on the mac, such a gazebo and wx*); I installed ROS core fresh on July 26.  I've been able to work through the simple roscpp for the publisher/subscriber and simple adding service and those work fine on my mac.
X-Plane version: 9.06rc2
    -- free demo app that can run the plugin available here:
        http://www.x-plane.com/pg_downloads.html
    -- run updater 2.05 from this same page to get the latest.
Downloading the X-Plane plugin SDK: I'm using the X-Plane SDK 2.0.1: 
    http://www.xsquawkbox.net/xpsdk/mediawiki/Download
    -- Only need the contents under SDK/CHeaders  (more on this below)



ROS package setup:
I created a simple ros package that depends on roscpp and std_msgs. Under src I placed another directory called xplane_sdk/ that contains the _contents_ of the X-Plane SDK/CHeaders/ directory (i.e., the Widgets, Wrapper and XPLM directories).

At the end of this email is the CMakeLists.txt I modified for building this package.

The file src/XP_ROS_Plugin.cpp contains the code to interface with the X-Plane plugin architecture -- I also list it below. (Near the top of the file is a log fn that uses XPlane's logging facilities to add log messages to the file <X-Plane-9 root>/Log.txt after running XPlane with the plugin; messages related to the XP_ROS_Plugin.xpl plugin all begin with '>>>'.)


The BUILD, INSTALL and RUN process:
After placing the files/directories in a ros package as described above, do rosmake.  All going well, the file XP_ROS_Plugin.xpl is generated under <pkg-root>/lib.
After building, put the plugin XP_ROS_Plugin.xpl in the X-Plane plugin folder: 
    <X-Plane-9 root>/Resources/plugins/
You can then launch X-Plane.  (If running the demo or you don't have the X-Plane CD, you will get a message about X-Plane going into demo mode, this is expected and unrelated to the plugin...)


Line 82 of src/XP_ROS_Plugin.cpp is the culprit -- this is where ros::init() is called. In the listing below it is commented-out. If building the plugin in this state and installing (putting the generated .xpl in the X-Plane plugin directory), then launching X-Plane (double-click) succeeds. (To verify the plugin has loaded properly: In X-Plane, go to the Plugins -> Plugin Admin -> Plugin Information and you'll see the plugin description text for "XP_ROS_Plugin"). Also, inspecting the X-Plane Log.txt includes logged lines starting with >>>, progressing beyond tick 2.

However, uncommenting line 82, buiding, installing, and then launching X-Plane results in early X-Plane crash.  The X-Plane Log.txt gets up to: 
    >>> XPluginStart: calling ros::init() tick 2




------------------
XP_ROS_Plugin.cpp:
------------------

#include "XPLMProcessing.h"
#include "XPLMUtilities.h"

#include "ros/ros.h"
#include "std_msgs/String.h"

#include <stdio.h>
#include <string>
#include <sstream>
#include <map>
using namespace std;

static int t;
static float tickPeriod;

void log(char *logString)
{
stringstream ss;
ss << ">>> " << logString << " tick " << t++ << endl;
XPLMDebugString(ss.str().c_str());
}

PLUGIN_API void XPluginStop(void)
{ }

PLUGIN_API void XPluginDisable(void)
{ }

PLUGIN_API int XPluginEnable(void)
{
return 1;
}

PLUGIN_API void XPluginReceiveMessage(XPLMPluginID inFromWho,
                                      long         inMessage,
                                      void *       inParam)
{ }


void rosCallback(const std_msgs::String::ConstPtr& msg)
{
const char *constMsg = msg->data.c_str();
char *msg1 = new char[strlen(constMsg)];
strcpy(msg1, constMsg);
log(msg1);
}

XPLM_API float MyFlightLoopCallback(float  inElapsedSinceLastCall,
                                    float  inElapsedTimeSinceLastFlightLoop,
                                    int    inCounter,
                                    void * inRefcon)
{
  log("ROSListenerNode Called");


return tickPeriod;
}

PLUGIN_API int XPluginStart(char * outName,
                            char * outSig,
                            char * outDesc)
{
  strcpy(outName, "XP_ROS_Plugin");
  strcpy(outSig,  "edu.au.xprosplugin");
  strcpy(outDesc, "An XPlane plugin implementing a ROS node");


t = 0;
tickPeriod = 1.0;

log("XPluginStart: defining map<string,string>");
map<string, string> m;
log("XPluginStart: defining map<string,string> DONE");

log("XPluginStart: calling ros::init()");
// ros::init(m, "XP_Plugin_Node");
log("XPluginStart: ros::init() CALLED");

  XPLMRegisterFlightLoopCallback(MyFlightLoopCallback,
                                 tickPeriod,
                                 NULL);


return 1;
}





---------------
CMakeLists.txt:
---------------

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

# Set the build type.  Options are:
#  Coverage       : w/ debug symbols, w/o optimization, w/ code-coverage
#  Debug          : w/ debug symbols, w/o optimization
#  Release        : w/o debug symbols, w/ optimization
#  RelWithDebInfo : w/ debug symbols, w/ optimization
#  MinSizeRel     : w/o debug symbols, w/ optimization, stripped binaries
#set(ROS_BUILD_TYPE RelWithDebInfo)


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)

#uncomment if you have defined messages
#rosbuild_genmsg()
#uncomment if you have defined services
#rosbuild_gensrv()

#common commands for building c++ executables and libraries
#rosbuild_add_library(${PROJECT_NAME} src/example.cpp)
#target_link_libraries(${PROJECT_NAME} another_library)
#rosbuild_add_boost_directories()
#rosbuild_link_boost(${PROJECT_NAME} thread)
#rosbuild_add_executable(example examples/example.cpp)
#target_link_libraries(example ${PROJECT_NAME})


# project(XP_ROS_Plugin)

message(">>> PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")

set(XPLANE_SDK_ROOT "${PROJECT_SOURCE_DIR}/src/xplane_sdk")

message(">>> XPLANE_SDK_ROOT: ${XPLANE_SDK_ROOT}")

set(OS_COMPILE_FLAGS "-D APL -m32")
set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup")

include_directories("${XPLANE_SDK_ROOT}/Widgets")
include_directories("${XPLANE_SDK_ROOT}/XPLM")

set(CMAKE_C_FLAGS "${OS_COMPILE_FLAGS} -D XPLM200 -D XPLM=1")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")

file(GLOB SRC_FILES "src/*.cpp")

message(">>> SRC_FILES: ${SRC_FILES}")

rosbuild_add_library(XP_ROS_Plugin ${SRC_FILES})
target_link_libraries(XP_ROS_Plugin ${OSX_LIBRARIES})
set_target_properties(XP_ROS_Plugin PROPERTIES PREFIX "" SUFFIX ".xpl")