fastcat 0.13.20
C++ EtherCAT Device Command & Control Library
Loading...
Searching...
No Matches
manager.h
Go to the documentation of this file.
1#ifndef FASTCAT_MANAGER_H_
2#define FASTCAT_MANAGER_H_
3
4// Include related header (for cc files)
5
6// Include c then c++ libraries
7#include <cstdint>
8#include <atomic>
9#include <condition_variable>
10#include <memory>
11#include <mutex>
12#include <queue>
13#include <string>
14#include <thread>
15#include <unordered_map>
16#include <vector>
17
18// Include external then project includes
19#include <yaml-cpp/yaml.h>
20
21#include "fastcat/thread_safe_queue.h"
22#include "fastcat/device_base.h"
23#include "fastcat/jsd/actuator.h"
24#include "fastcat/jsd/jsd_device_base.h"
25#include "jsd/jsd.h"
26
27namespace fastcat
28{
29typedef std::pair<std::string, std::shared_ptr<DeviceBase>> DevicePair;
30typedef std::pair<std::string, jsd_t*> JSDPair;
31
36{
37 public:
38 Manager();
39 ~Manager();
40
46 void Shutdown();
47
67
73 bool ConfigFromYaml(const YAML::Node& node, double external_time = -1);
74
79 bool CreateConfigFromYaml(const YAML::Node& node, double external_time = -1);
80
85 bool InitHardware();
86
110 bool Process(double external_time = -1);
111
121 void QueueCommand(DeviceCmd& cmd);
122
127 std::vector<DeviceState> GetDeviceStates();
128
136 std::vector<std::shared_ptr<const DeviceState>> GetDeviceStatePointers();
137
141 double GetTargetLoopRate();
142
146 bool IsFaulted();
147
157 bool RecoverBus(std::string ifname);
158
165 bool ExecuteDeviceReset(std::string device_name);
166
173 bool ExecuteDeviceFault(std::string device_name);
174
183
193
198
206 bool PopSdoResponseQueue(SdoResponse& res);
207
212 bool GetActuatorParams(const std::string& name,
214
217 void GetDeviceNamesByType(std::vector<std::string>&,
218 fastcat::DeviceStateType);
219
223
227
232
237
244 bool SetExplicitInterpolationCyclesDelay(size_t delay);
245
248 bool SetInterpolationCyclesStale(size_t cycles);
249
250
251 private:
252 bool ConfigJSDBusFromYaml(const YAML::Node& node, double external_time);
253 bool ConfigFastcatBusFromYaml(const YAML::Node& node, double external_time);
254 bool ConfigOfflineBusFromYaml(const YAML::Node& node, double external_time);
255 bool WriteCommands();
256 bool ConfigSignals();
257 bool SortFastcatDevice(
258 std::shared_ptr<DeviceBase> device,
259 std::vector<std::shared_ptr<DeviceBase>>& sorted_devices,
260 std::vector<std::string> parents);
261
262 bool LoadActuatorPosFile();
263 bool ValidateActuatorPosFile();
264 // Full path of the saved positions file, so every message about it can name
265 // the file the operator has to go look at.
266 std::string PosFilePath() const;
267 bool SetActuatorPositions();
268 void GetActuatorPositions();
269 // Serialize actuator_pos_map_ to a YAML string. Cheap, pure CPU; called on
270 // the RT thread under parameter_mutex_ so it sees a consistent snapshot.
271 std::string BuildActuatorPosYaml();
272 // Perform the actual disk write (temp file + fsync + _prev backup + atomic
273 // rename) for the already-serialized `contents`. Runs ONLY on the background
274 // writer thread; touches no shared device state, takes no RT lock.
275 void WritePosFileToDisk(const std::string& contents);
276 void InvalidateActuatorPosFile();
277 // fsync the position directory so the last rename/unlink is durable across a
278 // power loss. Runs ONLY on the background writer thread.
279 void SyncPosFileDirectory();
280 // Background position-file writer: keeps all disk I/O (fsync, rename, backup
281 // copy) off the RT Process() thread so a save cannot cause a cycle slip.
282 void StartPosWriter();
283 void StopPosWriter();
284 void PosWriterLoop();
285 // Post a write (contents) or an invalidate request to the writer thread. If
286 // `wait` is true, block until the writer has processed it (used on shutdown
287 // to guarantee durability before exit). Both return the request sequence
288 // number, which can be handed to WaitForPosWriter() later to defer the block
289 // until after a caller-held lock is released; 0 means the request was already
290 // serviced inline because the writer thread is not running.
291 uint64_t PostPosWriteRequest(std::string contents, bool wait);
292 uint64_t PostPosInvalidateRequest(bool wait);
293 // Block until the writer has drained request `seq`. Never call while holding
294 // parameter_mutex_: the wait is fsync-bound and Process() contends on it.
295 void WaitForPosWriter(uint64_t seq);
296 // True iff every GOLD/PLATINUM actuator has its brake engaged (motor_on == 0,
297 // i.e. unpowered and mechanically held). Actuators with absolute encoders are
298 // ignored (their positions are not persisted). Returns false if there are no
299 // relevant actuators.
300 bool AllBrakesEngaged();
301 // Called at the end of each Process() cycle (under parameter_mutex_). Once
302 // AllBrakesEngaged() has held for pos_save_settle_sec_ it saves the current
303 // positions; on the falling edge (motion starting) it immediately invalidates
304 // the saved file so a stale in-motion position can never be loaded.
305 void UpdatePositionFileOnBrakeState(double monotonic_time);
306 bool CheckDeviceNameIsUnique(std::string name);
307 struct JsdBusInitParams {
308 std::string ifname;
309 jsd_t* jsd;
310 bool enable_autorecovery;
311 };
312
313 double target_loop_rate_hz_ = 0.0;
314 bool zero_latency_required_ = true;
315 bool faulted_ = true;
316 bool actuator_fault_on_missing_pos_file_ = true;
317 bool online_devices_exist_ = false;
318 std::string actuator_position_directory_;
319 std::map<std::string, jsd_t*> jsd_map_;
320
321 std::map<std::string, std::shared_ptr<DeviceBase>> device_map_;
322 std::vector<std::shared_ptr<DeviceBase>> fastcat_device_list_;
323 std::vector<std::shared_ptr<JsdDeviceBase>> jsd_device_list_;
324 std::shared_ptr<ThreadSafeQueue<DeviceCmd>> cmd_queue_;
325 std::vector<DeviceState> states_;
326 std::map<std::string, ActuatorPosData> actuator_pos_map_;
327 std::unordered_map<std::string, bool> unique_device_map_;
328 std::shared_ptr<std::queue<SdoResponse>> sdo_response_queue_;
329
330 std::vector<JsdBusInitParams> pending_jsd_inits_;
331
332 std::mutex parameter_mutex_;
333
334 // Falling-edge tracking for the invalidate-on-motion path. Starts true so a
335 // bus that comes up already stopped is not treated as a transition.
336 bool prev_all_brakes_engaged_ = true;
337
338 // Set whenever the motors are powered (brakes not all engaged), cleared once a
339 // save completes. Gating the save on this, rather than on an edge, guarantees
340 // exactly one save per motion->stop cycle and means a bus that comes up already
341 // stopped does not re-save the positions it just loaded.
342 bool saw_motion_since_last_save_ = false;
343
344 // monotonic_time at which the brakes most recently became fully engaged, or
345 // -1.0 when they are not. Used to enforce the pos_save_settle_sec_ debounce.
346 double brakes_engaged_since_ = -1.0;
347
348 // How long all brakes must stay continuously engaged before positions are
349 // considered settled and saved. Guards against persisting a mid-travel
350 // position when drive power is cut at speed (STO/e-stop/fault) and the joint
351 // coasts to rest against its brake. YAML: actuator_position_save_settle_sec.
352 double pos_save_settle_sec_ = 0.5;
353
354 // True only for topologies that actually persist actuator positions, i.e.
355 // those with at least one non-absolute-encoder GOLD/PLATINUM actuator. Set by
356 // LoadActuatorPosFile(), which bypasses all position-file handling otherwise.
357 // Every save/invalidate path must check this: AllBrakesEngaged() reports false
358 // when it finds no relevant actuator, which would otherwise be read as "in
359 // motion" and delete a position file this topology does not own (it may be
360 // shared with another topology that does use incremental encoders).
361 bool pos_file_enabled_ = false;
362
363 // ---- Background position-file writer ----
364 // A single dedicated thread performs all disk I/O for the position file so
365 // that no fsync/rename/backup-copy ever runs on the RT Process() thread. The
366 // RT thread only serializes the (tiny) YAML string under parameter_mutex_ and
367 // hands it off via the single-slot coalescing mailbox below.
368 std::thread pos_writer_thread_;
369 std::mutex pos_writer_mutex_;
370 std::condition_variable pos_writer_cv_; // RT -> writer: new request
371 std::condition_variable pos_writer_done_cv_; // writer -> RT: request drained
372 std::string pos_pending_contents_; // payload for a pending write
373 bool pos_pending_write_ = false;
374 bool pos_pending_invalidate_ = false;
375 bool pos_writer_stop_ = false; // ask writer to exit
376 // Monotonic counters to let a waiter (shutdown) know its request was handled.
377 uint64_t pos_request_seq_ = 0; // incremented on each post
378 uint64_t pos_processed_seq_ = 0; // writer sets = seq handled
379 // Whether pos_writer_thread_ exists and will drain the mailbox. Atomic because
380 // it is written by StartPosWriter()/StopPosWriter() on the application thread
381 // but read by the RT Process() thread (via PostPos*Request) to decide between
382 // handing off to the writer and writing inline.
383 std::atomic<bool> pos_writer_running_{false};
384
385};
386} // namespace fastcat
387
388#endif
Fastcat::Manager is the main application interface to manage all fastcat devices.
Definition manager.h:36
bool RecoverBus(std::string ifname)
Attempts to recover a faulty JSD bus by name.
Definition manager.cc:505
std::vector< std::shared_ptr< const DeviceState > > GetDeviceStatePointers()
Returns list of device state pointers.
Definition manager.cc:461
double GetTargetLoopRate()
Public getter to the YAML target_loop_rate_hz parameter.
Definition manager.cc:475
bool ExecuteDeviceFault(std::string device_name)
Triggers a single device to fault.
Definition manager.cc:1036
bool CreateConfigFromYaml(const YAML::Node &node, double external_time=-1)
Parses YAML configuration and creates device objects (no hardware init)
Definition manager.cc:164
void SetExplicitInterpolationAlgorithmLinear()
Set interpolation algorithm to use 1st order linear interpolation between knot points for both positi...
Definition manager.cc:1802
void SaveActuatorPositions()
Capture current actuator positions and write them to file.
Definition manager.cc:114
bool IsSdoResponseQueueEmpty()
checks if the SdoResponse Queue is empty
Definition manager.cc:1107
void ExecuteAllDeviceFaults()
Triggers all devices to Fault.
Definition manager.cc:1076
bool ConfigFromYaml(const YAML::Node &node, double external_time=-1)
Method that accepts a fastcat topology yaml and intializes bus.
Definition manager.cc:291
void ExecuteAllDeviceResets()
Triggers all devices to Reset.
Definition manager.cc:1094
void QueueCommand(DeviceCmd &cmd)
Interface to command devices on the bus.
Definition manager.cc:445
void SetExplicitInterpolationAlgorithmCubic()
Set interpolation algorithm to use 3rd order cubic interpolation between knot points for all actuator...
Definition manager.cc:1789
bool InitHardware()
Initializes EtherCAT hardware (executes deferred jsd_init calls)
Definition manager.cc:300
void SetExplicitInterpolationTimestampSourceClock()
Set interpolation algorithm to use the timestamp when the CSP message was received according to fastc...
Definition manager.cc:1828
bool GetActuatorParams(const std::string &name, fastcat::Actuator::ActuatorParams &param)
get actuator parameters
Definition manager.cc:490
void Shutdown()
Shutdown the bus and joins all threads.
Definition manager.cc:109
bool IsFaulted()
Public getter retrieve fault status.
Definition manager.cc:477
void SetExplicitInterpolationTimestampSourceCspMessage()
Set interpolation algorithm to use the timestamp in the CSP message generated by the calling module f...
Definition manager.cc:1815
std::vector< DeviceState > GetDeviceStates()
Returns list of device states.
Definition manager.cc:447
bool ExecuteDeviceReset(std::string device_name)
Triggers a single device to reset.
Definition manager.cc:1056
bool Process(double external_time=-1)
Updates synchronous PDO and background async SDO requests.
Definition manager.cc:336
void GetDeviceNamesByType(std::vector< std::string > &, fastcat::DeviceStateType)
names of actuator devices
Definition manager.cc:479
bool SetInterpolationCyclesStale(size_t cycles)
CSP interpolation will transition to a holding state if it has not received a CSP message within the ...
Definition manager.cc:1858
bool SetExplicitInterpolationCyclesDelay(size_t delay)
Set number of cycles of the calling module to delay the onset of explicit interpolation,...
Definition manager.cc:1841
Manager()
Definition manager.cc:89
~Manager()
Definition manager.cc:95
bool PopSdoResponseQueue(SdoResponse &res)
get the result of a background SDO operation
Definition manager.cc:1112
Definition device_base.h:18
std::pair< std::string, std::shared_ptr< DeviceBase > > DevicePair
Definition manager.h:29
std::pair< std::string, jsd_t * > JSDPair
Definition manager.h:30
Definition actuator.h:110