.
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(hos_cosgi_core)
|
||||
|
||||
## Find catkin macros and libraries
|
||||
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
|
||||
## is used, also find other catkin packages
|
||||
find_package(catkin REQUIRED COMPONENTS
|
||||
hos_celix
|
||||
roscpp
|
||||
hos_cpp_utils
|
||||
hos_libvariant
|
||||
)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
find_package(Boost REQUIRED)
|
||||
find_package(APR REQUIRED)
|
||||
|
||||
|
||||
## Uncomment this if the package has a setup.py. This macro ensures
|
||||
## modules and global scripts declared therein get installed
|
||||
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
|
||||
# catkin_python_setup()
|
||||
|
||||
################################################
|
||||
## Declare ROS messages, services and actions ##
|
||||
################################################
|
||||
|
||||
## To declare and build messages, services or actions from within this
|
||||
## package, follow these steps:
|
||||
## * Let MSG_DEP_SET be the set of packages whose message types you use in
|
||||
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
|
||||
## * If MSG_DEP_SET isn't empty the following dependencies might have been
|
||||
## pulled in transitively but can be declared for certainty nonetheless:
|
||||
## * add a build_depend tag for "message_generation"
|
||||
## * add a run_depend tag for "message_runtime"
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "message_generation" and every package in MSG_DEP_SET to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * add "message_runtime" and every package in MSG_DEP_SET to
|
||||
## catkin_package(CATKIN_DEPENDS ...)
|
||||
## * uncomment the add_*_files sections below as needed
|
||||
## and list every .msg/.srv/.action file to be processed
|
||||
## * uncomment the generate_messages entry below
|
||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||
|
||||
## Generate messages in the 'msg' folder
|
||||
# add_message_files(
|
||||
# FILES
|
||||
# Message1.msg
|
||||
# Message2.msg
|
||||
# )
|
||||
|
||||
## Generate services in the 'srv' folder
|
||||
# add_service_files(
|
||||
# FILES
|
||||
# Service1.srv
|
||||
# Service2.srv
|
||||
# )
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
# add_action_files(
|
||||
# FILES
|
||||
# Action1.action
|
||||
# Action2.action
|
||||
# )
|
||||
|
||||
## Generate added messages and services with any dependencies listed here
|
||||
# generate_messages(
|
||||
# DEPENDENCIES
|
||||
# std_msgs # Or other packages containing msgs
|
||||
# )
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
INCLUDE_DIRS include/${PROJECT_NAME}/
|
||||
# LIBRARIES hos_cosgi_launcher
|
||||
CATKIN_DEPENDS hos_celix
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
add_definitions(
|
||||
-std=c++11
|
||||
)
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
# include_directories(include)
|
||||
include_directories(
|
||||
${catkin_INCLUDE_DIRS}
|
||||
${APR_INCLUDE_DIR}
|
||||
${APR_INCLUDE_DIR}/apr-1.0
|
||||
include/${PROJECT_NAME}/
|
||||
)
|
||||
|
||||
|
||||
add_executable(hos_cosgi_launcher
|
||||
src/launcher.cpp
|
||||
src/hos/cosgi/service/core/core_serviceimpl.cpp
|
||||
)
|
||||
target_link_libraries(hos_cosgi_launcher
|
||||
${catkin_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
## Declare a cpp library
|
||||
# add_library(hos_osgi_launcher
|
||||
# src/${PROJECT_NAME}/hos_osgi_launcher.cpp
|
||||
# )
|
||||
|
||||
## Declare a cpp executable
|
||||
# add_executable(hos_osgi_launcher_node src/hos_osgi_launcher_node.cpp)
|
||||
|
||||
## Add cmake target dependencies of the executable/library
|
||||
## as an example, message headers may need to be generated before nodes
|
||||
# add_dependencies(hos_osgi_launcher_node hos_osgi_launcher_generate_messages_cpp)
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
# target_link_libraries(hos_osgi_launcher_node
|
||||
# ${catkin_LIBRARIES}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Install ##
|
||||
#############
|
||||
|
||||
# all install targets should use catkin DESTINATION variables
|
||||
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
|
||||
|
||||
## Mark executable scripts (Python etc.) for installation
|
||||
## in contrast to setup.py, you can choose the destination
|
||||
# install(PROGRAMS
|
||||
# scripts/my_python_script
|
||||
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
# )
|
||||
|
||||
## Mark executables and/or libraries for installation
|
||||
install(TARGETS hos_cosgi_launcher
|
||||
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
|
||||
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
|
||||
)
|
||||
|
||||
## Mark cpp header files for installation
|
||||
install(DIRECTORY include/${PROJECT_NAME}/
|
||||
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
|
||||
FILES_MATCHING PATTERN "*.h"
|
||||
PATTERN ".svn" EXCLUDE
|
||||
)
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc
|
||||
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
OPTIONAL
|
||||
)
|
||||
|
||||
## Mark other files for installation (e.g. launch and bag files, etc.)
|
||||
# install(FILES
|
||||
# # myfile1
|
||||
# # myfile2
|
||||
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_hos_osgi_launcher.cpp)
|
||||
# if(TARGET ${PROJECT_NAME}-test)
|
||||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
|
||||
# endif()
|
||||
|
||||
## Add folders to be run by python nosetests
|
||||
# catkin_add_nosetests(test)
|
||||
|
||||
|
||||
###################
|
||||
## Documentation ##
|
||||
###################
|
||||
|
||||
find_package(Doxygen)
|
||||
if(DOXYGEN_FOUND)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
|
||||
add_custom_target(doc
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
endif(DOXYGEN_FOUND)
|
||||
@@ -0,0 +1,248 @@
|
||||
# Doxyfile 1.8.8
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = hos_cosgi_core
|
||||
OUTPUT_DIRECTORY = doc
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class" \
|
||||
"The $name widget" \
|
||||
"The $name file" \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = NO
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = NO
|
||||
HIDE_UNDOC_CLASSES = NO
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = @CMAKE_CURRENT_SOURCE_DIR@/include \
|
||||
@CMAKE_CURRENT_SOURCE_DIR@/src
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.idl \
|
||||
*.ddl \
|
||||
*.odl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.cs \
|
||||
*.d \
|
||||
*.php \
|
||||
*.php4 \
|
||||
*.php5 \
|
||||
*.phtml \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.markdown \
|
||||
*.md \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.f90 \
|
||||
*.f \
|
||||
*.for \
|
||||
*.tcl \
|
||||
*.vhd \
|
||||
*.vhdl \
|
||||
*.ucf \
|
||||
*.qsf \
|
||||
*.as \
|
||||
*.js
|
||||
RECURSIVE = YES
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
|
||||
DOCSET_PUBLISHER_NAME = Publisher
|
||||
GENERATE_HTMLHELP = NO
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
GENERATE_QHP = NO
|
||||
QHP_NAMESPACE = org.doxygen.Project
|
||||
QHP_VIRTUAL_FOLDER = doc
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
GENERATE_TREEVIEW = YES
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
DOT_FONTNAME = Helvetica
|
||||
DOT_FONTSIZE = 10
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
@@ -0,0 +1,268 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include "Interface.h"
|
||||
#include <mutex>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
|
||||
// main namespace
|
||||
namespace hos {
|
||||
namespace cosgi{
|
||||
namespace service {
|
||||
namespace implementation {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Template holding information about a service.
|
||||
*
|
||||
* Works in conjunction with the Service class below which is the implementation of interface::Service.
|
||||
* Concrete services need to inherit the Service class and specialize this template.
|
||||
*/
|
||||
template<class _Service>
|
||||
struct ServiceInfo {
|
||||
static const char* name /** Service name. */;
|
||||
static const int major /** Version major number. */;
|
||||
static const int minor /** Version minor number. */;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of interface::Service.
|
||||
*/
|
||||
template<class _Service>
|
||||
class Service
|
||||
: public virtual interface::Service {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Returns the name of the service.
|
||||
*
|
||||
* \return service name.
|
||||
**/
|
||||
virtual const char* getServiceName() {
|
||||
return ServiceInfo<_Service>::name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the version of the service.
|
||||
*
|
||||
* \param[out] major version major number.
|
||||
* \param[out] minor version minor number.
|
||||
*/
|
||||
virtual void getServiceVersion(int& major, int& minor) override {
|
||||
major = ServiceInfo<_Service>::major;
|
||||
minor = ServiceInfo<_Service>::minor;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of interface::Observable.
|
||||
*
|
||||
* This template does not provide any functionality, so do not use it but use only its specializations.
|
||||
*/
|
||||
template <class... _Args> class Observable {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of interface::Observable<_Event>.
|
||||
*
|
||||
* Observers are stored in an std::unordered_set.
|
||||
*/
|
||||
template<class _Event>
|
||||
class Observable<_Event>
|
||||
: public virtual interface::Observable<_Event> {
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::unordered_set<typename interface::Observable<_Event>::observer_type*> observers_type;
|
||||
|
||||
std::mutex _observersMutex;
|
||||
|
||||
observers_type _observers;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Observable() {}
|
||||
|
||||
/**
|
||||
* Registers an observer.
|
||||
*
|
||||
* \param[in] o observer to be registered.
|
||||
*/
|
||||
virtual void addObserver(typename interface::Observable<_Event>::observer_type* o) override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
if (o != nullptr) {
|
||||
auto elem = _observers.find(o);
|
||||
if (elem == _observers.end()) {
|
||||
_observers.insert(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an observer.
|
||||
*
|
||||
* \param[in] o observer to be unregistered.
|
||||
*/
|
||||
virtual void deleteObserver(typename interface::Observable<_Event>::observer_type* o) override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
if (o != nullptr) {
|
||||
auto elem = _observers.find(o);
|
||||
if (elem != _observers.end()) {
|
||||
_observers.erase(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all observers.
|
||||
*/
|
||||
virtual void deleteObservers() override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
_observers.clear();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of registered observers.
|
||||
*
|
||||
* \return number of registered observers.
|
||||
*/
|
||||
virtual size_t countObservers() override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
return _observers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify observers of a new event.
|
||||
*
|
||||
* \param[in] e event.
|
||||
*/
|
||||
virtual void notifyObservers(const _Event* e) override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
for (auto l : _observers) {
|
||||
l->notificationReceived(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of interface::Observable<_Key, _Event>.
|
||||
*
|
||||
* Observers are stored in an std::unordered_map using the filter key as map key.
|
||||
*/
|
||||
template<class _Key, class _Event>
|
||||
class Observable<_Key, _Event>
|
||||
: public virtual interface::Observable<_Key, _Event> {
|
||||
|
||||
protected:
|
||||
|
||||
typedef std::unordered_multimap<_Key, typename interface::Observable<_Key, _Event>::observer_type*> observers_type;
|
||||
|
||||
std::mutex _observersMutex;
|
||||
|
||||
observers_type _observers;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Observable() {}
|
||||
|
||||
/**
|
||||
* Registers an observer.
|
||||
*
|
||||
* \param[in] k filter key.
|
||||
* \param[in] o observer to be registered.
|
||||
*/
|
||||
virtual void addObserver(_Key k, typename interface::Observable<_Key, _Event>::observer_type* o) override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
if (o != nullptr) {
|
||||
bool _found = false;
|
||||
auto range = _observers.equal_range(k);
|
||||
for (auto i = range.first; i != range.second; i++) {
|
||||
if (i.second == o) {
|
||||
_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!_found) {
|
||||
_observers.insert({k, o});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters an observer.
|
||||
*
|
||||
* \param[in] k filter key.
|
||||
* \param[in] o observer to be unregistered.
|
||||
*/
|
||||
virtual void deleteObserver(_Key k, typename interface::Observable<_Key, _Event>::observer_type* o) override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
if (o != nullptr) {
|
||||
bool _found = false;
|
||||
auto range = _observers.equal_range(k);
|
||||
for (auto i = range.first; i != range.second; i++) {
|
||||
if (i.second == o) {
|
||||
_observers.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all observers.
|
||||
*/
|
||||
virtual void deleteObservers() override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
_observers.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of registered observers.
|
||||
*
|
||||
* \return number of registered observers.
|
||||
*/
|
||||
virtual size_t countObservers() override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
return _observers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify observers of a new event.
|
||||
*
|
||||
* \param[in] k observer filter key.
|
||||
* \param[in] e event.
|
||||
*/
|
||||
void notifyObservers(_Key k, const _Event* e) override {
|
||||
std::lock_guard<std::mutex> lock(_observersMutex);
|
||||
auto ol = _observers.equal_range(k);
|
||||
std::for_each(ol.first, ol.second, [&](const typename interface::Observable<_Key, _Event>::observer_type::value_type& o) {
|
||||
o.second->notificationReceived(this, k, e);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -0,0 +1,271 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
|
||||
// main namespace
|
||||
namespace hos {
|
||||
namespace cosgi{
|
||||
namespace service {
|
||||
namespace interface {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic public OSGI interface class.
|
||||
*
|
||||
* Every public OSGI interface class needs to inherit from this class.
|
||||
* At the moment it only defines an empty virtual destructor.
|
||||
*/
|
||||
class Object {
|
||||
public:
|
||||
virtual ~Object() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic public OSGI service interface class.
|
||||
*
|
||||
* Every public OSGI service interface class needs to inherit from this class.
|
||||
* Defines generic methods to get information about a service.
|
||||
*/
|
||||
class Service
|
||||
: public virtual Object {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Returns the name of the service.
|
||||
*
|
||||
* The service name is used to register a service in the OSGI framework.
|
||||
*
|
||||
* \return service name.
|
||||
**/
|
||||
virtual const char* getServiceName() = 0;
|
||||
|
||||
/**
|
||||
* Returns the version of the service.
|
||||
*
|
||||
* The version numbers are used to determine compatibility. Different major numbers are incompatible with each other.
|
||||
* Different minor numbers are backwards compatible (e.g. a mininum requirement of 1.2 means that service version 1.3 is compatible
|
||||
* but service version 1.1 is incompatible).
|
||||
*
|
||||
* \param[out] major version major number.
|
||||
* \param[out] minor version minor number.
|
||||
*/
|
||||
virtual void getServiceVersion(int& major, int& minor) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Public OSGI interface template implementing the observer from the observer-pattern.
|
||||
*
|
||||
* This template does not provide any functionality, so do not use it but use only its specializations.
|
||||
*/
|
||||
template<class...> class Observer {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Public OSGI interface template implementing the observable from the observer-pattern.
|
||||
*
|
||||
* This template does not provide any functionality, so do not use it but use only its specializations.
|
||||
*/
|
||||
template<class...> class Observable {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convenience template merging the Object class and the Observable template into a single template.
|
||||
*/
|
||||
template<class... _Args> class ObservableObject
|
||||
: public virtual Object,
|
||||
public virtual Observable<_Args...> {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Convenience template merging the Service class and the Observable template into a single template.
|
||||
*/
|
||||
template<class... _Args> class ObservableService
|
||||
: public virtual Service,
|
||||
public virtual Observable<_Args...> {};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specialization of the Observer template with one template argument (the event emitted from the observable).
|
||||
*/
|
||||
template<class _Event>
|
||||
class Observer<_Event>
|
||||
: public virtual Object {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Specifies the type of compatible observables.
|
||||
*/
|
||||
typedef Observable<_Event> observable_type;
|
||||
|
||||
/**
|
||||
* Function that is called when an event is emitted by the observable object.
|
||||
*
|
||||
* \param[in] o observable object emitting the event.
|
||||
* \param[in] e the event (can be null).
|
||||
*/
|
||||
virtual void notificationReceived(observable_type* o, const _Event* e) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specialization of the Observer template with two template arguments (the key used to filter observers,
|
||||
* and the event emitted from the observable).
|
||||
*/
|
||||
template<class _Key, class _Event>
|
||||
class Observer<_Key, _Event>
|
||||
: public virtual Object {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Specifies the type of compatible observables.
|
||||
*/
|
||||
typedef Observable<_Key, _Event> observable_type;
|
||||
|
||||
/**
|
||||
* Function that is called when an event is emitted by the observable object.
|
||||
*
|
||||
* \param[in] o observable object emitting the event.
|
||||
* \param[in] key the filter key.
|
||||
* \param[in] e the event (can be null).
|
||||
*/
|
||||
virtual void notificationReceived(observable_type* o, const _Key& key, const _Event* e) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specialization of the Observable template with one template argument (the event emitted from the observable).
|
||||
*
|
||||
* When an event is emitted, all registered observers will be notified.
|
||||
*/
|
||||
template<class _Event>
|
||||
class Observable<_Event>
|
||||
: public virtual Object {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Specifies the type of compatible observers.
|
||||
*/
|
||||
typedef Observer<_Event> observer_type;
|
||||
|
||||
/**
|
||||
* Registers an observer.
|
||||
*
|
||||
* \param[in] o observer to be registered.
|
||||
*/
|
||||
virtual void addObserver(observer_type* o) = 0;
|
||||
|
||||
/**
|
||||
* Unregisters an observer.
|
||||
*
|
||||
* \param[in] o observer to be unregistered.
|
||||
*/
|
||||
virtual void deleteObserver(observer_type* o) = 0;
|
||||
|
||||
/**
|
||||
* Unregisters all observers.
|
||||
*/
|
||||
virtual void deleteObservers() = 0;
|
||||
|
||||
/**
|
||||
* Returns the number of registered observers.
|
||||
*
|
||||
* \return number of registered observers.
|
||||
*/
|
||||
virtual size_t countObservers() = 0;
|
||||
|
||||
/**
|
||||
* Notify observers of a new event.
|
||||
*
|
||||
* \param[in] e event.
|
||||
*/
|
||||
virtual void notifyObservers(const _Event* e) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Specialization of the Observable template with two template arguments (the key used to filter observers,
|
||||
* and the event emitted from the observable).
|
||||
*
|
||||
* When an event is emitted, only observers registered under the specified key will be notified.
|
||||
*/
|
||||
template<class _Key, class _Event>
|
||||
class Observable<_Key, _Event>
|
||||
: public virtual Object {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Specifies the type of compatible observers.
|
||||
*/
|
||||
typedef Observer<_Key, _Event> observer_type;
|
||||
|
||||
/**
|
||||
* Registers an observer.
|
||||
*
|
||||
* \param[in] key filter key.
|
||||
* \param[in] o observer to be registered.
|
||||
*/
|
||||
virtual void addObserver(_Key& key, observer_type* o) = 0;
|
||||
|
||||
/**
|
||||
* Unregisters an observer.
|
||||
*
|
||||
* \param[in] key filter key.
|
||||
* \param[in] o observer to be unregistered.
|
||||
*/
|
||||
virtual void deleteObserver(_Key& key, observer_type* o) = 0;
|
||||
|
||||
/**
|
||||
* Unregisters all observers.
|
||||
*/
|
||||
virtual void deleteObservers() = 0;
|
||||
|
||||
/**
|
||||
* Returns the number of registered observers.
|
||||
*
|
||||
* \return number of registered observers.
|
||||
*/
|
||||
virtual size_t countObservers() = 0;
|
||||
|
||||
/**
|
||||
* Notify observers of a new event.
|
||||
*
|
||||
* \param[in] key observer filter key.
|
||||
* \param[in] e event.
|
||||
*/
|
||||
virtual void notifyObservers(const _Key& key, const _Event* e) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace interface
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include <hos/cosgi/service/Interface.h>
|
||||
|
||||
|
||||
|
||||
// Forward declarations
|
||||
namespace ros { class NodeHandle; }
|
||||
|
||||
|
||||
|
||||
// Service Namespace
|
||||
namespace hos {
|
||||
namespace cosgi {
|
||||
namespace service {
|
||||
namespace core {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base class for events emitted by the CoreService.
|
||||
*/
|
||||
class CoreServiceEvent {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* CoreService event types.
|
||||
*/
|
||||
enum class EventType : int { STARTUP_FINISHED = 1, SHUTDOWN = 2 };
|
||||
|
||||
/**
|
||||
* Event type.
|
||||
*/
|
||||
const EventType eventType;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
CoreServiceEvent(EventType type) : eventType(type) {}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Startup finished event.
|
||||
*
|
||||
* This event is emitted when all autostart bundles have been started and hos_cosgi_launcher is about to enter the main loop.
|
||||
*/
|
||||
class StartupFinishedEvent
|
||||
: public CoreServiceEvent {
|
||||
public:
|
||||
StartupFinishedEvent() : CoreServiceEvent(EventType::STARTUP_FINISHED) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Shutdown event.
|
||||
*
|
||||
* This event is emitted when hos_cosgi_launcher is about to exit.
|
||||
*/
|
||||
class ShutdownEvent
|
||||
: public CoreServiceEvent {
|
||||
public:
|
||||
ShutdownEvent() : CoreServiceEvent(EventType::SHUTDOWN) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Public COSGI interface of the CoreService.
|
||||
*
|
||||
* The CoreService is directly provided by hos_cosgi_launcher. The best way to test whether a bundle was started by
|
||||
* hos_cosgi_launcher is to try to retrieve the CoreService.
|
||||
*
|
||||
* It offers following functionality:
|
||||
* - Events indicating system events (currently startup, shutdown)
|
||||
* - Request application shutdown.
|
||||
* - Get ROS node handles.
|
||||
*/
|
||||
class CoreService
|
||||
: public virtual interface::ObservableService<CoreServiceEvent> {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* The service name.
|
||||
*/
|
||||
static constexpr const char* SERVICE_NAME = "hos_core_service";
|
||||
|
||||
/**
|
||||
* Returns a reference to a node handle with public namespace.
|
||||
*
|
||||
* The node handle was created using the default constructor.
|
||||
*
|
||||
* \return public node handle
|
||||
*/
|
||||
virtual ros::NodeHandle& getPublicNodeHandle() = 0;
|
||||
|
||||
/**
|
||||
* Returns a reference to a node handle with private namespace.
|
||||
*
|
||||
* The node handle was created using namespace "~".
|
||||
*
|
||||
* \return private node handle
|
||||
*/
|
||||
virtual ros::NodeHandle& getPrivateNodeHandle() = 0;
|
||||
|
||||
/**
|
||||
* Request an application shutdown
|
||||
*/
|
||||
virtual void requestShutdown() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace core
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>hos_cosgi_core</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The hos_cosgi_core package</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<!-- Example: -->
|
||||
<!-- <maintainer email="jane.doe@example.com">Jane Doe</maintainer> -->
|
||||
<maintainer email="matzman@todo.todo">matzman</maintainer>
|
||||
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
<!-- <url type="website">http://wiki.ros.org/hos_osgi_launcher</url> -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<!-- <build_depend>message_generation</build_depend> -->
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<!-- <run_depend>message_runtime</run_depend> -->
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>hos_celix</build_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>hos_cpp_utils</build_depend>
|
||||
<build_depend>hos_libvariant</build_depend>
|
||||
<run_depend>hos_celix</run_depend>
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>hos_cpp_utils</run_depend>
|
||||
<run_depend>hos_libvariant</run_depend>
|
||||
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- You can specify that this package is a metapackage here: -->
|
||||
<!-- <metapackage/> -->
|
||||
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* hos_core_service_impl.cpp
|
||||
*
|
||||
* Created on: 05.04.2015
|
||||
* Author: matzman
|
||||
*/
|
||||
|
||||
#include <ros/ros.h>
|
||||
#include "core_serviceimpl.h"
|
||||
|
||||
namespace hos {
|
||||
namespace cosgi{
|
||||
namespace service {
|
||||
namespace core {
|
||||
|
||||
template<> const char* implementation::ServiceInfo<CoreServiceImpl>::name = service::core::CoreService::SERVICE_NAME;
|
||||
template<> const int implementation::ServiceInfo<CoreServiceImpl>::major = 0;
|
||||
template<> const int implementation::ServiceInfo<CoreServiceImpl>::minor = 3;
|
||||
|
||||
CoreServiceImpl::CoreServiceImpl(ros::NodeHandle& publicNodeHandle, ros::NodeHandle& privateNodeHandle)
|
||||
: publicNodeHandle(publicNodeHandle), privateNodeHandle(privateNodeHandle) {}
|
||||
|
||||
|
||||
ros::NodeHandle& CoreServiceImpl::getPublicNodeHandle() {
|
||||
return publicNodeHandle;
|
||||
}
|
||||
|
||||
ros::NodeHandle& CoreServiceImpl::getPrivateNodeHandle() {
|
||||
return privateNodeHandle;
|
||||
}
|
||||
|
||||
|
||||
void CoreServiceImpl::requestShutdown() {
|
||||
ROS_INFO("Received shutdown request");
|
||||
ros::shutdown();
|
||||
}
|
||||
|
||||
|
||||
} // namespace core
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* hos_core_service_private.h
|
||||
*
|
||||
* Created on: 05.04.2015
|
||||
* Author: matzman
|
||||
*/
|
||||
|
||||
#ifndef SRC_CORE_SERVICEIMPL_H_
|
||||
#define SRC_CORE_SERVICEIMPL_H_
|
||||
|
||||
#include <hos/cosgi/service/core/CoreService.h>
|
||||
#include <hos/cosgi/service/Implementation.h>
|
||||
|
||||
|
||||
// Service Namespace
|
||||
namespace hos {
|
||||
namespace cosgi{
|
||||
namespace service {
|
||||
namespace core {
|
||||
|
||||
|
||||
class CoreServiceImpl;
|
||||
class CoreServiceImpl : public virtual CoreService, public virtual implementation::Service<CoreServiceImpl>, public virtual implementation::Observable<CoreServiceEvent> {
|
||||
private:
|
||||
ros::NodeHandle publicNodeHandle;
|
||||
ros::NodeHandle privateNodeHandle;
|
||||
|
||||
public:
|
||||
CoreServiceImpl(ros::NodeHandle& publicNodeHandle, ros::NodeHandle& privateNodeHandle);
|
||||
|
||||
virtual ros::NodeHandle& getPublicNodeHandle();
|
||||
virtual ros::NodeHandle& getPrivateNodeHandle();
|
||||
virtual void requestShutdown();
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
} // namespace service
|
||||
} // namespace cosgi
|
||||
} // namespace hos
|
||||
|
||||
|
||||
#endif /* SRC_CORE_SERVICEIMPL_H_ */
|
||||
@@ -0,0 +1,232 @@
|
||||
|
||||
#include <cstdlib>
|
||||
#include "ros/ros.h"
|
||||
#include <apr_general.h>
|
||||
#include <apr_strings.h>
|
||||
|
||||
#include "hos/cosgi/service/core/core_serviceimpl.h"
|
||||
|
||||
extern "C" { // celix does not provide C++ ready headers
|
||||
#include "celix/framework.h"
|
||||
#include "celix/linked_list_iterator.h"
|
||||
}
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <boost/format.hpp>
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
using namespace hos::cosgi::service::core;
|
||||
|
||||
|
||||
std::function<void(int)> signalHandler;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
bool apr_initialized = false;
|
||||
apr_pool_t* memoryPool = nullptr;
|
||||
framework_pt framework = nullptr;
|
||||
bundle_pt fwBundle = nullptr;
|
||||
properties_pt properties = nullptr;
|
||||
|
||||
int loop_frequency = 100;
|
||||
std::string autostart_bundles;
|
||||
|
||||
try {
|
||||
// Initialize ROS
|
||||
ros::init(argc, argv, "hos_osgi_launcher", ros::init_options::AnonymousName | ros::init_options::NoSigintHandler);
|
||||
// Create public node-handle
|
||||
ros::NodeHandle rosPublicNodeHandle;
|
||||
// Create private node-handle
|
||||
ros::NodeHandle rosPrivateNodeHandle("~");
|
||||
if (!ros::ok()) {
|
||||
throw std::runtime_error(boost::format("Could not initialize ROS.").str());
|
||||
}
|
||||
ROS_INFO("ROS initialized");
|
||||
|
||||
// Retrieve ROS parameter
|
||||
rosPrivateNodeHandle.getParam("loop_frequency", loop_frequency);
|
||||
rosPrivateNodeHandle.getParam("autostart_bundles", autostart_bundles);
|
||||
|
||||
// Initialize APR and APR memory pool
|
||||
apr_status_t astatus = apr_initialize();
|
||||
if (astatus != APR_SUCCESS) {
|
||||
throw std::runtime_error((boost::format("Could not initialize APR (%1%).") % astatus).str());
|
||||
}
|
||||
apr_initialized = true;
|
||||
astatus = apr_pool_create(&memoryPool, nullptr);
|
||||
if (astatus != APR_SUCCESS) {
|
||||
memoryPool = nullptr;
|
||||
throw std::runtime_error((boost::format("Could not create APR memory pool (%1%).") % astatus).str());
|
||||
}
|
||||
ROS_INFO("APR initialized");
|
||||
|
||||
// Create celix properties
|
||||
properties = properties_create();
|
||||
|
||||
//properties = properties_load((char*)"config.properties");
|
||||
if (properties == nullptr) {
|
||||
throw std::runtime_error(boost::format("Could not create celix properties.").str());
|
||||
}
|
||||
properties_store(properties, (char*)"config.properties", nullptr);
|
||||
|
||||
// Create and initialize celix framework
|
||||
celix_status_t cstatus = framework_create(&framework, memoryPool, properties);
|
||||
if (cstatus != CELIX_SUCCESS) {
|
||||
framework = nullptr;
|
||||
throw std::runtime_error((boost::format("Could not create celix framework (%1%).") % cstatus).str());
|
||||
}
|
||||
cstatus = fw_init(framework);
|
||||
if (cstatus != CELIX_SUCCESS) {
|
||||
framework = nullptr;
|
||||
throw std::runtime_error((boost::format("Could not initialize celix framework (%1%).") % cstatus).str());
|
||||
}
|
||||
ROS_INFO("Celix initialized");
|
||||
|
||||
// Get and start framework bundle
|
||||
cstatus = framework_getFrameworkBundle(framework, &fwBundle);
|
||||
if (cstatus != CELIX_SUCCESS) {
|
||||
fwBundle = nullptr;
|
||||
throw std::runtime_error((boost::format("Could not find framework bundle (%1%).") % cstatus).str());
|
||||
}
|
||||
cstatus = bundle_start(fwBundle);
|
||||
if (cstatus != CELIX_SUCCESS) {
|
||||
fwBundle = nullptr;
|
||||
throw std::runtime_error((boost::format("Could not start framework bundle (%1%).") % cstatus).str());
|
||||
}
|
||||
ROS_INFO("Framework bundle started");
|
||||
|
||||
// Create bundle context
|
||||
bundle_context_pt context = nullptr;
|
||||
bundle_getContext(fwBundle, &context);
|
||||
|
||||
// Create and register hos-core-service
|
||||
CoreServiceImpl hosCoreService(rosPublicNodeHandle, rosPrivateNodeHandle);
|
||||
service_registration_pt reg = nullptr;
|
||||
bundleContext_registerService(context, (char*)CoreService::SERVICE_NAME, static_cast<CoreService*>(&hosCoreService), nullptr, ®);
|
||||
ROS_INFO("HOS core service registered");
|
||||
|
||||
|
||||
// Auto-start bundles
|
||||
// #### Copied from celix launcher ####
|
||||
apr_pool_t *pool = nullptr;
|
||||
cstatus = apr_pool_create(&pool, memoryPool);
|
||||
if (cstatus == APR_SUCCESS) {
|
||||
ROS_INFO("Starting auto-start bundles");
|
||||
char* autoStart;
|
||||
// ROS param overrides config file
|
||||
if (!autostart_bundles.empty()) {
|
||||
autoStart = (char*)autostart_bundles.c_str();
|
||||
} else {
|
||||
autoStart = properties_get(properties, (char*)"cosgi.auto.start.1");
|
||||
}
|
||||
ROS_INFO_STREAM("Autostart bundles: " << autoStart);
|
||||
char delims[] = " ";
|
||||
char *result = nullptr;
|
||||
linked_list_pt bundles;
|
||||
array_list_pt installed = nullptr;
|
||||
bundle_pt bundle = nullptr;
|
||||
bundle_context_pt context = nullptr;
|
||||
linked_list_iterator_pt iter = nullptr;
|
||||
unsigned int i;
|
||||
|
||||
if (linkedList_create(&bundles) != CELIX_SUCCESS) {
|
||||
ROS_ERROR("Could not create linked list.");
|
||||
exit(1);
|
||||
}
|
||||
result = strtok(autoStart, delims);
|
||||
while (result != nullptr) {
|
||||
char * location = apr_pstrdup(memoryPool, result);
|
||||
linkedList_addElement(bundles, location);
|
||||
result = strtok(nullptr, delims);
|
||||
}
|
||||
// First install all bundles
|
||||
// Afterwards start them
|
||||
arrayList_create(&installed);
|
||||
framework_getFrameworkBundle(framework, &bundle);
|
||||
bundle_getContext(bundle, &context);
|
||||
iter = linkedListIterator_create(bundles, 0);
|
||||
while (linkedListIterator_hasNext(iter)) {
|
||||
bundle_pt current = nullptr;
|
||||
char *location = (char *) linkedListIterator_next(iter);
|
||||
if (bundleContext_installBundle(context, location, ¤t) == CELIX_SUCCESS) {
|
||||
// Only add bundle if it is installed correctly
|
||||
arrayList_add(installed, current);
|
||||
ROS_INFO("Installed bundle %p from %s", current, location);
|
||||
} else {
|
||||
ROS_ERROR("Could not install bundle from %s", location);
|
||||
}
|
||||
linkedListIterator_remove(iter);
|
||||
}
|
||||
linkedListIterator_destroy(iter);
|
||||
|
||||
for (i = 0; i < arrayList_size(installed); i++) {
|
||||
bundle_pt bundle = (bundle_pt) arrayList_get(installed, i);
|
||||
if (bundle_startWithOptions(bundle, 0) == CELIX_SUCCESS) {
|
||||
ROS_INFO("Started bundle %p", bundle);
|
||||
} else {
|
||||
ROS_ERROR("Could not start bundle %p", bundle);
|
||||
}
|
||||
}
|
||||
|
||||
arrayList_destroy(installed);
|
||||
apr_pool_destroy(pool);
|
||||
// #### End Copied from celix launcher ####
|
||||
} else {
|
||||
throw std::runtime_error((boost::format("Could not create temporary APR memory pool.") % cstatus).str());
|
||||
}
|
||||
|
||||
// Send startup finished event
|
||||
{
|
||||
StartupFinishedEvent event;
|
||||
hosCoreService.notifyObservers(&event);
|
||||
}
|
||||
|
||||
// main loop
|
||||
ROS_INFO("Entering main loop");
|
||||
signalHandler = [&](int signum) {
|
||||
hosCoreService.requestShutdown();
|
||||
};
|
||||
signal(SIGINT, [](int signum) { signalHandler(signum); });
|
||||
ros::Rate loop_rate(loop_frequency);
|
||||
while (ros::ok()) {
|
||||
ros::spinOnce();
|
||||
loop_rate.sleep();
|
||||
}
|
||||
ROS_INFO("Exiting main loop");
|
||||
|
||||
} catch (std::exception &ex) {
|
||||
std::stringstream ss;
|
||||
ss << "ERROR: " << ex.what() << std::endl;
|
||||
ROS_ERROR_STREAM(ss.str());
|
||||
std::cerr << ss.str();
|
||||
}
|
||||
|
||||
// Deinitialize celix frameork
|
||||
if (fwBundle != nullptr) {
|
||||
bundle_stop(fwBundle);
|
||||
framework_waitForStop(framework);
|
||||
}
|
||||
if (framework != nullptr) {
|
||||
framework_destroy(framework);
|
||||
}
|
||||
if (properties != nullptr) {
|
||||
properties_destroy(properties);
|
||||
}
|
||||
ROS_INFO("Celix Framework is shut down");
|
||||
|
||||
// Deinitialize APR
|
||||
if (memoryPool != nullptr) {
|
||||
apr_pool_destroy(memoryPool);
|
||||
}
|
||||
if (apr_initialized) {
|
||||
apr_terminate();
|
||||
}
|
||||
ROS_INFO("APR Framework is shut down");
|
||||
|
||||
ROS_INFO("Exiting ...");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user