13#include <toml++/toml.h>
21#include <yarp/os/LogStream.h>
22#include <yarp/os/ResourceFinder.h>
25using namespace std::chrono_literals;
43 return (sw & (1u << 12)) != 0;
47 return (sw & (1u << 13)) != 0;
61 yCInfo(CIA402,
"StoreHome37: initializing EtherCAT on %s", ifname.
c_str());
62 const auto rc = mgr.init(ifname);
65 yCError(CIA402,
"StoreHome37: init failed on %s (rc=%d)", ifname.
c_str(),
int(rc));
73 auto name = mgr.getName(s);
76 yCInfo(CIA402,
"StoreHome3537: found slave %d: %s", s, name.c_str());
81 yCError(CIA402,
"StoreHome3537: no slaves found");
88 allOk = allOk && this->homeAndPersistSingle(s, hm, hoff, timeoutMs, restore);
94 allOk = this->writeEncoderToml(slaves, tomlPath);
108 toml::table slaveTable;
111 uint32_t enc1Res = 0;
112 uint32_t enc2Res = 0;
117 uint32_t enc1RawPos = 0;
118 int32_t enc1AdjPos = 0;
123 uint32_t enc2RawPos = 0;
124 int32_t enc2AdjPos = 0;
129 const double enc1ResInv = enc1Res ? (1.0 /
static_cast<double>(enc1Res)) : 0.0;
130 const double enc2ResInv = enc2Res ? (1.0 /
static_cast<double>(enc2Res)) : 0.0;
131 const double enc1AdjDeg =
static_cast<double>(enc1AdjPos) * enc1ResInv * 360.0;
132 const double enc2AdjDeg =
static_cast<double>(enc2AdjPos) * enc2ResInv * 360.0;
135 const double enc1RawDeg =
static_cast<double>(enc1RawPos) * enc1ResInv * 360.0;
136 const double enc2RawDeg =
static_cast<double>(enc2RawPos) * enc2ResInv * 360.0;
139 toml::table enc1Table;
140 enc1Table.insert(
"raw_position",
static_cast<int64_t
>(enc1RawPos));
141 enc1Table.insert(
"raw_position_degrees", enc1RawDeg);
142 enc1Table.insert(
"adjusted_position",
static_cast<int64_t
>(enc1AdjPos));
143 enc1Table.insert(
"adjusted_position_degrees", enc1AdjDeg);
144 enc1Table.insert(
"counts_per_revolution",
static_cast<int64_t
>(enc1Res));
145 enc1Table.insert(
"raw_to_degrees_factor", enc1Res ? (360.0 /
static_cast<double>(enc1Res)) : 0.0);
146 slaveTable.insert(
"encoder1", enc1Table);
149 toml::table enc2Table;
150 enc2Table.insert(
"raw_position",
static_cast<int64_t
>(enc2RawPos));
151 enc2Table.insert(
"raw_position_degrees", enc2RawDeg);
152 enc2Table.insert(
"adjusted_position",
static_cast<int64_t
>(enc2AdjPos));
153 enc2Table.insert(
"adjusted_position_degrees", enc2AdjDeg);
154 enc2Table.insert(
"counts_per_revolution",
static_cast<int64_t
>(enc2Res));
155 enc2Table.insert(
"raw_to_degrees_factor", enc2Res ? (360.0 /
static_cast<double>(enc2Res)) : 0.0);
156 slaveTable.insert(
"encoder2", enc2Table);
159 slaveTable.insert(
"name", mgr.
getName(s));
161 root.insert(slaveName, slaveTable);
164 "s%02d: enc1 raw=%u adj=%d adj_deg=%.6f (res=%u), "
165 "enc2 raw=%u adj=%d adj_deg=%.6f (res=%u)",
181 yCError(CIA402,
"StoreHome37: cannot open %s for writing", tomlPath.
c_str());
186 yCInfo(CIA402,
"StoreHome37: encoder data written to %s", tomlPath.
c_str());
190 bool homeAndPersistSingle(
int s, int8_t hm, int32_t hoff,
int timeoutMs,
bool restore)
197 yCError(CIA402,
"s%02d: write 0x6060=6 failed", s);
203 if (hm != 35 && hm != 37)
205 yCWarning(CIA402,
"s%02d: invalid homing method %d, using 37", s,
int(hm));
210 yCError(CIA402,
"s%02d: write 0x6098=%d failed", s,
int(hm));
220 yCError(CIA402,
"s%02d: write 0x607C=%d failed", s, hoff);
229 const uint16_t cwLow =
static_cast<uint16_t
>(cw & ~(1u << 4));
230 const uint16_t cwHigh =
static_cast<uint16_t
>(cwLow | (1u << 4));
236 yCError(CIA402,
"s%02d: toggle 0x6040 bit4 failed", s);
249 yCError(CIA402,
"s%02d: read 0x6041 failed", s);
254 yCError(CIA402,
"s%02d: homing error (0x6041=0x%04X)", s, sw);
261 yCInfo(CIA402,
"s%02d: homing attained (pos=%d, sw=0x%04X)", s, pos, sw);
269 yCError(CIA402,
"s%02d: timeout waiting homing attained", s);
278 yCInfo(CIA402,
"s%02d: vendor Home (0x2005:01) = %d", s, homeVal);
282 const uint8_t flag = restore ? uint8_t{1} : uint8_t{0};
286 yCError(CIA402,
"s%02d: write 0x2005:02=%u failed", s, flag);
293 constexpr uint32_t EVAS = 0x65766173u;
297 yCError(CIA402,
"s%02d: save 0x1010:01='evas' failed", s);
301 "s%02d: configuration saved (home persisted, restoreOnStartup=%s)",
303 restore ?
"true" :
"false");
314 m_impl = std::make_unique<Impl>();
321 const std::string ifname = rf.check(
"ifname") ? rf.
find(
"ifname").asString()
324 if (rf.check(
"method"))
326 methodTmp = rf.find(
"method").asInt32();
328 const int8_t method =
static_cast<int8_t
>(methodTmp);
330 int32_t homeOffset = 0;
331 if (rf.check(
"home-offset"))
333 homeOffset = rf.find(
"home-offset").asInt32();
336 int timeoutMs = 2000;
337 if (rf.check(
"timeout-ms"))
339 timeoutMs = rf.find(
"timeout-ms").asInt32();
342 bool restoreOnBoot =
true;
343 if (rf.check(
"restore-on-boot"))
346 if (rf.find(
"restore-on-boot").isBool())
348 restoreOnBoot = rf.find(
"restore-on-boot").asBool();
351 restoreOnBoot = (rf.find(
"restore-on-boot").asInt32() != 0);
356 "StoreHome37: ifname=%s method=%d home-offset=%d timeout-ms=%d restore-on-boot=%s",
361 restoreOnBoot ?
"true" :
"false");
363 if (rf.check(
"toml-output"))
365 tomlPath = rf.
find(
"toml-output").asString();
373 oss <<
"joint_calibration_"
376 tomlPath = oss.
str();
379 yCInfo(CIA402,
"Do you want to proceed? (press ENTER to continue)");
382 return m_impl->run(ifname, method, homeOffset, timeoutMs, restoreOnBoot, tomlPath);
static constexpr uint16_t IDX_STORE_PARAMS
static bool swHomingAttained(uint16_t sw)
static constexpr uint16_t IDX_POSITION_ACT
static constexpr uint16_t IDX_HOME_VENDOR
static constexpr uint16_t IDX_OPMODE
static bool swHomingError(uint16_t sw)
static constexpr uint16_t IDX_HOME_OFFSET
static constexpr uint16_t IDX_HOMING_METHOD
static constexpr uint16_t IDX_CONTROLWORD
static constexpr uint16_t IDX_STATUSWORD
std::string getName(int slaveIndex) const noexcept
Get the name of a slave device.
Error readSDO(int slaveIndex, uint16_t idx, uint8_t subIdx, T &out) noexcept
Read an SDO value from a slave (blocking call).
@ NoError
Operation completed successfully.
~StoreHome37()
Destructor.
StoreHome37()
Default constructor.
bool run(yarp::os::ResourceFinder &rf)
Run the full homing and persistence procedure on all slaves, then write encoder data.
bool run(const std::string &ifname, int8_t hm, int32_t hoff, int timeoutMs, bool restore, const std::string &tomlPath)
T duration_cast(T... args)
static constexpr uint16_t IDX_ENC2_CONFIG
:03 = resolution (counts/rev)
static constexpr uint16_t IDX_ENC1_DATA
:01 = raw position, :02 = adjusted position
static constexpr uint16_t IDX_ENC1_CONFIG
:03 = resolution (counts/rev)
std::tm getLocalTime(const std::time_t &t)
static constexpr uint16_t IDX_ENC2_DATA
:01 = raw position, :02 = adjusted position