This is a work in progress
This part creates a toolkit plugin making our types known to Orocos.
Everything needed for this part was built in Part 1.
In a shell
cd /path/to/plugins/build ./combined
The combined tests uses an OCL taskbrowser to show two components: send and recv. Typing an "ls" or "ls Send" command, as in Part 1, you will get something like the following:
RW(C) boost_ptime ptime = 2009-Aug-09 16:14:19.724622 RW(C) boost_timeduration timeDuration = 00:00:00.200005
Note that Orocos now knows the correct types (eg boost_ptime) and can display each ports value. Issue multiple ls commands and you will see the values change. The ptime is simply the date and time at which the send component set the port value, and the duration is the time between port values being set on each iteration (ie this should approximately be the period of the send component).
namespace Examples { /// \remark these do not need to be in the same namespace as the plugin /// put the time onto the stream std::ostream& operator<<(std::ostream& os, const boost::posix_time::ptime& t); /// put the time onto duration the stream std::ostream& operator<<(std::ostream& os, const boost::posix_time::time_duration& d); /// get a time from the stream std::istream& operator>>(std::istream& is, boost::posix_time::ptime& t); /// get a time duration from the stream std::istream& operator>>(std::istream& is, boost::posix_time::time_duration& d);
class BoostPlugin : public RTT::ToolkitPlugin { public: virtual std::string getName(); virtual bool loadTypes(); virtual bool loadConstructors(); virtual bool loadOperators(); }; /// The singleton for the Toolkit. extern BoostPlugin BoostToolkit;
/// provide ptime type to RTT type system /// \remark the 'true' argument indicates that we supply stream operators struct BoostPtimeTypeInfo : public RTT::TemplateTypeInfo<boost::posix_time::ptime,true> { BoostPtimeTypeInfo(std::string name) : RTT::TemplateTypeInfo<boost::posix_time::ptime,true>(name) {}; bool decomposeTypeImpl(const boost::posix_time::ptime& img, RTT::PropertyBag& targetbag); bool composeTypeImpl(const RTT::PropertyBag& bag, boost::posix_time::ptime& img); }; /// provide time duration type to RTT type system /// \remark the 'true' argument indicates that we supply stream operators struct BoostTimeDurationTypeInfo : public RTT::TemplateTypeInfo<boost::posix_time::time_duration,true> { BoostTimeDurationTypeInfo(std::string name) : RTT::TemplateTypeInfo<boost::posix_time::time_duration,true>(name) {}; bool decomposeTypeImpl(const boost::posix_time::time_duration& img, RTT::PropertyBag& targetbag); bool composeTypeImpl(const RTT::PropertyBag& bag, boost::posix_time::time_duration& img); }; } // namespace Exampels
The toolkit plugin implementation is in the BoostToolkit.cpp file.
namespace Examples { using namespace RTT; using namespace RTT::detail; using namespace std; std::ostream& operator<<(std::ostream& os, const boost::posix_time::ptime& t) { os << boost::posix_time::to_simple_string(t); return os; } std::ostream& operator<<(std::ostream& os, const boost::posix_time::time_duration& d) { os << boost::posix_time::to_simple_string(d); return os; } std::istream& operator>>(std::istream& is, boost::posix_time::ptime& t) { is >> t; return is; } std::istream& operator>>(std::istream& is, boost::posix_time::time_duration& d) { is >> d; return is; }
BoostPlugin BoostToolkit; std::string BoostPlugin::getName() { return "Boost"; }
bool BoostPlugin::loadTypes() { TypeInfoRepository::shared_ptr ti = TypeInfoRepository::Instance(); /* each quoted name here (eg "boost_ptime") must _EXACTLY_ match that in the associated TypeInfo::composeTypeImpl() and TypeInfo::decomposeTypeImpl() functions (in this file), as well as the name registered in the associated Corba plugin's registerTransport() function (see corba/BoostCorbaToolkit.cpp) */ ti->addType( new BoostPtimeTypeInfo("boost_ptime") ); ti->addType( new BoostTimeDurationTypeInfo("boost_timeduration") ); return true; }
bool BoostPlugin::loadConstructors() { // no constructors for these particular types return true; } bool BoostPlugin::loadOperators() { // no operators for these particular types return true; }
bool BoostPtimeTypeInfo::decomposeTypeImpl(const boost::posix_time::ptime& source, PropertyBag& targetbag) { targetbag.setType("boost_ptime"); assert(0); return true; } bool BoostPtimeTypeInfo::composeTypeImpl(const PropertyBag& bag, boost::posix_time::ptime& result) { if ( "boost_ptime" == bag.getType() ) // ensure is correct type { // \todo assert(0); } return false; }
ORO_TOOLKIT_PLUGIN(Examples::BoostToolkit)
cmake_minimum_required(VERSION 2.6) # pick up additional cmake package files (eg FindXXX.cmake) from this directory list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/config")
find_package(Orocos-RTT 1.6.0 REQUIRED corba) find_package(Orocos-OCL 1.6.0 REQUIRED taskbrowser)
include(${CMAKE_SOURCE_DIR}/config/UseOrocos.cmake)
create_component(BoostToolkit-${OROCOS_TARGET} VERSION 1.0.0 BoostToolkit.cpp) TARGET_LINK_LIBRARIES(BoostToolkit-${OROCOS_TARGET} boost_date_time)
SUBDIRS(tests)
The send component regularly updates the current time on its ptime port, and the duration between ptime port updates on its timeDuration port.
class Send : public RTT::TaskContext { public: RTT::DataPort<boost::posix_time::ptime> ptime_port; RTT::DataPort<boost::posix_time::time_duration> timeDuration_port; public: Send(std::string name); virtual ~Send(); virtual bool startHook(); virtual void updateHook(); protected: boost::posix_time::ptime lastNow; };
The implementation is very simple, and will not be discussed in detail here.
#include "send.hpp" Send::Send(std::string name) : RTT::TaskContext(name), ptime_port("ptime"), timeDuration_port("timeDuration") { ports()->addPort(&ptime_port); ports()->addPort(&timeDuration_port); } Send::~Send() { } bool Send::startHook() { // just set last to now lastNow = boost::posix_time::microsec_clock::local_time(); return true; } void Send::updateHook() { boost::posix_time::ptime now; boost::posix_time::time_duration delta; // send the current time, and the duration since the last updateHook() now = boost::posix_time::microsec_clock::local_time(); delta = now - lastNow; ptime_port.Set(now); timeDuration_port.Set(delta); lastNow = now; }
The recv component has the same ports but does nothing. It is simply an empty receiver component, that allows us to view its ports within the deployer.
class Recv : public RTT::TaskContext { public: RTT::DataPort<boost::posix_time::ptime> ptime_port; RTT::DataPort<boost::posix_time::time_duration> timeDuration_port; public: Recv(std::string name); virtual ~Recv(); };
And the recv implementation.
#include "recv.hpp" Recv::Recv(std::string name) : RTT::TaskContext(name), ptime_port("ptime"), timeDuration_port("timeDuration") { ports()->addPort(&ptime_port); ports()->addPort(&timeDuration_port); } Recv::~Recv() { }
Now the combined test program just combines one of each test component directly within the same executable.
#include <rtt/RTT.hpp> #include <rtt/PeriodicActivity.hpp> #include <rtt/TaskContext.hpp> #include <rtt/os/main.h> #include <rtt/Ports.hpp> #include <ocl/TaskBrowser.hpp> #include "send.hpp" #include "recv.hpp" #include "../BoostToolkit.hpp" using namespace std; using namespace Orocos; int ORO_main(int argc, char* argv[]) { RTT::Toolkit::Import(Examples::BoostToolkit);
Recv recv("Recv"); PeriodicActivity recv_activity(ORO_SCHED_OTHER, 0, 0.1, recv.engine()); Send send("Send"); PeriodicActivity send_activity(ORO_SCHED_OTHER, 0, 0.2, send.engine()); if ( connectPeers( &send, &recv ) == false ) { log(Error) << "Could not connect peers !"<<endlog(); return -1; } if ( connectPorts( &send, &recv) == false ) { log(Error) << "Could not connect ports !"<<endlog(); return -1; }
send.configure(); recv.configure(); send_activity.start(); recv_activity.start(); TaskBrowser browser( &recv ); browser.setColorTheme( TaskBrowser::whitebg ); browser.loop();
send_activity.stop(); recv_activity.stop(); return 0; }
The differences between the combined and no-toolkit test programs will be covered in Part 2, but essentially amounts to not loading the toolkit.
Part 3 Transport plugin will build a transport plugin allowing Orocos to communicate these types across CORBA.