DS301Node.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of the SCHUNK Canopen Driver suite.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 SCHUNK GmbH, Lauffen/Neckar Germany
12 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
23 //----------------------------------------------------------------------
24 
25 #include "DS301Node.h"
26 #include "exceptions.h"
27 
28 namespace icl_hardware {
29 namespace canopen_schunk {
30 
31 DS301Node::DS301Node(const uint8_t node_id, const CanDevPtr& can_device, HeartBeatMonitor::Ptr heartbeat_monitor):
32  m_nmt(node_id,can_device),
33  m_sdo(node_id, can_device),
34  m_emcy(EMCY::Ptr(new EMCY(node_id))),
35  m_node_id(node_id),
36  m_can_dev(can_device),
37  m_heartbeat_monitor(heartbeat_monitor),
38  m_heartbeat_cycle_time_ms(50)
39 {
40  for (size_t i = 0; i < 4; ++i)
41  {
42  m_rpdos.push_back(RPDO::Ptr(new RPDO(node_id, i, can_device)));
43  m_tpdos.push_back(TPDO::Ptr(new TPDO(node_id, i, can_device)));
44  }
45 }
46 
48 {
51 }
52 
54 {
55  m_ws_broadcaster = broadcaster;
56 }
57 
59 {
60  m_sdo.download(false, 0x1017, 0, m_heartbeat_cycle_time_ms);
61  // add initial heartbeat. If the device never sends a heartbeat the monitor will escalate quickly
62  m_heartbeat_monitor->addHeartbeat(m_node_id);
63 }
64 
65 
67  const uint16_t pdo_nr,
68  const PDO::eTransmissionType& transmission_type,
69  const ePDO_TYPE& direction_type,
70  const bool dummy_mapping,
71  const uint8_t cyclic_timeout_cycles)
72 {
74  boost::unordered_map<std::string, PDOMapEntry>* map;
75  if (direction_type == RECEIVE_PDO)
76  {
77  mapping = m_rpdos.at(pdo_nr)->remap(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
78  map = &m_rpdo_mapping;
79  }
80  else if (direction_type == TRANSMIT_PDO)
81  {
82  mapping = m_tpdos.at(pdo_nr)->remap(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
83  map = &m_tpdo_mapping;
84  }
85  else
86  {
87  LOGGING_ERROR_C (CanOpen, DS301Node, "Illegal PDO type given. Only RECEIVE_PDO and TRANSMIT_PDO are allowed." << endl);
88  }
89 
90  // remove all mapping entries from this pdo
91  for (boost::unordered_map<std::string, PDOMapEntry>::iterator it = map->begin();
92  it != map->end();
93  /* iterating is done in the body */)
94  {
95  if (it->second.pdo_nr == pdo_nr)
96  {
97  map->erase(it++);
98  }
99  else
100  {
101  ++it;
102  }
103  }
104 
105  // Now add the configured pdos to the node's mapping
106  for (PDO::PDOStringMatchVec::iterator it = mapping.begin(); it != mapping.end(); ++it)
107  {
108  PDOMapEntry entry;
109  entry.pdo_nr = pdo_nr;
110  entry.pdo_mapping_index = it->pdo_mapping_index;
111 
112  map->insert(std::pair<std::string, PDOMapEntry>(it->name, entry));
113  }
114 }
115 
117  const uint16_t pdo_nr,
118  const PDO::eTransmissionType& transmission_type,
119  const DS301Node::ePDO_TYPE& direction_type,
120  const bool dummy_mapping,
121  const uint8_t cyclic_timeout_cycles)
122 {
124  boost::unordered_map<std::string, PDOMapEntry>* map;
125 
126  if (direction_type == RECEIVE_PDO)
127  {
128  mapping = m_rpdos.at(pdo_nr)->appendMapping(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
129  map = &m_rpdo_mapping;
130  }
131  else if (direction_type == TRANSMIT_PDO)
132  {
133  mapping = m_tpdos.at(pdo_nr)->appendMapping(m_sdo, config, transmission_type, dummy_mapping, cyclic_timeout_cycles);
134  map = &m_tpdo_mapping;
135  }
136  else
137  {
138  LOGGING_ERROR_C (CanOpen, DS301Node, "Illegal PDO type given. Only RECEIVE_PDO and TRANSMIT_PDO are allowed." << endl);
139  }
140 
141  // Now add the configured pdos to the node's mapping
142  for (PDO::PDOStringMatchVec::iterator it = mapping.begin(); it != mapping.end(); ++it)
143  {
144  PDOMapEntry entry;
145  entry.pdo_nr = pdo_nr;
146  entry.pdo_mapping_index = it->pdo_mapping_index;
147 
148  map->insert(std::pair<std::string, PDOMapEntry>(it->name, entry));
149  }
150 }
151 
152 
153 
155 {
156  for (TPDO::PtrList::iterator it = m_tpdos.begin(); it != m_tpdos.end(); ++it)
157  {
158  (*it)->upload();
159  }
160 }
161 
163 {
164  for (RPDO::PtrList::iterator it = m_rpdos.begin(); it != m_rpdos.end(); ++it)
165  {
166  (*it)->download();
167  }
168 }
169 
171 {
172  uint32_t data32;
173  size_t max_num_rpdo = 512;
174  // get number of RPDOs
175 
176  std::stringstream ss;
177  ss << "PDO Mapping queried from device:" << std::endl;
178  ss << "===== RPDOs ===== " << std::endl;
179 
180  for (uint8_t i = 0; i < max_num_rpdo; ++i)
181  {
182  uint8_t num_entries;
183  try
184  {
185  m_sdo.upload(false, 0x1600+i, 0, num_entries);
186  }
187  catch (const ProtocolException& e)
188  {
189  // This PDO object does not exist
190  break;
191  }
192  ss << " === RPDO " << static_cast<int>(i) << " - " << static_cast<int>(num_entries) << " entries ===" << std::endl;
193 
194  for (uint8_t j = 1; j <= num_entries; ++j)
195  {
196  m_sdo.upload(false, 0x1600+i, j, data32);
197  int index = (data32 & 0xFFFF0000) >> 16;
198  int subindex = (data32 & 0x0000FF00) >> 8;
199  int length = data32 & 0x000000FF;
200  ss << " " << static_cast<int>(j) << " -> "
201  << hexToString(index) << " / " << subindex << ", length: " << length << " bits" << std::endl;
202  }
203  }
204 
205  ss << std::endl;
206 
207  size_t max_num_tpdo = 512;
208 
209  ss << "===== TPDOs ===== " << std::endl;
210 
211  for (uint8_t i = 0; i < max_num_tpdo; ++i)
212  {
213  uint8_t num_entries;
214  try
215  {
216  m_sdo.upload(false, 0x1A00+i, 0, num_entries);
217  }
218  catch (const ProtocolException& e)
219  {
220  // This PDO object does not exist
221  break;
222  }
223  ss << " === TPDO " << static_cast<int>(i) << " - " << static_cast<int>(num_entries) << " entries ===" << std::endl;
224 
225  for (uint8_t j = 1; j <= num_entries; ++j)
226  {
227  m_sdo.upload(false, 0x1A00+i, j, data32);
228  int index = (data32 & 0xFFFF0000) >> 16;
229  int subindex = (data32 & 0x0000FF00) >> 8;
230  int length = data32 & 0x000000FF;
231  ss << " " << static_cast<int>(j) << " -> "
232  << hexToString(index) << " / " << subindex << ", length: " << length << " bits" << std::endl;
233  }
234  }
235 
236  LOGGING_INFO (CanOpen, ss.str() << endl);
237 }
238 
239 void DS301Node::registerPDONotifyCallback (const std::string& identifier,
240  const boost::function< void() >& f)
241 {
242  boost::unordered_map<std::string,PDOMapEntry>::iterator it = m_tpdo_mapping.find(identifier);
243  if(it != m_tpdo_mapping.end())
244  {
245  size_t pdo_nr = it->second.pdo_nr;
246  m_tpdos[pdo_nr]->registerNotifyCallback(f);
247  LOGGING_DEBUG_C (CanOpen, DS302Node, "Registered notification callback for PDO entry " <<
248  identifier << endl;
249  );
250  }
251  else
252  {
253  std::stringstream ss;
254  ss << "Notifier callback function for a PDO entry named " << identifier
255  << " requested, however, no entry with this given identifier exists within this PDO";
256  throw PDOException(ss.str());
257  }
258 }
259 
261 {
262  m_nmt.stop();
263 }
264 
265 
266 
267 }}// end of NS
RPDO::PtrList m_rpdos
RPDOS of this node (up to 4 in standard config)
Definition: DS301Node.h:307
unsigned int uint32_t
DS301Node(const uint8_t node_id, const CanDevPtr &can_device, HeartBeatMonitor::Ptr heartbeat_monitor)
Definition: DS301Node.cpp:31
std::vector< MappingConfiguration > MappingConfigurationList
The MappingConfigurationList holds multiple Mapping configurations. The Mapping of a single PDO is de...
Definition: PDO.h:70
virtual void initPDOMappingSingle(const PDO::MappingConfigurationList &config, const uint16_t pdo_nr, const PDO::eTransmissionType &transmission_type, const ePDO_TYPE &pdo_type, const bool dummy_mapping=false, const uint8_t cyclic_timeout_cycles=0)
Init PDO mapping with a given mapping configuration for a given pdo nr.
Definition: DS301Node.cpp:66
f
Unique index to find a mapped Object dictionary item in a PDO.
Definition: DS301Node.h:78
virtual void startHeartbeat()
Initializes the heartbeat for the node. Throws ProtocolException it heartbeat cannot be initialized...
Definition: DS301Node.cpp:58
#define LOGGING_INFO(streamname, arg)
Basic CanOpen exception that contains the Object dictionary index and subindex.
Definition: exceptions.h:37
SDO m_sdo
SDO object for specific calls.
Definition: DS301Node.h:305
boost::shared_ptr< icl_comm::websocket::WsBroadcaster > m_ws_broadcaster
Interface to send out diagnostics data. Only available if compiled with IC_BUILDER_ICL_COMM_WEBSOCKET...
Definition: DS301Node.h:331
This class describes Receive PDOs, meaning PDOs that send data from the host to the device...
Definition: RPDO.h:33
bool download(const bool normal_transfer, const uint16_t index, const uint8_t subindex, const std::vector< uint8_t > &usrdata)
Downloads SDO data from the master to the slave (From PC to node).
Definition: SDO.cpp:84
boost::unordered_map< std::string, PDOMapEntry > m_rpdo_mapping
This map holds a mapping between an identifier string and a mapped position in a RPDO.
Definition: DS301Node.h:321
void preOperational()
preOperational switches the device back into pre-operational state where configuration can occur ...
Definition: NMT.cpp:101
virtual void appendPDOMappingSingle(const PDO::MappingConfigurationList &config, const uint16_t pdo_nr, const PDO::eTransmissionType &transmission_type, const ePDO_TYPE &pdo_type, const bool dummy_mapping=false, const uint8_t cyclic_timeout_cycles=0)
Appends one or more mapping parameters to the existing mapping. Note that the PDO will be disabled wh...
Definition: DS301Node.cpp:116
PDO related exceptions go here.
Definition: exceptions.h:114
virtual void initNode()
Initializes the node.
Definition: DS301Node.cpp:47
uint8_t m_node_id
CANOPEN ID of the node.
Definition: DS301Node.h:315
eTransmissionType
Transmission types of a PDO, needed when mapping PDOs.
Definition: PDO.h:122
virtual void registerWSBroadcaster(boost::shared_ptr< icl_comm::websocket::WsBroadcaster > broadcaster)
registerWSBroadcaster Adds a debug interface
Definition: DS301Node.cpp:53
void stop()
stop Stops the device by setting the NMT state to stopped
Definition: NMT.cpp:96
unsigned char uint8_t
boost::unordered_map< std::string, PDOMapEntry > m_tpdo_mapping
This map holds a mapping between an identifier string and a mapped position in a TPDO.
Definition: DS301Node.h:324
void printPDOMapping()
Will query the PDO mapping from the device and print that to the output.
Definition: DS301Node.cpp:170
#define LOGGING_DEBUG_C(streamname, classname, arg)
This class describes Transmit PDOs, meaning PDOs that send data from the device to the host...
Definition: TPDO.h:33
ThreadStream & endl(ThreadStream &stream)
The EMCY class handles the spontaneously occurring Emergency (EMCY) messages, keeps track of a nodes ...
Definition: EMCY.h:42
virtual void stopNode()
Puts the node into nmt state preo_operational.
Definition: DS301Node.cpp:260
bool upload(const bool normal_transfer, const uint16_t index, const uint8_t subindex, std::vector< uint8_t > &uploaded_data)
Uploads data from a slave (node) to a master (PC).
Definition: SDO.cpp:209
std::vector< PDOStringMatch > PDOStringMatchVec
Definition: PDO.h:119
std::vector< unsigned int > mapping(const T &t1, const T &t2)
void downloadPDOs()
Downloads all Receive-PDOs of this node to the device.
Definition: DS301Node.cpp:162
TPDO::PtrList m_tpdos
TPDOS of this node (up to 4 in standard config)
Definition: DS301Node.h:309
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
ePDO_TYPE
Type of a PDO. RECEIVE_PDOs carry data from the host to the device, TRANSMIT_PDOs from the device to ...
Definition: DS301Node.h:88
void uploadPDOs()
Uploads all Transmit-PDOs of this node from the device.
Definition: DS301Node.cpp:154
std::string hexToString(const uint64_t num)
Converts a hexadecimal number into its string representation 0xXX.
Definition: helper.cpp:33
unsigned short uint16_t
HeartBeatMonitor::Ptr m_heartbeat_monitor
Definition: DS301Node.h:326
#define LOGGING_ERROR_C(streamname, classname, arg)
The DS301Node class Is the base class representation of canOpen devices. It is the access point to th...
Definition: DS301Node.h:67
NMT m_nmt
Object to handle NMT calls and status.
Definition: DS301Node.h:303
void registerPDONotifyCallback(const std::string &identifier, const boost::function< void()> &f)
This function maps a callback to a specific mapped PDO entry. This callback will be called by the PDO...
Definition: DS301Node.cpp:239


schunk_canopen_driver
Author(s): Felix Mauch , Georg Heppner
autogenerated on Mon Jun 10 2019 15:07:49