00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00023
00024
00025 #include "DS301Node.h"
00026 #include "exceptions.h"
00027
00028 namespace icl_hardware {
00029 namespace canopen_schunk {
00030
00031 DS301Node::DS301Node(const uint8_t node_id, const CanDevPtr& can_device, HeartBeatMonitor::Ptr heartbeat_monitor):
00032 m_nmt(node_id,can_device),
00033 m_sdo(node_id, can_device),
00034 m_emcy(EMCY::Ptr(new EMCY(node_id))),
00035 m_node_id(node_id),
00036 m_can_dev(can_device),
00037 m_heartbeat_monitor(heartbeat_monitor),
00038 m_heartbeat_cycle_time_ms(50)
00039 {
00040 for (size_t i = 0; i < 4; ++i)
00041 {
00042 m_rpdos.push_back(RPDO::Ptr(new RPDO(node_id, i, can_device)));
00043 m_tpdos.push_back(TPDO::Ptr(new TPDO(node_id, i, can_device)));
00044 }
00045 }
00046
00047 void DS301Node::initNode()
00048 {
00049 m_nmt.preOperational();
00050 startHeartbeat();
00051 }
00052
00053 void DS301Node::registerWSBroadcaster(boost::shared_ptr<icl_comm::websocket::WsBroadcaster> broadcaster)
00054 {
00055 m_ws_broadcaster = broadcaster;
00056 }
00057
00058 void DS301Node::startHeartbeat()
00059 {
00060 m_sdo.download(false, 0x1017, 0, m_heartbeat_cycle_time_ms);
00061
00062 m_heartbeat_monitor->addHeartbeat(m_node_id);
00063 }
00064
00065
00066 void DS301Node::initPDOMappingSingle (const PDO::MappingConfigurationList& config,
00067 const uint16_t pdo_nr,
00068 const PDO::eTransmissionType& transmission_type,
00069 const ePDO_TYPE& direction_type,
00070 const bool dummy_mapping,
00071 const uint8_t cyclic_timeout_cycles)
00072 {
00073 PDO::PDOStringMatchVec mapping;
00074 boost::unordered_map<std::string, PDOMapEntry>* map;
00075 if (direction_type == RECEIVE_PDO)
00076 {
00077 mapping = m_rpdos.at(pdo_nr)->remap(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
00078 map = &m_rpdo_mapping;
00079 }
00080 else if (direction_type == TRANSMIT_PDO)
00081 {
00082 mapping = m_tpdos.at(pdo_nr)->remap(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
00083 map = &m_tpdo_mapping;
00084 }
00085 else
00086 {
00087 LOGGING_ERROR_C (CanOpen, DS301Node, "Illegal PDO type given. Only RECEIVE_PDO and TRANSMIT_PDO are allowed." << endl);
00088 }
00089
00090
00091 for (boost::unordered_map<std::string, PDOMapEntry>::iterator it = map->begin();
00092 it != map->end();
00093 )
00094 {
00095 if (it->second.pdo_nr == pdo_nr)
00096 {
00097 map->erase(it++);
00098 }
00099 else
00100 {
00101 ++it;
00102 }
00103 }
00104
00105
00106 for (PDO::PDOStringMatchVec::iterator it = mapping.begin(); it != mapping.end(); ++it)
00107 {
00108 PDOMapEntry entry;
00109 entry.pdo_nr = pdo_nr;
00110 entry.pdo_mapping_index = it->pdo_mapping_index;
00111
00112 map->insert(std::pair<std::string, PDOMapEntry>(it->name, entry));
00113 }
00114 }
00115
00116 void DS301Node::appendPDOMappingSingle (const PDO::MappingConfigurationList& config,
00117 const uint16_t pdo_nr,
00118 const PDO::eTransmissionType& transmission_type,
00119 const DS301Node::ePDO_TYPE& direction_type,
00120 const bool dummy_mapping,
00121 const uint8_t cyclic_timeout_cycles)
00122 {
00123 PDO::PDOStringMatchVec mapping;
00124 boost::unordered_map<std::string, PDOMapEntry>* map;
00125
00126 if (direction_type == RECEIVE_PDO)
00127 {
00128 mapping = m_rpdos.at(pdo_nr)->appendMapping(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
00129 map = &m_rpdo_mapping;
00130 }
00131 else if (direction_type == TRANSMIT_PDO)
00132 {
00133 mapping = m_tpdos.at(pdo_nr)->appendMapping(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
00134 map = &m_tpdo_mapping;
00135 }
00136 else
00137 {
00138 LOGGING_ERROR_C (CanOpen, DS301Node, "Illegal PDO type given. Only RECEIVE_PDO and TRANSMIT_PDO are allowed." << endl);
00139 }
00140
00141
00142 for (PDO::PDOStringMatchVec::iterator it = mapping.begin(); it != mapping.end(); ++it)
00143 {
00144 PDOMapEntry entry;
00145 entry.pdo_nr = pdo_nr;
00146 entry.pdo_mapping_index = it->pdo_mapping_index;
00147
00148 map->insert(std::pair<std::string, PDOMapEntry>(it->name, entry));
00149 }
00150 }
00151
00152
00153
00154 void DS301Node::uploadPDOs()
00155 {
00156 for (TPDO::PtrList::iterator it = m_tpdos.begin(); it != m_tpdos.end(); ++it)
00157 {
00158 (*it)->upload();
00159 }
00160 }
00161
00162 void DS301Node::downloadPDOs()
00163 {
00164 for (RPDO::PtrList::iterator it = m_rpdos.begin(); it != m_rpdos.end(); ++it)
00165 {
00166 (*it)->download();
00167 }
00168 }
00169
00170 void DS301Node::printPDOMapping()
00171 {
00172 uint32_t data32;
00173 size_t max_num_rpdo = 512;
00174
00175
00176 std::stringstream ss;
00177 ss << "PDO Mapping queried from device:" << std::endl;
00178 ss << "===== RPDOs ===== " << std::endl;
00179
00180 for (uint8_t i = 0; i < max_num_rpdo; ++i)
00181 {
00182 uint8_t num_entries;
00183 try
00184 {
00185 m_sdo.upload(false, 0x1600+i, 0, num_entries);
00186 }
00187 catch (const ProtocolException& e)
00188 {
00189
00190 break;
00191 }
00192 ss << " === RPDO " << static_cast<int>(i) << " - " << static_cast<int>(num_entries) << " entries ===" << std::endl;
00193
00194 for (uint8_t j = 1; j <= num_entries; ++j)
00195 {
00196 m_sdo.upload(false, 0x1600+i, j, data32);
00197 int index = (data32 & 0xFFFF0000) >> 16;
00198 int subindex = (data32 & 0x0000FF00) >> 8;
00199 int length = data32 & 0x000000FF;
00200 ss << " " << static_cast<int>(j) << " -> "
00201 << hexToString(index) << " / " << subindex << ", length: " << length << " bits" << std::endl;
00202 }
00203 }
00204
00205 ss << std::endl;
00206
00207 size_t max_num_tpdo = 512;
00208
00209 ss << "===== TPDOs ===== " << std::endl;
00210
00211 for (uint8_t i = 0; i < max_num_tpdo; ++i)
00212 {
00213 uint8_t num_entries;
00214 try
00215 {
00216 m_sdo.upload(false, 0x1A00+i, 0, num_entries);
00217 }
00218 catch (const ProtocolException& e)
00219 {
00220
00221 break;
00222 }
00223 ss << " === TPDO " << static_cast<int>(i) << " - " << static_cast<int>(num_entries) << " entries ===" << std::endl;
00224
00225 for (uint8_t j = 1; j <= num_entries; ++j)
00226 {
00227 m_sdo.upload(false, 0x1A00+i, j, data32);
00228 int index = (data32 & 0xFFFF0000) >> 16;
00229 int subindex = (data32 & 0x0000FF00) >> 8;
00230 int length = data32 & 0x000000FF;
00231 ss << " " << static_cast<int>(j) << " -> "
00232 << hexToString(index) << " / " << subindex << ", length: " << length << " bits" << std::endl;
00233 }
00234 }
00235
00236 LOGGING_INFO (CanOpen, ss.str() << endl);
00237 }
00238
00239 void DS301Node::registerPDONotifyCallback (const std::string& identifier,
00240 const boost::function< void() >& f)
00241 {
00242 boost::unordered_map<std::string,PDOMapEntry>::iterator it = m_tpdo_mapping.find(identifier);
00243 if(it != m_tpdo_mapping.end())
00244 {
00245 size_t pdo_nr = it->second.pdo_nr;
00246 m_tpdos[pdo_nr]->registerNotifyCallback(f);
00247 LOGGING_DEBUG_C (CanOpen, DS302Node, "Registered notification callback for PDO entry " <<
00248 identifier << endl;
00249 );
00250 }
00251 else
00252 {
00253 std::stringstream ss;
00254 ss << "Notifier callback function for a PDO entry named " << identifier
00255 << " requested, however, no entry with this given identifier exists within this PDO";
00256 throw PDOException(ss.str());
00257 }
00258 }
00259
00260 void DS301Node::stopNode()
00261 {
00262 m_nmt.stop();
00263 }
00264
00265
00266
00267 }}