ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
1 | initial version |
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.
cmake_minimum_required(VERSION 2.4.6) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
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)
And the opengl code is (just the normal opengl program): //t.c
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; }
2 | No.2 Revision |
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.
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):
//t.c
#include <stdio.h>
#include <stdlib.h>
#include <GL/glx.h>
/* this includes the necessary X headers
/*
/*
/*
/*
/*
/*
/*
/*
/*
}
return 0; }