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 addDigitalInInterface( const std::string& name, const std::string& devicename)
00495 {
00496 if ( this->isRunning() )
00497 return false;
00498
00499 DigitalInInterface* input = DigitalInInterface::nameserver.getObject(devicename);
00500 if ( !input ) {
00501 log(Error) << "DigitalInput: "<< devicename <<" not found."<<endlog();
00502 return false;
00503 }
00504
00505 std::stringstream name_number;
00506 for(unsigned int i=0; i != input->nbOfInputs(); ++i) {
00507 name_number << name;
00508 name_number << i;
00509 if ( d_in.count(name_number.str()) )
00510 delete d_in.find(name_number.str())->second;
00511 d_in[name_number.str()] = new DigitalInput( input, i );
00512 name_number.str("");
00513 }
00514
00515 return true;
00516 }
00517
00525 bool addDigitalOutInterface( const std::string& name, const std::string& devicename)
00526 {
00527 if ( this->isRunning() )
00528 return false;
00529
00530 DigitalOutInterface* output = DigitalOutInterface::nameserver.getObject(devicename);
00531 if ( !output ) {
00532 log(Error) << "DigitalOut: "<< devicename <<" not found."<<endlog();
00533 return false;
00534 }
00535
00536 std::stringstream name_number;
00537 for(unsigned int i=0; i != output->nbOfOutputs(); ++i) {
00538 name_number << name;
00539 name_number << i;
00540 if ( d_out.count(name_number.str()) )
00541 delete d_out.find(name_number.str())->second;
00542 d_out[name_number.str()] = new DigitalOutput( output, i );
00543 name_number.str("");
00544 }
00545
00546 return true;
00547 }
00548
00555 bool removeDigitalInInterface( const std::string& name)
00556 {
00557 if ( this->isRunning() )
00558 return false;
00559
00560 std::stringstream name_number;
00561 for(int i=0; i != 128; ++i) {
00562 name_number << name;
00563 name_number << i;
00564 if ( d_in.count(name_number.str()) )
00565 delete d_in.find(name_number.str())->second;
00566 d_in.erase(name_number.str());
00567 name_number.str("");
00568 }
00569
00570 return true;
00571 }
00572
00579 bool removeDigitalOutInterface( const std::string& name)
00580 {
00581 if ( this->isRunning() )
00582 return false;
00583
00584 std::stringstream name_number;
00585 for(int i=0; i != 128; ++i) {
00586 name_number << name;
00587 name_number << i;
00588 if ( d_out.count(name_number.str()) )
00589 delete d_out.find(name_number.str())->second;
00590 d_out.erase(name_number.str());
00591 name_number.str("");
00592 }
00593
00594 return true;
00595 }
00596
00606 bool addDigitalOutput( const std::string& name, const std::string& devicename, int channel, bool invert=false)
00607 {
00608 if ( d_out.count(name) != 0 || this->isRunning() )
00609 return false;
00610
00611 DigitalOutInterface* output = DigitalOutInterface::nameserver.getObject(devicename);
00612 if ( !output ) {
00613 log(Error) << "DigitalOut: "<< devicename <<" not found."<<endlog();
00614 return false;
00615 }
00616
00617 d_out[name] = new DigitalOutput( output, channel, invert );
00618
00619 return true;
00620 }
00621
00628 bool removeDigitalOutput( const std::string& name )
00629 {
00630 if ( d_out.count(name) != 1 || this->isRunning() )
00631 return false;
00632
00633 delete d_out[name];
00634
00635 d_out.erase(name);
00636 return true;
00637 }
00638
00644 void switchOn( const std::string& name )
00645 {
00646 DOutMap::iterator it = d_out.find(name);
00647 if ( it == d_out.end() )
00648 return;
00649 it->second->switchOn();
00650 }
00651
00659 bool isOn( const std::string& name ) const
00660 {
00661 DOutMap::const_iterator it = d_out.find(name);
00662 if ( it != d_out.end() )
00663 return it->second->isOn();
00664 DInMap::const_iterator it2 = d_in.find(name);
00665 if ( it2 != d_in.end() )
00666 return it2->second->isOn();
00667 return false;
00668 }
00669
00675 void switchOff( const std::string& name )
00676 {
00677 DOutMap::const_iterator it = d_out.find(name);
00678 if ( it == d_out.end() )
00679 return;
00680 it->second->switchOff();
00681 }
00682
00690 double value(const std::string& name) const
00691 {
00692 AInMap::const_iterator it = a_in.find(name);
00693 if ( it != a_in.end() )
00694 return boost::get<0>( it->second )->value();
00695 AOutMap::const_iterator it2 = a_out.find(name);
00696 if ( it2 != a_out.end() )
00697 return it2->second.first->value();
00698 return 0;
00699 }
00700
00708 int rawValue(const std::string& name) const
00709 {
00710 AInMap::const_iterator it = a_in.find(name);
00711 if ( it != a_in.end() )
00712 return boost::get<0>( it->second )->rawValue();
00713
00714 AOutMap::const_iterator it2 = a_out.find(name);
00715 if ( it2 != a_out.end() )
00716 return it2->second.first->rawValue();
00717 return 0;
00718 }
00719
00724 int getInputChannels() const
00725 {
00726 return chan_meas.size();
00727 }
00728
00733 int getOutputChannels() const
00734 {
00735 return chan_out.size();
00736 }
00741 protected:
00742
00743 void createAPI();
00744
00745 Property<int> max_inchannels;
00746 Property<int> max_outchannels;
00750 std::vector< AnalogInput* > inchannels;
00751 std::vector< AnalogOutput* > outchannels;
00752
00753 std::vector<double> chan_meas;
00754 std::vector<double> chan_out;
00755 WriteDataPort< std::vector<double> > inChannelPort;
00756 ReadDataPort< std::vector<double> > outChannelPort;
00757
00761 typedef std::map<std::string, DigitalInput* > DInMap;
00762 DInMap d_in;
00763 typedef std::map<std::string, DigitalOutput* > DOutMap;
00764 DOutMap d_out;
00765
00769 typedef
00770 std::map<std::string,
00771 boost::tuple< AnalogInput*,
00772 WriteDataPort<unsigned int>*,
00773 WriteDataPort<double>* > > AInMap;
00774 AInMap a_in;
00775 typedef std::map<std::string, std::pair<AnalogOutput*, ReadDataPort<double>* > > AOutMap;
00776 AOutMap a_out;
00777
00778 typedef
00779 std::map<std::string,
00780 boost::tuple< AnalogInInterface*,
00781 WriteDataPort<std::vector<double> >* > > AInInterfaceMap;
00782 AInInterfaceMap ai_interface;
00783 typedef std::map<std::string, std::pair<AnalogOutInterface*, ReadDataPort<std::vector<double> >* > > AOutInterfaceMap;
00784 AOutInterfaceMap ao_interface;
00785 std::vector<double> workvect;
00786
00787 int usingInChannels;
00788 int usingOutChannels;
00789
00793 void write_a_in_to_do( const AInMap::value_type& dd )
00794 {
00795
00796 boost::get<1>(dd.second)->Set( boost::get<0>(dd.second)->rawValue() );
00797 boost::get<2>(dd.second)->Set( boost::get<0>(dd.second)->value() );
00798 }
00799
00803 void write_to_aout( const AOutMap::value_type& dd )
00804 {
00805 dd.second.first->value( dd.second.second->Get() );
00806 }
00807
00811 void read_ai( const AInInterfaceMap::value_type& dd )
00812 {
00813
00814 workvect.resize( boost::get<0>(dd.second)->nbOfChannels() );
00815 for(unsigned int i=0; i != workvect.size(); ++i) {
00816 AnalogInput ain( boost::get<0>(dd.second), i);
00817 workvect[i] = ain.value();
00818 }
00819 boost::get<1>(dd.second)->Set( workvect );
00820 }
00821
00822 void write_ao( const AOutInterfaceMap::value_type& dd )
00823 {
00824 workvect.resize( dd.second.first->nbOfChannels() );
00825 dd.second.second->Get( workvect );
00826 for(unsigned int i=0; i != workvect.size(); ++i) {
00827 AnalogOutput aout( dd.second.first, i);
00828 aout.value( workvect[i]);
00829 }
00830 }
00831
00832 };
00833
00834 }
00835
00836 #endif
00837