00001 #ifndef ORO_IO_COMPONENT_HPP
00002 #define ORO_IO_COMPONENT_HPP
00003
00004 #include <rtt/dev/AnalogInput.hpp>
00005 #include <rtt/dev/DigitalInput.hpp>
00006 #include <rtt/dev/AnalogOutput.hpp>
00007 #include <rtt/dev/DigitalOutput.hpp>
00008
00009 #include <map>
00010 #include <utility>
00011 #include <vector>
00012 #include <string>
00013 #include <sstream>
00014 #include <boost/tuple/tuple.hpp>
00015 #include <rtt/Logger.hpp>
00016 #include <rtt/TaskContext.hpp>
00017 #include <rtt/DataPort.hpp>
00018 #include <rtt/Property.hpp>
00019 #include <rtt/RTT.hpp>
00020
00021 #include <ocl/OCL.hpp>
00022
00023 namespace OCL
00024 {
00025
00047 class IOComponent
00048 : public TaskContext
00049 {
00050 public:
00054 IOComponent(const std::string& name="IOComponent")
00055 : TaskContext( name ),
00056 max_inchannels("MaximumInChannels","The maximum number of virtual analog input channels", 32),
00057 max_outchannels("MaximumOutChannels","The maximum number of virtual analog output channels", 32),
00058 inChannelPort( "InputValues", std::vector<double>( max_outchannels.get(), 0.0) ),
00059 outChannelPort("OutputValues"),
00060 workvect(32),
00061 usingInChannels(0),
00062 usingOutChannels(0)
00063 {
00064 this->configure();
00065
00066 this->ports()->addPort( &inChannelPort,
00067 "A DataPort containing the values read by this Component from hardware." );
00068 this->ports()->addPort( &outChannelPort,
00069 "A DataPort containing the values which this Component will write to hardware." );
00070
00071 this->properties()->addProperty( &max_outchannels );
00072 this->properties()->addProperty( &max_inchannels );
00073
00074 this->createAPI();
00075 }
00076
00077 virtual bool configureHook()
00078 {
00079 if ( max_inchannels.get() > max_outchannels.get() )
00080 workvect.resize( max_inchannels.get() );
00081 else
00082 workvect.resize( max_outchannels.get() );
00083
00084 inchannels.resize(max_inchannels.get(), 0 );
00085 outchannels.resize(max_outchannels.get(), 0 );
00086 chan_meas.resize(max_inchannels.get(), 0.0);
00087 chan_out.resize(max_outchannels.get(), 0);
00088
00089 return true;
00090 }
00091
00095 virtual void updateHook()
00096 {
00097
00098
00099
00100 std::for_each( a_in.begin(), a_in.end(), bind( &IOComponent::write_a_in_to_do, this, _1 ) );
00101 std::for_each( ai_interface.begin(), ai_interface.end(), bind( &IOComponent::read_ai, this, _1 ) );
00102
00103 if (usingInChannels) {
00104 for (unsigned int i=0; i < inchannels.size(); ++i)
00105 chan_meas[i] = inchannels[i] ? inchannels[i]->value() : 0 ;
00106
00107
00108 inChannelPort.Set( chan_meas );
00109 }
00110
00111
00112
00113
00114 std::for_each( a_out.begin(), a_out.end(), bind( &IOComponent::write_to_aout, this, _1 ) );
00115 std::for_each( ao_interface.begin(), ao_interface.end(), bind( &IOComponent::write_ao, this, _1 ) );
00116
00117
00118 if ( usingOutChannels ) {
00119 outChannelPort.Get( chan_out );
00120
00121
00122 for (unsigned int i=0; i < outchannels.size(); ++i)
00123 if ( outchannels[i] )
00124 outchannels[i]->value( chan_out[i] );
00125 }
00126 }
00127
00137 bool addAnalogInInterface( const std::string& Portname, const std::string& devicename)
00138 {
00139 Logger::In("addAnalogInInterface");
00140 AnalogInInterface* input = AnalogInInterface::nameserver.getObject(devicename);
00141 if ( !input ) {
00142 log(Error) << "AnalogIn: "<< devicename <<" not found."<<endlog();
00143 return false;
00144 }
00145 if ( ai_interface.count(Portname) != 0 ){
00146 log(Error) << "Portname: "<< Portname <<" already in use."<<endlog();
00147 return false;
00148 }
00149 if ( isRunning() ) {
00150 log(Error) << "Can not add interfaces when running."<<endlog();
00151 return false;
00152 }
00153
00154 ai_interface[Portname] =
00155 boost::make_tuple(input, new WriteDataPort<std::vector<double> >(Portname, std::vector<double>(input->nbOfChannels())) );
00156
00157 this->ports()->addPort( boost::get<1>(ai_interface[Portname]), "Analog Input value.");
00158
00159 this->exportPorts();
00160 return true;
00161 }
00162
00171 bool removeAnalogInInterface(const std::string& Portname)
00172 {
00173 Logger::In("removeAnalogInInterface");
00174 if ( ai_interface.count(Portname) == 0 ){
00175 log(Error) << "Portname: "<< Portname <<" unknown."<<endlog();
00176 return false;
00177 }
00178 if ( isRunning() ) {
00179 log(Error) << "Can not remove interfaces when running."<<endlog();
00180 return false;
00181 }
00182
00183 delete boost::get<1>(ai_interface[Portname]);
00184 this->removeObject( Portname );
00185 ai_interface.erase(Portname);
00186 return true;
00187 }
00188
00201 bool addAnalogInput( const std::string& Portname, const std::string& devicename, int channel)
00202 {
00203 if ( a_in.count(Portname) != 0 || this->isRunning() )
00204 return false;
00205
00206 AnalogInInterface* input = AnalogInInterface::nameserver.getObject(devicename);
00207 if ( !input ) {
00208 log(Error) << "AnalogIn: "<< devicename <<" not found."<<endlog();
00209 return false;
00210 }
00211
00212 a_in[Portname] =
00213 boost::make_tuple( new AnalogInput( input, channel ),
00214 new WriteDataPort<unsigned int>(Portname+"_raw", 0),
00215 new WriteDataPort<double>(Portname, 0.0) );
00216
00217 this->ports()->addPort( boost::get<1>(a_in[Portname]), "Analog Input raw value.");
00218 this->ports()->addPort( boost::get<2>(a_in[Portname]), "Analog Input value.");
00219
00220 this->exportPorts();
00221 return true;
00222 }
00223
00227 bool removeAnalogInput( const std::string& Portname )
00228 {
00229 if ( a_in.count(Portname) != 1 || this->isRunning() )
00230 return false;
00231
00232 using namespace boost;
00233 tuple<AnalogInput*, WriteDataPort<unsigned int>*, WriteDataPort<double>* > res = a_in[Portname];
00234 this->ports()->removePort( Portname );
00235 this->ports()->removePort( Portname );
00236 a_in.erase(Portname);
00237
00238 delete get<0>(res);
00239 delete get<1>(res);
00240 delete get<2>(res);
00241
00242 this->removeObject(Portname);
00243 return true;
00244 }
00245
00256 bool addInputChannel(int virt_channel, const std::string& devicename, int channel )
00257 {
00258 if ( inchannels[virt_channel] != 0 || this->isRunning() )
00259 return false;
00260
00261 AnalogInInterface* input = AnalogInInterface::nameserver.getObject(devicename);
00262 if ( !input ) {
00263 log(Error) << "AnalogIn: "<< devicename <<" not found."<<endlog();
00264 return false;
00265 }
00266 ++usingInChannels;
00267
00268 inchannels[virt_channel] = new AnalogInput( input, channel ) ;
00269
00270 return true;
00271 }
00272
00276 bool removeInputChannel( int virt_channel )
00277 {
00278 if ( this->isRunning() )
00279 return false;
00280
00281 --usingInChannels;
00282
00283 inchannels[virt_channel] = 0;
00284
00285 return true;
00286 }
00287
00299 bool addDigitalInput( const std::string& name, const std::string& devicename, int channel, bool invert=false)
00300 {
00301 if ( d_in.count(name) != 0 || this->isRunning() )
00302 return false;
00303
00304 DigitalInInterface* input = DigitalInInterface::nameserver.getObject(devicename);
00305 if ( !input ) {
00306 log(Error) << "DigitalIn: "<< devicename <<" not found."<<endlog();
00307 return false;
00308 }
00309
00310 d_in[name] = new DigitalInput( input, channel, invert );
00311
00312 return true;
00313 }
00314
00318 bool removeDigitalInput( const std::string& name )
00319 {
00320 if ( d_in.count(name) != 1 || this->isRunning() )
00321 return false;
00322
00323 DigitalInput* res = d_in[name];
00324
00325 delete res;
00326
00327 d_in.erase(name);
00328 return true;
00329 }
00330
00340 bool addAnalogOutInterface( const std::string& Portname, const std::string& devicename)
00341 {
00342 Logger::In("addAnalogOutInterface");
00343 AnalogOutInterface* output = AnalogOutInterface::nameserver.getObject(devicename);
00344 if ( !output ) {
00345 log(Error) << "AnalogOut: "<< devicename <<" not found."<<endlog();
00346 return false;
00347 }
00348 if ( ao_interface.count(Portname) != 0 ){
00349 log(Error) << "Portname: "<< Portname <<" already in use."<<endlog();
00350 return false;
00351 }
00352 if ( isRunning() ) {
00353 log(Error) << "Can not add interfaces when running."<<endlog();
00354 return false;
00355 }
00356
00357 ao_interface[Portname] =
00358 std::make_pair(output, new ReadDataPort<std::vector<double> >(Portname) );
00359
00360 this->ports()->addPort( ao_interface[Portname].second, "Analog Output value.");
00361
00362 this->exportPorts();
00363 return true;
00364 }
00365
00374 bool removeAnalogOutInterface(const std::string& Portname)
00375 {
00376 Logger::In("removeAnalogOutInterface");
00377 if ( ao_interface.count(Portname) == 0 ){
00378 log(Error) << "Portname: "<< Portname <<" unknown."<<endlog();
00379 return false;
00380 }
00381 if ( isRunning() ) {
00382 log(Error) << "Can not remove interfaces when running."<<endlog();
00383 return false;
00384 }
00385
00386 delete ao_interface[Portname].second;
00387 this->removeObject( Portname );
00388 ao_interface.erase(Portname);
00389 return true;
00390 }
00391
00401 bool addAnalogOutput( const std::string& portname, const std::string& devicename, int channel )
00402 {
00403 if ( a_out.count(portname) != 0 || this->isRunning() )
00404 return false;
00405
00406 AnalogOutInterface* output = AnalogOutInterface::nameserver.getObject(devicename);
00407 if ( !output ) {
00408 log(Error) << "AnalogOut: "<< devicename <<" not found."<<endlog();
00409 return false;
00410 }
00411
00412 a_out[portname] = std::make_pair( new AnalogOutput( output, channel ), new ReadDataPort<double>(portname) );
00413
00414 this->ports()->addPort( a_out[portname].second, "Analog Output value." );
00415
00416 this->exportPorts();
00417 return true;
00418 }
00419
00427 bool removeAnalogOutput( const std::string& name )
00428 {
00429 if ( a_out.count(name) != 1 || this->isRunning() )
00430 return false;
00431
00432 this->ports()->removePort( name );
00433
00434 delete a_out[name].first;
00435 delete a_out[name].second;
00436
00437 a_out.erase(name);
00438 this->removeObject(name);
00439 return true;
00440 }
00441
00454 bool addOutputChannel( int virt_channel, const std::string& devicename, int channel )
00455 {
00456 if ( outchannels[virt_channel] != 0 || this->isRunning() )
00457 return false;
00458
00459 AnalogOutInterface* output = AnalogOutInterface::nameserver.getObject(devicename);
00460 if ( !output ) {
00461 log(Error) << "AnalogOut: "<< devicename <<" not found."<<endlog();
00462 return false;
00463 }
00464
00465
00466 outchannels[virt_channel] = new AnalogOutput( output, channel );
00467 ++usingOutChannels;
00468 return true;
00469 }
00470
00477 bool removeOutputChannel( int virt_channel )
00478 {
00479 if ( outchannels[virt_channel] == 0 || this->isRunning() )
00480 return false;
00481
00482 delete outchannels[virt_channel];
00483 --usingOutChannels;
00484 return true;
00485 }
00486
00494 bool addDigitalOutInterface( const std::string& name, const std::string& devicename)
00495 {
00496 if ( this->isRunning() )
00497 return false;
00498
00499 DigitalOutInterface* output = DigitalOutInterface::nameserver.getObject(devicename);
00500 if ( !output ) {
00501 log(Error) << "DigitalOut: "<< devicename <<" not found."<<endlog();
00502 return false;
00503 }
00504
00505 std::stringstream name_number;
00506 for(unsigned int i=0; i != output->nbOfOutputs(); ++i) {
00507 name_number.str( name );
00508 name_number << i;
00509 if ( d_out.count(name_number.str()) )
00510 delete d_out.find(name_number.str())->second;
00511 d_out[name_number.str()] = new DigitalOutput( output, i );
00512 name_number.clear();
00513 }
00514
00515 return true;
00516 }
00517
00524 bool removeDigitalOutInterface( const std::string& name)
00525 {
00526 if ( this->isRunning() )
00527 return false;
00528
00529 std::stringstream name_number;
00530 for(int i=0; i != 128; ++i) {
00531 name_number.str( name );
00532 name_number << i;
00533 if ( d_out.count(name_number.str()) )
00534 delete d_out.find(name_number.str())->second;
00535 d_out.erase(name_number.str());
00536 name_number.clear();
00537 }
00538
00539 return true;
00540 }
00541
00551 bool addDigitalOutput( const std::string& name, const std::string& devicename, int channel, bool invert=false)
00552 {
00553 if ( d_out.count(name) != 0 || this->isRunning() )
00554 return false;
00555
00556 DigitalOutInterface* output = DigitalOutInterface::nameserver.getObject(devicename);
00557 if ( !output ) {
00558 log(Error) << "DigitalOut: "<< devicename <<" not found."<<endlog();
00559 return false;
00560 }
00561
00562 d_out[name] = new DigitalOutput( output, channel, invert );
00563
00564 return true;
00565 }
00566
00573 bool removeDigitalOutput( const std::string& name )
00574 {
00575 if ( d_out.count(name) != 1 || this->isRunning() )
00576 return false;
00577
00578 delete d_out[name];
00579
00580 d_out.erase(name);
00581 return true;
00582 }
00583
00589 void switchOn( const std::string& name )
00590 {
00591 DOutMap::iterator it = d_out.find(name);
00592 if ( it == d_out.end() )
00593 return;
00594 it->second->switchOn();
00595 }
00596
00604 bool isOn( const std::string& name ) const
00605 {
00606 DOutMap::const_iterator it = d_out.find(name);
00607 if ( it != d_out.end() )
00608 return it->second->isOn();
00609 DInMap::const_iterator it2 = d_in.find(name);
00610 if ( it2 != d_in.end() )
00611 return it2->second->isOn();
00612 return false;
00613 }
00614
00620 void switchOff( const std::string& name )
00621 {
00622 DOutMap::const_iterator it = d_out.find(name);
00623 if ( it == d_out.end() )
00624 return;
00625 it->second->switchOff();
00626 }
00627
00635 double value(const std::string& name) const
00636 {
00637 AInMap::const_iterator it = a_in.find(name);
00638 if ( it != a_in.end() )
00639 return boost::get<0>( it->second )->value();
00640 AOutMap::const_iterator it2 = a_out.find(name);
00641 if ( it2 != a_out.end() )
00642 return it2->second.first->value();
00643 return 0;
00644 }
00645
00653 int rawValue(const std::string& name) const
00654 {
00655 AInMap::const_iterator it = a_in.find(name);
00656 if ( it != a_in.end() )
00657 return boost::get<0>( it->second )->rawValue();
00658
00659 AOutMap::const_iterator it2 = a_out.find(name);
00660 if ( it2 != a_out.end() )
00661 return it2->second.first->rawValue();
00662 return 0;
00663 }
00664
00669 int getInputChannels() const
00670 {
00671 return chan_meas.size();
00672 }
00673
00678 int getOutputChannels() const
00679 {
00680 return chan_out.size();
00681 }
00686 protected:
00687
00688 void createAPI();
00689
00690 Property<int> max_inchannels;
00691 Property<int> max_outchannels;
00695 std::vector< AnalogInput* > inchannels;
00696 std::vector< AnalogOutput* > outchannels;
00697
00698 std::vector<double> chan_meas;
00699 std::vector<double> chan_out;
00700 WriteDataPort< std::vector<double> > inChannelPort;
00701 ReadDataPort< std::vector<double> > outChannelPort;
00702
00706 typedef std::map<std::string, DigitalInput* > DInMap;
00707 DInMap d_in;
00708 typedef std::map<std::string, DigitalOutput* > DOutMap;
00709 DOutMap d_out;
00710
00714 typedef
00715 std::map<std::string,
00716 boost::tuple< AnalogInput*,
00717 WriteDataPort<unsigned int>*,
00718 WriteDataPort<double>* > > AInMap;
00719 AInMap a_in;
00720 typedef std::map<std::string, std::pair<AnalogOutput*, ReadDataPort<double>* > > AOutMap;
00721 AOutMap a_out;
00722
00723 typedef
00724 std::map<std::string,
00725 boost::tuple< AnalogInInterface*,
00726 WriteDataPort<std::vector<double> >* > > AInInterfaceMap;
00727 AInInterfaceMap ai_interface;
00728 typedef std::map<std::string, std::pair<AnalogOutInterface*, ReadDataPort<std::vector<double> >* > > AOutInterfaceMap;
00729 AOutInterfaceMap ao_interface;
00730 std::vector<double> workvect;
00731
00732 int usingInChannels;
00733 int usingOutChannels;
00734
00738 void write_a_in_to_do( const AInMap::value_type& dd )
00739 {
00740
00741 boost::get<1>(dd.second)->Set( boost::get<0>(dd.second)->rawValue() );
00742 boost::get<2>(dd.second)->Set( boost::get<0>(dd.second)->value() );
00743 }
00744
00748 void write_to_aout( const AOutMap::value_type& dd )
00749 {
00750 dd.second.first->value( dd.second.second->Get() );
00751 }
00752
00756 void read_ai( const AInInterfaceMap::value_type& dd )
00757 {
00758
00759 workvect.resize( boost::get<0>(dd.second)->nbOfChannels() );
00760 for(unsigned int i=0; i != workvect.size(); ++i) {
00761 AnalogInput ain( boost::get<0>(dd.second), i);
00762 workvect[i] = ain.value();
00763 }
00764 boost::get<1>(dd.second)->Set( workvect );
00765 }
00766
00767 void write_ao( const AOutInterfaceMap::value_type& dd )
00768 {
00769 workvect.resize( dd.second.first->nbOfChannels() );
00770 dd.second.second->Get( workvect );
00771 for(unsigned int i=0; i != workvect.size(); ++i) {
00772 AnalogOutput aout( dd.second.first, i);
00773 aout.value( workvect[i]);
00774 }
00775 }
00776
00777 };
00778
00779 }
00780
00781 #endif
00782