ethercat_driver_ros2  main
C++ ROS test
ec_pdo_channel_manager.hpp
Go to the documentation of this file.
1 // Copyright 2023 ICUBE Laboratory, University of Strasbourg
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Author: Maciej Bednarczyk (macbednarczyk@gmail.com)
16 
17 #ifndef ETHERCAT_INTERFACE__EC_PDO_CHANNEL_MANAGER_HPP_
18 #define ETHERCAT_INTERFACE__EC_PDO_CHANNEL_MANAGER_HPP_
19 
20 #include <ecrt.h>
21 #include <string>
22 #include <vector>
23 #include <limits>
24 
25 #include "yaml-cpp/yaml.h"
26 
27 namespace ethercat_interface
28 {
29 enum PdoType
30 {
31  RPDO = 0,
32  TPDO = 1
33 };
34 
36 {
37 public:
41  std::vector<double> * state_interface,
42  std::vector<double> * command_interface)
43  {
44  command_interface_ptr_ = command_interface;
45  state_interface_ptr_ = state_interface;
46  }
47 
48  ec_pdo_entry_info_t get_pdo_entry_info() {return {index, sub_index, type2bits(data_type)};}
49 
50  double ec_read(uint8_t * domain_address)
51  {
52  if (data_type == "uint8") {
53  last_value = static_cast<double>(EC_READ_U8(domain_address));
54  } else if (data_type == "int8") {
55  last_value = static_cast<double>(EC_READ_S8(domain_address));
56  } else if (data_type == "uint16") {
57  last_value = static_cast<double>(EC_READ_U16(domain_address));
58  } else if (data_type == "int16") {
59  last_value = static_cast<double>(EC_READ_S16(domain_address));
60  } else if (data_type == "uint32") {
61  last_value = static_cast<double>(EC_READ_U32(domain_address));
62  } else if (data_type == "int32") {
63  last_value = static_cast<double>(EC_READ_S32(domain_address));
64  } else if (data_type == "uint64") {
65  last_value = static_cast<double>(EC_READ_U64(domain_address));
66  } else if (data_type == "int64") {
67  last_value = static_cast<double>(EC_READ_S64(domain_address));
68  } else if (data_type == "bool") {
69  last_value = (EC_READ_U8(domain_address) & data_mask) ? 1 : 0;
70  } else {
71  last_value = static_cast<double>(EC_READ_U8(domain_address) & data_mask);
72  }
74  return last_value;
75  }
76 
77  void ec_write(uint8_t * domain_address, double value)
78  {
79  if (data_type == "uint8") {
80  EC_WRITE_U8(domain_address, static_cast<uint8_t>(value));
81  } else if (data_type == "int8") {
82  EC_WRITE_S8(domain_address, static_cast<int8_t>(value));
83  } else if (data_type == "uint16") {
84  EC_WRITE_U16(domain_address, static_cast<uint16_t>(value));
85  } else if (data_type == "int16") {
86  EC_WRITE_S16(domain_address, static_cast<int16_t>(value));
87  } else if (data_type == "uint32") {
88  EC_WRITE_U32(domain_address, static_cast<uint32_t>(value));
89  } else if (data_type == "int32") {
90  EC_WRITE_S32(domain_address, static_cast<int32_t>(value));
91  } else if (data_type == "uint64") {
92  EC_WRITE_U64(domain_address, static_cast<uint64_t>(value));
93  } else if (data_type == "int64") {
94  EC_WRITE_S64(domain_address, static_cast<int64_t>(value));
95  } else {
96  buffer_ = EC_READ_U8(domain_address);
97  if (popcount(data_mask) == 1) {
98  buffer_ &= ~(data_mask);
99  if (value) {buffer_ |= data_mask;}
100  } else if (data_mask != 0) {
101  buffer_ = 0;
102  buffer_ |= (static_cast<uint8_t>(value) & data_mask);
103  }
104  EC_WRITE_U8(domain_address, buffer_);
105  }
106  last_value = value;
107  }
108 
109  void ec_update(uint8_t * domain_address)
110  {
111  // update state interface
112  if (pdo_type == TPDO) {
113  ec_read(domain_address);
114  if (interface_index >= 0) {
115  state_interface_ptr_->at(interface_index) = last_value;
116  }
117  } else if (pdo_type == RPDO && allow_ec_write) {
118  if (interface_index >= 0 &&
119  !std::isnan(command_interface_ptr_->at(interface_index)) &&
121  {
122  ec_write(domain_address, factor * command_interface_ptr_->at(interface_index) + offset);
123  } else {
124  if (!std::isnan(default_value)) {
125  ec_write(domain_address, default_value);
126  }
127  }
128  }
129  }
130 
131  bool load_from_config(YAML::Node channel_config)
132  {
133  // index
134  if (channel_config["index"]) {
135  index = channel_config["index"].as<uint16_t>();
136  } else {
137  std::cerr << "missing channel index info" << std::endl;
138  }
139  // sub_index
140  if (channel_config["sub_index"]) {
141  sub_index = channel_config["sub_index"].as<uint8_t>();
142  } else {
143  std::cerr << "channel " << index << ": missing channel info" << std::endl;
144  }
145  // data type
146  if (channel_config["type"]) {
147  data_type = channel_config["type"].as<std::string>();
148  } else {
149  std::cerr << "channel " << index << ": missing channel data type info" << std::endl;
150  }
151 
152  if (pdo_type == RPDO) {
153  // interface name
154  if (channel_config["command_interface"]) {
155  interface_name = channel_config["command_interface"].as<std::string>();
156  }
157  // default value
158  if (channel_config["default"]) {
159  default_value = channel_config["default"].as<double>();
160  }
161 
162  } else if (pdo_type == TPDO) {
163  // interface name
164  if (channel_config["state_interface"]) {
165  interface_name = channel_config["state_interface"].as<std::string>();
166  }
167  }
168 
169  // factor
170  if (channel_config["factor"]) {
171  factor = channel_config["factor"].as<double>();
172  }
173  // offset
174  if (channel_config["offset"]) {
175  offset = channel_config["offset"].as<double>();
176  }
177  // mask
178  if (channel_config["mask"]) {
179  data_mask = channel_config["mask"].as<uint8_t>();
180  }
181 
182  return true;
183  }
184 
185  uint8_t type2bits(std::string type)
186  {
187  if (type == "bool") {
188  return 1;
189  } else if (type == "int16" || type == "uint16") {
190  return 16;
191  } else if (type == "int8" || type == "uint8") {
192  return 8;
193  } else if (type == "int16" || type == "uint16") {
194  return 16;
195  } else if (type == "int32" || type == "uint32") {
196  return 32;
197  } else if (type == "int64" || type == "uint64") {
198  return 64;
199  } else if (type.find("bit") != std::string::npos) {
200  std::string n_bits = type.substr(type.find("bit") + 3);
201  return static_cast<uint8_t>(std::stoi(n_bits));
202  }
203  return -1;
204  }
205 
207  uint16_t index;
208  uint8_t sub_index;
209  std::string data_type;
210  std::string interface_name;
211  uint8_t data_mask = 255;
212  double default_value = std::numeric_limits<double>::quiet_NaN();
213  int interface_index = -1;
214  double last_value = std::numeric_limits<double>::quiet_NaN();
215  bool allow_ec_write = true;
216  bool override_command = false;
217  double factor = 1;
218  double offset = 0;
219 
220 private:
221  std::vector<double> * command_interface_ptr_;
222  std::vector<double> * state_interface_ptr_;
223  uint8_t buffer_ = 0;
224 
225  int popcount(uint8_t x)
226  {
227  int count = 0;
228  for (; x != 0; x >>= 1) {if (x & 1) {count++;}}
229  return count;
230  }
231 };
232 
233 } // namespace ethercat_interface
234 #endif // ETHERCAT_INTERFACE__EC_PDO_CHANNEL_MANAGER_HPP_
Definition: ec_pdo_channel_manager.hpp:36
void setup_interface_ptrs(std::vector< double > *state_interface, std::vector< double > *command_interface)
Definition: ec_pdo_channel_manager.hpp:40
ec_pdo_entry_info_t get_pdo_entry_info()
Definition: ec_pdo_channel_manager.hpp:48
std::string interface_name
Definition: ec_pdo_channel_manager.hpp:210
void ec_update(uint8_t *domain_address)
Definition: ec_pdo_channel_manager.hpp:109
bool load_from_config(YAML::Node channel_config)
Definition: ec_pdo_channel_manager.hpp:131
double last_value
Definition: ec_pdo_channel_manager.hpp:214
double ec_read(uint8_t *domain_address)
Definition: ec_pdo_channel_manager.hpp:50
bool allow_ec_write
Definition: ec_pdo_channel_manager.hpp:215
int interface_index
Definition: ec_pdo_channel_manager.hpp:213
uint16_t index
Definition: ec_pdo_channel_manager.hpp:207
double offset
Definition: ec_pdo_channel_manager.hpp:218
double default_value
Definition: ec_pdo_channel_manager.hpp:212
uint8_t sub_index
Definition: ec_pdo_channel_manager.hpp:208
uint8_t data_mask
Definition: ec_pdo_channel_manager.hpp:211
PdoType pdo_type
Definition: ec_pdo_channel_manager.hpp:206
std::string data_type
Definition: ec_pdo_channel_manager.hpp:209
EcPdoChannelManager()
Definition: ec_pdo_channel_manager.hpp:38
bool override_command
Definition: ec_pdo_channel_manager.hpp:216
void ec_write(uint8_t *domain_address, double value)
Definition: ec_pdo_channel_manager.hpp:77
~EcPdoChannelManager()
Definition: ec_pdo_channel_manager.hpp:39
uint8_t type2bits(std::string type)
Definition: ec_pdo_channel_manager.hpp:185
double factor
Definition: ec_pdo_channel_manager.hpp:217
Definition: ec_master.hpp:29
PdoType
Definition: ec_pdo_channel_manager.hpp:30
@ TPDO
Definition: ec_pdo_channel_manager.hpp:32
@ RPDO
Definition: ec_pdo_channel_manager.hpp:31