- Development
- European Robotics Forum 2011 Workshop on the Orocos Toolchain
- European Robotics Forum 2012: workshops
- Geometric relations semantics
- KDL wiki
- Kuka LBR user group
- Links of Orocos components
- OCL v1.x wiki
- RTT v1.x wiki
- Documentation suggestions
- Examples and Tutorials
- Frequently asked questions (FAQ)
- Installation
- RTT Dictionary
- RTT on MS Windows
- The 1st RTT Developers Workshop
- The Road to RTT 2.0
- Using Eclipse and Orocos
- Using Git and Orocos
- Toolchain v2.x
- Wiki for site admins
- iTaSC wiki
Part 2 Toolkit plugin
Table of Contents
This is a work in progress
This part creates a toolkit plugin making our types known to Orocos.
Files
See the attachments at the bottom of Developing plugins and toolkitsTo build
Everything needed for this part was built in Part 1.
To run
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).
Toolkit plugin
The toolkit plugin is defined in BoostToolkit.hpp.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)
Build system
Now the build system takes this .cpp file, and turns it into a dynamic library. We are going to examine the root CMakeLists.txt to see how to create this library, but for now, we will ignore the corba parts of that file.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)
Tests
There are two very simply test components that communicate each of our custom types between them. Tests are very important when developing plugins. Trying to debug a plugin within a complete system is a daunting challenge - do it in isolation first.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.
»
- Printer-friendly version
- Login or register to post comments