DataElementFactory.h
Go to the documentation of this file.
00001 
00006 #ifndef DATAELEMENTFACTORY_H_
00007 #define DATAELEMENTFACTORY_H_
00008 
00009 #include "robot_instance/RobonetDataElement.h"
00010 #include "robot_instance/StringUtilities.h"
00011 #include "robot_instance/XmlParserExceptions.h"
00012 #include "nasa_common_logging/Logger.h"
00013 #include "tinyxml.h"
00014 #include <string>
00015 #include <sstream>
00016 #include <utility>
00017 #include <vector>
00018 #include <stdexcept>
00019 #include "shared_memory_transport/smtclient.hpp"
00020 
00021 // Exceptions ----------------------------------------------------------
00022 
00025 class InvalidDataElementTypeException: public std::exception
00026 {
00027     virtual const char* what() const throw()
00028     {
00029         return "Cannot call DataElementFactory methods for DataElement type T when T does not equal RobonetDataElement.  A specialization of this method needs to be added to DataElementFactory.cpp to support your DataElement type.";
00030     }
00031 };
00032 
00035 template <typename T>
00036 class DataElementFactory
00037 {
00041     std::shared_ptr<SMT::SMTClient> smtclient;
00042 public:
00043     DataElementFactory(std::shared_ptr<SMT::SMTClient> client = nullptr):
00044         smtclient(client) {};
00045     virtual ~DataElementFactory() {};
00046 
00051     std::pair< std::string, boost::shared_ptr<T> > fromXml(const std::string& elementName, const std::string& robonetNode, const std::string& xml)
00052     {
00053         InvalidDataElementTypeException invalidDataElementTypeException;
00054         throw invalidDataElementTypeException;
00055     }
00056 
00061     std::pair< std::string, boost::shared_ptr<T> > stringsToDataElement(const std::string& name, const std::string& type, const std::string& direction, const std::string& channel, const std::string& node, const std::string& offset1, const std::string& offset2, const std::string& group, const std::string& style)
00062     {
00063         InvalidDataElementTypeException invalidDataElementTypeException;
00064         throw invalidDataElementTypeException;
00065     }
00066 };
00067 
00070 template <>
00071 class DataElementFactory<RobonetDataElement>
00072 {
00076     std::shared_ptr<SMT::SMTClient> smtclient;
00077 public:
00078     DataElementFactory(std::shared_ptr<SMT::SMTClient> client = nullptr):
00079         smtclient(client) {};
00080     virtual ~DataElementFactory() {};
00081 
00094     std::pair< std::string, RobonetDataElementPtr > fromXml(const std::string& elementName, const std::string& robonetNode, const std::string& xml)
00095     {
00096         TiXmlDocument file;
00097         file.Parse(xml.c_str());
00098 
00099         TiXmlHandle doc(&file);
00100 
00101         RobonetDataElementPtr dataElement;
00102         std::string str;
00103         std::string name;
00104         std::string type;
00105         std::string channel;
00106         std::string node;
00107         std::string offset1;
00108         std::string offset2;
00109         DataElement::ReadWrite direction = DataElement::Read;
00110         std::string group;
00111         RobonetDataElement::ElementStyle style = RobonetDataElement::Normal;
00112         // For SMT stuff later
00113         std::stringstream err;
00114         std::string smttype;
00115 
00116         TiXmlHandle elementHandle(doc.FirstChild("Element"));
00117 
00118         if (elementHandle.ToElement())
00119         {
00120             if (elementHandle.ToElement()->Attribute("id"))
00121             {
00122                 if (robonetNode.size() <= 0)
00123                 {
00124                     std::stringstream err;
00125                     err << "The robonetNode parameter is required.";
00126                     NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00127                     throw std::runtime_error(err.str());
00128                 }
00129 
00130                 if (elementName.size() > 0)
00131                 {
00132                     name = StringUtilities::makeFullyQualifiedRoboDynElement(elementName, elementHandle.ToElement()->Attribute("id"));
00133                 }
00134                 else
00135                 {
00136                     std::stringstream err;
00137                     err << "The elementName parameter is required.";
00138                     NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00139                     throw std::runtime_error(err.str());
00140                 }
00141             }
00142             else
00143             {
00144                 std::stringstream err;
00145                 err << "The attribute [id] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00146                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00147                 //throw runtime_error(err.str());
00148                 MissingXMLElementException missingXMLElementException;
00149                 throw missingXMLElementException;
00150             }
00151 
00152             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "Element name: " << name;
00153 
00154             if (elementHandle.ToElement()->Attribute("type"))
00155             {
00156                 type = elementHandle.ToElement()->Attribute("type");
00157             }
00158             else
00159             {
00160                 std::stringstream err;
00161                 err << "The attribute [type] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00162                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00163                 //throw runtime_error(err.str());
00164                 MissingXMLElementException missingXMLElementException;
00165                 throw missingXMLElementException;
00166             }
00167 
00168             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        type: " << type;
00169 
00170             if (elementHandle.ToElement()->Attribute("direction"))
00171             {
00172                 str = elementHandle.ToElement()->Attribute("direction");
00173 
00174                 if ( str.compare("Read") == 0 )
00175                 {
00176                     direction = DataElement::Read;
00177                 }
00178                 else if ( str.compare("Write") == 0 )
00179                 {
00180                     direction = DataElement::Write;
00181                 }
00182                 else
00183                 {
00184                     NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, "DataElementFactory::xmlToDataElement() - Direction must be either Read or Write, not '" + str + "'");
00185                     MissingXMLElementException missingXMLElementException;
00186                     throw missingXMLElementException;
00187                 }
00188             }
00189             else
00190             {
00191                 std::stringstream err;
00192                 err << "The attribute [direction] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00193                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00194                 //throw runtime_error(err.str());
00195                 MissingXMLElementException missingXMLElementException;
00196                 throw missingXMLElementException;
00197             }
00198 
00199             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        direction: " << str;
00200 
00201             channel = StringUtilities::getRobonetChannel(robonetNode);
00202             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        channel: " << channel;
00203 
00204             node = StringUtilities::getRobonetNode(robonetNode);
00205             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        node: " << node;
00206 
00207             if (elementHandle.ToElement()->Attribute("offset1"))
00208             {
00209                 offset1 = elementHandle.ToElement()->Attribute("offset1");
00210             }
00211             else
00212             {
00213                 std::stringstream err;
00214                 err << "The attribute [offset1] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00215                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00216                 //throw runtime_error(err.str());
00217                 MissingXMLElementException missingXMLElementException;
00218                 throw missingXMLElementException;
00219             }
00220 
00221             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        offset1: " << offset1;
00222 
00223             if (elementHandle.ToElement()->Attribute("offset2"))
00224             {
00225                 offset2 = elementHandle.ToElement()->Attribute("offset2");
00226             }
00227 
00228             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        offset2: " << offset2;
00229 
00230             if (elementHandle.ToElement()->Attribute("group"))
00231             {
00232                 group = elementHandle.ToElement()->Attribute("group");
00233             }
00234             else
00235             {
00236                 std::stringstream err;
00237                 err << "The attribute [group] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00238                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00239                 //throw runtime_error(err.str());
00240                 MissingXMLElementException missingXMLElementException;
00241                 throw missingXMLElementException;
00242             }
00243 
00244             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        group: " << group;
00245 
00246             if (elementHandle.ToElement()->Attribute("style"))
00247             {
00248                 str = elementHandle.ToElement()->Attribute("style");
00249 
00250                 if ( str.compare("Normal") == 0 )
00251                 {
00252                     style = RobonetDataElement::Normal;
00253                 }
00254                 else if ( str.compare("MotCom") == 0 )
00255                 {
00256                     style = RobonetDataElement::MotCom;
00257                 }
00258                 else if ( str.compare("Temperature") == 0 )
00259                 {
00260                     style = RobonetDataElement::Temperature;
00261                 }
00262                 else if ( str.compare("BrakePwm") == 0 )
00263                 {
00264                     style = RobonetDataElement::BrakePwm;
00265                 }
00266                 else if ( str.compare("FixedPointMilli") == 0 )
00267                 {
00268                     style = RobonetDataElement::FixedPointMilli;
00269                 }
00270                 else if ( str.compare("UnsignedFixedPointMilli") == 0 )
00271                 {
00272                     style = RobonetDataElement::UnsignedFixedPointMilli;
00273                 }
00274                 else if ( str.compare("FixedPointCenti") == 0 )
00275                 {
00276                     style = RobonetDataElement::FixedPointCenti;
00277                 }
00278                 else if ( str.compare("UnsignedFixedPointCenti") == 0 )
00279                 {
00280                     style = RobonetDataElement::UnsignedFixedPointCenti;
00281                 }
00282                 else if ( str.compare("PowConTemperature") == 0 )
00283                 {
00284                     style = RobonetDataElement::PowConTemperature;
00285                 }
00286                 else if ( str.compare("PowConCurrentMany") == 0 )
00287                 {
00288                     style = RobonetDataElement::PowConCurrentMany;
00289                 }
00290                 else if ( str.compare("PowConVoltageMany") == 0 )
00291                 {
00292                     style = RobonetDataElement::PowConVoltageMany;
00293                 }
00294                 else
00295                 {
00296                     NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, "DataElementFactory::xmlToDataElement() - Style must be either Normal, MotCom, Temperature or BrakePwm, not '" + str + "'");
00297                     MissingXMLElementException missingXMLElementException;
00298                     throw missingXMLElementException;
00299                 }
00300             }
00301             else
00302             {
00303                 std::stringstream err;
00304                 err << "The attribute [style] was not found for element [" << elementHandle.ToElement()->ValueStr() << "]";
00305                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00306                 //throw runtime_error(err.str());
00307                 MissingXMLElementException missingXMLElementException;
00308                 throw missingXMLElementException;
00309             }
00310 
00311             NasaCommonLogging::Logger::getCategory("gov.nasa.robonet.DataElementFactory") << log4cpp::Priority::INFO << "        style: " << str;
00312         }
00313         else
00314         {
00315             std::stringstream err;
00316             err << "The element [Element] was not found.";
00317             NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::ERROR, err.str());
00318             //throw runtime_error(err.str());
00319             MissingXMLElementException missingXMLElementException;
00320             throw missingXMLElementException;
00321         }
00322 
00323         // Only attempt to add to SMT if the client exists
00324         if ( smtclient ) {
00325             try {
00326                 // Suffix _t not used in SMT, eliminate it if it exists:
00327                 smttype = type.substr(0, type.rfind("_t"));
00328                 // SMT has different float types as well...
00329                 if ( !smttype.compare("float") ){
00330                     smttype = "float32";
00331                 }
00332                 if ( !smttype.compare("double") ){
00333                     smttype = "float64";
00334                 }
00335                 // Use uint8 for booleans, since that should be used under the hood.
00336                 if ( !smttype.compare("bool") ){
00337                     smttype = "uint8";
00338                 }
00339                 // Attempt to create an SMT ressource. Linux = big-endian.
00340                 auto resource = std::make_shared<SMT::Resource>( smtclient->createResource(name, smttype, 0, 0, "big", "") );
00341                 // Use the resource in creating the RDE:
00342                 dataElement.reset(new RobonetDataElement(type, direction, channel, node, RobonetDataElement::OffsetPair(offset1, offset2), group, style, resource));
00343                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::DEBUG, "Added RDE `" + name + "` with SMT::Resource");
00344             }
00345             catch (const SMT::SMTException e) {
00346                 // Either the resource couldn't be created, or it already existed?
00347                 // So says the Python API at least...
00348                 // This isn't a failure... yet, so just log:
00349                 err << "DataElementFactory::xmlToDataElement() - Problem creating SMT Resource `" << name << "`: ";
00350                 err << e.what();
00351                 NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::DEBUG, err.str());
00352                 // Create RDE as normal without the SMT Resource (for now)
00353                 dataElement.reset(new RobonetDataElement(type, direction, channel, node, RobonetDataElement::OffsetPair(offset1, offset2), group, style));
00354             }
00355         } else {
00356             // Since we're deprecating non SMT stuff, we'll log a warning.
00357             NasaCommonLogging::Logger::log("gov.nasa.robonet.DataElementFactory", log4cpp::Priority::WARN, "DataElementFactory::xmlToDataElement() - SMTClient not specified. Not using SMT for now. This will be DEPRECATED soon.");
00358             // Create RDE as normal without the SMT Resource (for now)
00359             dataElement.reset(new RobonetDataElement(type, direction, channel, node, RobonetDataElement::OffsetPair(offset1, offset2), group, style));
00360         }
00361 
00362         return std::make_pair(name, dataElement);
00363     }
00364 
00365 };
00366 
00367 #endif /* DATAELEMENTFACTORY_H_ */


robot_instance
Author(s):
autogenerated on Sat Jun 8 2019 20:43:12