RokubiminiEthercatBusManager.cpp
Go to the documentation of this file.
2 
3 namespace rokubimini
4 {
5 namespace ethercat
6 {
7 bool RokubiminiEthercatBusManager::loadSetup(std::vector<std::shared_ptr<rokubimini::Rokubimini>>& rokubiminis)
8 {
9  // Loop through all Rokubiminis and create their buses.
10  for (const auto& rokubimini_setup : attachedRokubiminiSetups_)
11  {
12  const auto rokubimini_ethercat_setup = std::dynamic_pointer_cast<setup::RokubiminiEthercat>(rokubimini_setup);
13 
14  const std::string bus_name = rokubimini_ethercat_setup->ethercatBus_;
15  if (bus_name.empty())
16  {
17  ROS_ERROR("[%s] The name of the bus is empty.", rokubimini_setup->name_.c_str());
18  return false;
19  }
21  const auto& it = buses_.find(bus_name);
22  if (it == buses_.end())
23  {
24  // Create a new bus.
26  buses_.insert(std::make_pair(bus_name, std::unique_ptr<rokubimini::soem_interface::EthercatBusBase>(bus)));
27  }
28  else
29  {
30  // Take existing bus.
31  bus = it->second.get();
32  }
33 
34  for (const auto& rokubimini : rokubiminis)
35  {
36  if (rokubimini->getName() == rokubimini_ethercat_setup->name_)
37  {
38  auto rokubimini_ethercat = (RokubiminiEthercat*)(rokubimini.get());
39  if (!addRokubiminiToBus(rokubimini_ethercat, bus, rokubimini_ethercat_setup))
40  {
41  return false;
42  }
43  }
44  }
45  // const auto rokubimini = dynamic_cast<RokubiminiEthercat *>(rokubiminis[i].get());
46  // std::dynamic_pointer_cast<rokubimini::ethercat::RokubiminiEthercat>(rokubiminis[i]);
47  }
48 
49  return true;
50 }
51 
54  const std::shared_ptr<setup::RokubiminiEthercat>& rokubiminiEthercatSetup) const
55 {
56  auto slave = std::make_shared<RokubiminiEthercatSlave>(rokubiminiEthercatSetup->name_, bus,
57  rokubiminiEthercatSetup->ethercatAddress_,
58  rokubiminiEthercatSetup->ethercatPdoTypeEnum_);
59 
60  if (!bus->addSlave(slave))
61  {
62  return false;
63  }
64 
65  rokubimini->setSlavePointer(slave);
66  return true;
67 }
68 
70 {
72  // Sleep for some time to give the slave time to execute the pre-op cb
74 }
76 {
79 }
81 {
82  if (bus == nullptr)
83  {
84  ROS_ERROR_STREAM("[RokubiminiEthercatBusManager::addEthercatBus] bus is nullptr");
85  return false;
86  }
87 
88  std::lock_guard<std::recursive_mutex> lock(busMutex_);
89  const auto& it = buses_.find(bus->getName());
90  if (it == buses_.end())
91  {
92  buses_.insert(std::make_pair(bus->getName(), std::unique_ptr<rokubimini::soem_interface::EthercatBusBase>(bus)));
93  return true;
94  }
95  else
96  {
97  return false;
98  }
99 }
100 
101 bool RokubiminiEthercatBusManager::addEthercatBus(std::unique_ptr<rokubimini::soem_interface::EthercatBusBase> bus)
102 {
103  if (bus == nullptr)
104  {
105  ROS_ERROR_STREAM("[RokubiminiEthercatBusManager::addEthercatBus] bus is nullptr");
106  return false;
107  }
108 
109  std::lock_guard<std::recursive_mutex> lock(busMutex_);
110  const auto& it = buses_.find(bus->getName());
111  if (it == buses_.end())
112  {
113  buses_.insert(std::make_pair(bus->getName(), std::move(bus)));
114  return true;
115  }
116  else
117  {
118  return false;
119  }
120 }
121 
123 {
124  bool success = startupCommunication();
126  return success;
127 }
128 
130 {
131  std::lock_guard<std::recursive_mutex> lock(busMutex_);
132  // Only set the state but do not wait for it, since some devices (e.g. junctions) might not be able to reach it.
133  for (auto& bus : buses_)
134  {
135  bus.second->setState(EC_STATE_OPERATIONAL);
136  }
137 }
138 
140 {
141  std::lock_guard<std::recursive_mutex> lock(busMutex_);
142  // Only set the state but do not wait for it, since some devices (e.g. junctions) might not be able to reach it.
143  for (auto& bus : buses_)
144  {
145  bus.second->setState(EC_STATE_PRE_OP);
146  }
147 }
148 
150 {
151  std::lock_guard<std::recursive_mutex> lock(busMutex_);
152  // Only set the state but do not wait for it, since some devices (e.g. junctions) might not be able to reach it.
153  for (auto& bus : buses_)
154  {
155  bus.second->setState(EC_STATE_SAFE_OP);
156  }
157 }
158 
159 void RokubiminiEthercatBusManager::waitForState(const uint16_t state, const uint16_t slave, const std::string& busName,
160  const unsigned int maxRetries, const double retrySleep)
161 {
162  std::lock_guard<std::recursive_mutex> lock(busMutex_);
163  if (busName.empty())
164  {
165  for (auto& bus : buses_)
166  {
167  bus.second->waitForState(state, slave, maxRetries, retrySleep);
168  }
169  }
170  else
171  {
172  buses_.at(busName)->waitForState(state, slave, maxRetries, retrySleep);
173  }
174 }
175 
177 {
178  std::lock_guard<std::recursive_mutex> lock(busMutex_);
179  for (auto& bus : buses_)
180  {
181  if (!bus.second->startup())
182  {
183  ROS_ERROR("Failed to startup bus %s.", bus.first.c_str());
184  return false;
185  }
186  }
187  return true;
188 }
189 
191 {
192  std::lock_guard<std::recursive_mutex> lock(busMutex_);
193  for (auto& bus : buses_)
194  {
195  bus.second->updateRead();
196  }
197 }
198 
200 {
201  std::lock_guard<std::recursive_mutex> lock(busMutex_);
202  for (auto& bus : buses_)
203  {
204  bus.second->updateWrite();
205  }
206 }
207 
209 {
210  std::lock_guard<std::recursive_mutex> lock(busMutex_);
211  for (auto& bus : buses_)
212  {
213  bus.second->shutdown();
214  }
215 }
216 
217 std::unique_ptr<rokubimini::soem_interface::EthercatBusBase>
219 {
220  std::unique_ptr<rokubimini::soem_interface::EthercatBusBase> bus_out = std::move(buses_.at(name));
221  buses_.erase(name);
222  return bus_out;
223 }
224 
226 {
227  BusMap bus_map_out;
228 
229  for (auto& bus : buses_)
230  {
231  bus_map_out.insert(std::make_pair(bus.first, std::move(bus.second)));
232  }
233 
234  buses_.clear();
235  return bus_map_out;
236 }
237 
238 } // namespace ethercat
239 } // namespace rokubimini
bool addRokubiminiToBus(RokubiminiEthercat *rokubimini, rokubimini::soem_interface::EthercatBusBase *bus, const std::shared_ptr< setup::RokubiminiEthercat > &rokubiminiEthercatSetup) const
Adds a Rokubimini to Bus.
void threadSleep(const double duration)
Definition: ThreadSleep.cpp:9
bool addEthercatBus(rokubimini::soem_interface::EthercatBusBase *bus)
Adds an ethercat bus to the manager. The manager takes ownership of the bus pointer.
std::recursive_mutex busMutex_
Mutex prohibiting simultaneous access to EtherCAT bus manager.
bool addSlave(const EthercatSlaveBasePtr &slave)
bool loadSetup(std::vector< std::shared_ptr< rokubimini::Rokubimini >> &rokubiminis) override
Loads the Rokubimini Setups.
BusMap buses_
Map with all the Ethercat buses available.
unsigned short uint16_t
std::unique_ptr< rokubimini::soem_interface::EthercatBusBase > extractBusByName(const std::string &name)
Returns an owning bus pointer. The manager is now not managing this bus anymore.
The Rokubimini RokubiminiEthercat Setup class.
std::unordered_map< std::string, std::unique_ptr< rokubimini::soem_interface::EthercatBusBase >> BusMap
EC_STATE_OPERATIONAL
void setBussesOperational()
Sets all busses to operational state.
void readAllBuses() override
Calls update read on all busses.
int slave
EC_STATE_SAFE_OP
EC_STATE_PRE_OP
void setBussesPreOperational()
Sets all busses to pre operational state.
void setSlavePointer(const RokubiminiEthercatSlavePtr &slavePtr)
Sets a pointer to the implementation.
bool startupAllBuses()
Starts up all busses and puts them in operational mode.
std::vector< std::shared_ptr< setup::Rokubimini > > attachedRokubiminiSetups_
void writeToAllBuses() override
Calls update write on all busses.
BusMap extractBuses()
Extracts all buses from the manager. The manager is now not managing any buses anymore.
Class for managing an ethercat bus containing one or multiple slaves.
void shutdownAllBuses() override
Calls shutdown on all busses.
uint8_t state
#define ROS_ERROR_STREAM(args)
void setBussesSafeOperational()
Sets all busses to safe operational state.
#define ROS_ERROR(...)
void waitForState(const uint16_t state, const uint16_t slave=0, const std::string &busName="", const unsigned int maxRetries=40, const double retrySleep=0.001)
Waits for the slave to reach a state.


rokubimini_ethercat
Author(s):
autogenerated on Wed Mar 3 2021 03:09:16