ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

answered 2011-02-28 21:55:52 -0500

sam gravatar image

Because embedded ROS node in your program maybe hard (how hard I don't know~XD), so if we try to think another way that we can try to embedded other libs in ROS node to get the same outcome. Because ROS node also use main...return 0, so you can add any function you like in ROS node just you write your normal program without ROS utilties. And link all the libraries to ROS node (Cmake).

I can show one example:
(in my editing is ok,but ros answer showing will cut my cmake configruation in preview so you can just understand what I say,but not to copy and paste...) If my program is written in opengl. It maybe hard to embedded ROS in my opengl program. So I create a normal ROS package, put all the opengl program in that ROS node, and link opengl libs in CMakeLists.txt.

That my CMakeLists.txt is

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})

rosbuild_add_executable(opengl_test src/t.c) target_link_libraries(opengl_test /usr/lib/libGL.so) target_link_libraries(opengl_test /usr/lib/libX11.a)

target_link_libraries(opengl_test /usr/lib/libX11.so)

And the opengl code is (just the normal opengl program): //t.c

include <stdio.h>

include <stdlib.h>

include <gl glx.h=""> /* this includes the necessary X headers */

include <gl gl.h="">

include <x11 x.h=""> /* X11 constant (e.g. TrueColor) */

include <x11 keysym.h="">

static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, None}; static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None};

Display *dpy; Window win; GLfloat xAngle = 42.0, yAngle = 82.0, zAngle = 112.0; GLboolean doubleBuffer = GL_TRUE;

void fatalError(char *message) { fprintf(stderr, "main: %s\n", message); exit(1); }

void redraw(void) { static GLboolean displayListInited = GL_FALSE;

if (displayListInited) { /* if display list already exists, just execute it / glCallList(1); } else { / otherwise compile and execute to create the display list */ glNewList(1, GL_COMPILE_AND_EXECUTE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* front face */
glBegin(GL_QUADS);
  glColor3f(0.0, 0.7, 0.1);  /* green */
  glVertex3f(-1.0, 1.0, 1.0);
  glVertex3f(1.0, 1.0, 1.0);
  glVertex3f(1.0, -1.0, 1.0);
  glVertex3f(-1.0, -1.0, 1.0);

  /* back face */
  glColor3f(0.9, 1.0, 0.0);  /* yellow */
  glVertex3f(-1.0, 1.0, -1.0);
  glVertex3f(1.0, 1.0, -1.0);
  glVertex3f(1.0, -1.0, -1.0);
  glVertex3f(-1.0, -1.0, -1.0);

  /* top side face */
  glColor3f(0.2, 0.2, 1.0);  /* blue */
  glVertex3f(-1.0, 1.0, 1.0);
  glVertex3f(1.0, 1.0, 1.0);
  glVertex3f(1.0, 1.0, -1.0);
  glVertex3f(-1.0, 1.0, -1.0);

  /* bottom side face */
  glColor3f(0.7, 0.0, 0.1);  /* red */
  glVertex3f(-1.0, -1.0, 1.0);
  glVertex3f(1.0, -1.0, 1.0);
  glVertex3f(1.0, -1.0, -1.0);
  glVertex3f(-1.0, -1.0, -1.0);
glEnd();
glEndList();
displayListInited = GL_TRUE;

} if (doubleBuffer) glXSwapBuffers(dpy, win);/* buffer swap does implicit glFlush / else glFlush(); / explicit flush for single buffered case */ }

int main(int argc, char **argv) { XVisualInfo *vi; Colormap cmap; XSetWindowAttributes swa; GLXContext cx; XEvent event; GLboolean needRedraw = GL_FALSE, recalcModelView = GL_TRUE; int dummy;

/* (1) open a connection to the X server */

dpy = XOpenDisplay(NULL); if (dpy == NULL) fatalError("could not open display");

/* (2) make sure OpenGL's GLX extension supported */

if(!glXQueryExtension(dpy, &dummy, &dummy)) fatalError("X server has no OpenGL GLX extension");

/* (3) find an appropriate visual */

/* find an OpenGL-capable RGB visual with depth buffer */ vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf); if (vi == NULL) { vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf); if (vi == NULL) fatalError("no RGB visual with depth buffer"); doubleBuffer = GL_FALSE; } if(vi->class != TrueColor) fatalError("TrueColor visual required for this program");

/* (4) create an OpenGL rendering context */

/* create an OpenGL rendering context / cx = glXCreateContext(dpy, vi, / no shared dlists / None, / direct rendering if possible */ GL_TRUE); if (cx == NULL) fatalError("could not create rendering context");

/* (5) create an X window with the selected visual */

/* create an X colormap since probably not using default visual */ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = KeyPressMask | ExposureMask | ButtonPressMask | StructureNotifyMask; win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 300, 300, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa); XSetStandardProperties(dpy, win, "main", "main", None, argv, argc, NULL);

/* (6) bind the rendering context to the window */

glXMakeCurrent(dpy, win, cx);

/* (7) request the X window to be displayed on the screen */

XMapWindow(dpy, win);

/* (8) configure the OpenGL context for rendering */

glEnable(GL_DEPTH_TEST); /* enable depth buffering / glDepthFunc(GL_LESS); / pedantic, GL_LESS is the default / glClearDepth(1.0); / pedantic, 1.0 is the default */

/* frame buffer clears should be to black */ glClearColor(0.0, 0.0, 0.0, 0.0);

/* set up projection transform / glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0); / establish initial viewport / / pedantic, full window size is default viewport */ glViewport(0, 0, 300, 300);

printf( "Press left mouse button to rotate around X axis\n" ); printf( "Press middle mouse button to rotate around Y axis\n" ); printf( "Press right mouse button to rotate around Z axis\n" ); printf( "Press ESC to quit the application\n" );

/* (9) dispatch X events */

while (1) { do { XNextEvent(dpy, &event); switch (event.type) { case KeyPress: { KeySym keysym; XKeyEvent kevent; char buffer[1]; / It is necessary to convert the keycode to a * keysym before checking if it is an escape / kevent = (XKeyEvent *) &event; if ( (XLookupString((XKeyEvent *)&event,buffer,1,&keysym,NULL) == 1) && (keysym == (KeySym)XK_Escape) ) exit(0); break; } case ButtonPress: recalcModelView = GL_TRUE; switch (event.xbutton.button) { case 1: xAngle += 10.0; break; case 2: yAngle += 10.0; break; case 3: zAngle += 10.0; break; } break; case ConfigureNotify: glViewport(0, 0, event.xconfigure.width, event.xconfigure.height); / fall through... / case Expose: needRedraw = GL_TRUE; break; } } while(XPending(dpy)); / loop to compress events */

if (recalcModelView)
{
  glMatrixMode(GL_MODELVIEW);

  /* reset modelview matrix to the identity matrix */
  glLoadIdentity();

  /* move the camera back three units */
  glTranslatef(0.0, 0.0, -3.0);

  /* rotate by X, Y, and Z angles */
  glRotatef(xAngle, 0.1, 0.0, 0.0);
  glRotatef(yAngle, 0.0, 0.1, 0.0);
  glRotatef(zAngle, 0.0, 0.0, 1.0);

  recalcModelView = GL_FALSE;
  needRedraw = GL_TRUE;
}
if (needRedraw)
{
  redraw();
  needRedraw = GL_FALSE;
}

}

return 0; }

Because embedded ROS node in your program maybe hard (how hard I don't know~XD), so if we try to think another way that we can try to embedded other libs in ROS node to get the same outcome. Because ROS node also use main...return 0, so you can add any function you like in ROS node just you write your normal program without ROS utilties. And link all the libraries to ROS node (Cmake).

I can show one example:
(in my editing is ok,but ros answer showing will cut my cmake configruation in preview so you can just understand what I say,but not to copy and paste...) If my program is written in opengl. It maybe hard to embedded ROS in my opengl program. So I create a normal ROS package, put all the opengl program in that ROS node, and link opengl libs in CMakeLists.txt.

CMakeLists.txt. That my CMakeLists.txt is

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

include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) # Set the build type. Options are:

are: # Coverage : w/ debug symbols, w/o optimization, w/ code-coverage

code-coverage # Debug : w/ debug symbols, w/o optimization

optimization # Release : w/o debug symbols, w/ optimization

optimization # RelWithDebInfo : w/ debug symbols, w/ optimization

optimization # MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries

set(ROS_BUILD_TYPE RelWithDebInfo)

rosbuild_init()

set binaries #set(ROS_BUILD_TYPE RelWithDebInfo) rosbuild_init() #set the default path for built executables to the "bin" directory

directory set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

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

directory set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)

uncomment ${PROJECT_SOURCE_DIR}/lib) #uncomment if you have defined messages

rosbuild_genmsg()

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

rosbuild_gensrv()

common 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})

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}) rosbuild_add_executable(opengl_test src/t.c) target_link_libraries(opengl_test /usr/lib/libGL.so) target_link_libraries(opengl_test /usr/lib/libX11.a)

/usr/lib/libX11.a) target_link_libraries(opengl_test /usr/lib/libX11.so)

/usr/lib/libX11.so)

And the opengl code is (just the normal opengl program): //t.cprogram):

include <stdio.h>

include <stdlib.h>

include <gl glx.h="">
 //t.c
 #include <stdio.h>
 #include <stdlib.h>     
 #include <GL/glx.h>    /* this includes the necessary X  headers */

include <gl gl.h="">

include <x11 x.h=""> */ #include <GL/gl.h> #include <X11/X.h> /* X11 constant (e.g. TrueColor) */

include <x11 keysym.h="">

*/ #include <X11/keysym.h> static int snglBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, None}; static int dblBuf[] = {GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_DOUBLEBUFFER, None};

None}; Display *dpy; Window win; GLfloat xAngle = 42.0, yAngle = 82.0, zAngle = 112.0; GLboolean doubleBuffer = GL_TRUE;

GL_TRUE; void fatalError(char *message) { fprintf(stderr, "main: %s\n", message); exit(1); }

} void redraw(void) { static GLboolean displayListInited = GL_FALSE;

GL_FALSE; if (displayListInited) { /* if display list already exists, just execute it / */ glCallList(1); } else { / /* otherwise compile and execute to create the display list */ */ glNewList(1, GL_COMPILE_AND_EXECUTE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

GL_DEPTH_BUFFER_BIT);

     /* front face */
 glBegin(GL_QUADS);
   glColor3f(0.0, 0.7, 0.1);  /* green */
   glVertex3f(-1.0, 1.0, 1.0);
   glVertex3f(1.0, 1.0, 1.0);
   glVertex3f(1.0, -1.0, 1.0);
   glVertex3f(-1.0, -1.0, 1.0);

   /* back face */
   glColor3f(0.9, 1.0, 0.0);  /* yellow */
   glVertex3f(-1.0, 1.0, -1.0);
   glVertex3f(1.0, 1.0, -1.0);
   glVertex3f(1.0, -1.0, -1.0);
   glVertex3f(-1.0, -1.0, -1.0);

   /* top side face */
   glColor3f(0.2, 0.2, 1.0);  /* blue */
   glVertex3f(-1.0, 1.0, 1.0);
   glVertex3f(1.0, 1.0, 1.0);
   glVertex3f(1.0, 1.0, -1.0);
   glVertex3f(-1.0, 1.0, -1.0);

   /* bottom side face */
   glColor3f(0.7, 0.0, 0.1);  /* red */
   glVertex3f(-1.0, -1.0, 1.0);
   glVertex3f(1.0, -1.0, 1.0);
   glVertex3f(1.0, -1.0, -1.0);
   glVertex3f(-1.0, -1.0, -1.0);
 glEnd();
 glEndList();
 displayListInited = GL_TRUE;

} if (doubleBuffer) glXSwapBuffers(dpy, win);/* buffer swap does implicit glFlush / */ else glFlush(); / /* explicit flush for single buffered case */ }

} int main(int argc, char **argv) { XVisualInfo *vi; Colormap cmap; XSetWindowAttributes swa; GLXContext cx; XEvent event; GLboolean needRedraw = GL_FALSE, recalcModelView = GL_TRUE; int dummy;

/* dummy; /*** (1) open a connection to the X server */

***/ dpy = XOpenDisplay(NULL); if (dpy == NULL) fatalError("could not open display");

/* display"); /*** (2) make sure OpenGL's GLX extension supported */

***/ if(!glXQueryExtension(dpy, &dummy, &dummy)) fatalError("X server has no OpenGL GLX extension");

/* extension"); /*** (3) find an appropriate visual */

***/ /* find an OpenGL-capable RGB visual with depth buffer */ vi = glXChooseVisual(dpy, DefaultScreen(dpy), dblBuf); if (vi == NULL) { vi = glXChooseVisual(dpy, DefaultScreen(dpy), snglBuf); if (vi == NULL) fatalError("no RGB visual with depth buffer"); doubleBuffer = GL_FALSE; } if(vi->class != TrueColor) fatalError("TrueColor visual required for this program");

/* program"); /*** (4) create an OpenGL rendering context */

***/ /* create an OpenGL rendering context / */ cx = glXCreateContext(dpy, vi, / /* no shared dlists / */ None, / /* direct rendering if possible */ GL_TRUE); if (cx == NULL) fatalError("could not create rendering context");

/* context"); /*** (5) create an X window with the selected visual */

***/ /* create an X colormap since probably not using default visual */ cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone); swa.colormap = cmap; swa.border_pixel = 0; swa.event_mask = KeyPressMask | ExposureMask | ButtonPressMask | StructureNotifyMask; win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 300, 300, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa); XSetStandardProperties(dpy, win, "main", "main", None, argv, argc, NULL);

/* NULL); /*** (6) bind the rendering context to the window */

***/ glXMakeCurrent(dpy, win, cx);

/* cx); /*** (7) request the X window to be displayed on the screen */

***/ XMapWindow(dpy, win);

/* win); /*** (8) configure the OpenGL context for rendering */

***/ glEnable(GL_DEPTH_TEST); /* enable depth buffering / */ glDepthFunc(GL_LESS); / /* pedantic, GL_LESS is the default / */ glClearDepth(1.0); / /* pedantic, 1.0 is the default */

*/ /* frame buffer clears should be to black */ glClearColor(0.0, 0.0, 0.0, 0.0);

0.0); /* set up projection transform / */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0); / /* establish initial viewport / / */ /* pedantic, full window size is default viewport */ glViewport(0, 0, 300, 300);

300); printf( "Press left mouse button to rotate around X axis\n" ); printf( "Press middle mouse button to rotate around Y axis\n" ); printf( "Press right mouse button to rotate around Z axis\n" ); printf( "Press ESC to quit the application\n" );

/* ); /*** (9) dispatch X events */

***/ while (1) { do { XNextEvent(dpy, &event); switch (event.type) { case KeyPress: { KeySym keysym; XKeyEvent kevent; *kevent; char buffer[1]; / /* It is necessary to convert the keycode to a * keysym before checking if it is an escape / */ kevent = (XKeyEvent *) &event; if ( (XLookupString((XKeyEvent *)&event,buffer,1,&keysym,NULL) == 1) && (keysym == (KeySym)XK_Escape) ) exit(0); break; } case ButtonPress: recalcModelView = GL_TRUE; switch (event.xbutton.button) { case 1: xAngle += 10.0; break; case 2: yAngle += 10.0; break; case 3: zAngle += 10.0; break; } break; case ConfigureNotify: glViewport(0, 0, event.xconfigure.width, event.xconfigure.height); / /* fall through... / */ case Expose: needRedraw = GL_TRUE; break; } } while(XPending(dpy)); / /* loop to compress events */

*/

     if (recalcModelView)
 {
   glMatrixMode(GL_MODELVIEW);

   /* reset modelview matrix to the identity matrix */
   glLoadIdentity();

   /* move the camera back three units */
   glTranslatef(0.0, 0.0, -3.0);

   /* rotate by X, Y, and Z angles */
   glRotatef(xAngle, 0.1, 0.0, 0.0);
   glRotatef(yAngle, 0.0, 0.1, 0.0);
   glRotatef(zAngle, 0.0, 0.0, 1.0);

   recalcModelView = GL_FALSE;
   needRedraw = GL_TRUE;
 }
 if (needRedraw)
 {
   redraw();
   needRedraw = GL_FALSE;
     }
   }

   return 0;
 }

}

return 0; }