/** * @file hand_forcetest.cpp * @brief Read BOTH the actual angle (0x0A) and the force sensor (0x2E) of the * right hand while it holds open, to see whether pushing a finger by hand * registers as a FORCE change even though the position can't move * (non-backdrivable). Robust re-query read (flush + resend + scan). * * g++ -std=c++17 -Iinclude example/hand_forcetest.cpp -o /tmp/hft * /tmp/hft /dev/ttyUSB1 (right hand; needs the port free) */ #include "inspire.h" #include #include #include #include #include // Robust read of a 6-value register (angleAct 0x0A or forceAct 0x2E). static int robustRead(SerialPort &sp, uint8_t addr, uint8_t id, Eigen::Matrix &out, double scale, bool sign) { std::vector q = {0xEB, 0x90, id, 0x04, 0x11, addr, 0x06, 0x0C, 0x00}; uint8_t s = 0; for (size_t i = 2; i < q.size() - 1; i++) s += q[i]; q.back() = s; uint8_t buf[64]; for (int att = 0; att < 8; att++) { sp.flush(); sp.send(q.data(), q.size()); usleep(8000); size_t n = sp.recv(buf, sizeof(buf)); for (size_t off = 0; off + 20 <= n; off++) { if (!((buf[off] == 0x90 && buf[off + 1] == 0xEB) || (buf[off] == 0xEB && buf[off + 1] == 0x90))) continue; if (buf[off + 4] != 0x11 || buf[off + 5] != addr) continue; uint8_t cs = 0; for (int i = 2; i < 19; i++) cs += buf[off + i]; if (buf[off + 19] != cs) continue; const uint8_t *b = buf + off; for (int i = 0; i < 6; i++) { uint16_t raw = b[7 + 2 * i] | (b[8 + 2 * i] << 8); out(i) = (sign ? (double)(int16_t)raw : (double)raw) * scale; } return 0; } } return 1; } int main(int argc, char **argv) { const char *pr = argc > 1 ? argv[1] : "/dev/ttyUSB1"; auto sp = std::make_shared(pr, B115200, 6); inspire::InspireHand right(sp, 1); right.ClearError(); right.SetVelocity(1000, 1000, 1000, 1000, 1000, 1000); right.SetForce(500, 500, 500, 500, 500, 500); Eigen::Matrix qopen, pos, force; for (int i = 0; i < 6; i++) qopen(i) = 1.0; // DIAGNOSTIC: mimic inspire_g1's tight loop (SetPos, settle, GetPos, GetForce, // no inter-cycle sleep) and count how often each read fails + whether force // actually changes. This reproduces the "force frozen" symptom. if (argc > 2 && std::string(argv[2]) == "diag") { int posFail = 0, forceFail = 0, N = 200; double fmin[6], fmax[6]; for (int i = 0; i < 6; i++) { fmin[i] = 1e9; fmax[i] = -1e9; } for (int k = 0; k < N; k++) { right.SetPosition(qopen); usleep(3000); if (robustRead(*sp, 0x0A, 1, pos, 1.0 / 1000.0, false) != 0) posFail++; if (robustRead(*sp, 0x2E, 1, force, 1.0, true) != 0) forceFail++; else for (int i = 0; i < 6; i++) { if (force(i) < fmin[i]) fmin[i] = force(i); if (force(i) > fmax[i]) fmax[i] = force(i); } } printf("tight loop N=%d: GetPosition fails=%d GetForce fails=%d\n", N, posFail, forceFail); printf("force range over run (g): "); for (int i = 0; i < 6; i++) printf("[%.0f..%.0f] ", fmin[i], fmax[i]); printf("\n"); return 0; } const char *NM[6] = {"pinky", "ring", "mid", "index", "thumbB", "thumbR"}; const double THRESH = 100.0; // grams of deviation from baseline = a deliberate push // Drive open + hold, and calibrate each finger's resting-force baseline (~2s). printf("Calibrating resting baseline — DON'T touch the fingers for 2s...\n"); double base[6] = {0, 0, 0, 0, 0, 0}; int nb = 0; for (int k = 0; k < 10; k++) { right.SetPosition(qopen); usleep(3000); if (robustRead(*sp, 0x2E, 1, force, 1.0, true) == 0) { for (int i = 0; i < 6; i++) base[i] += force(i); nb++; } usleep(150000); } for (int i = 0; i < 6; i++) base[i] = nb ? base[i] / nb : 0; printf("Baseline(g): "); for (int i = 0; i < 6; i++) printf("%s=%.0f ", NM[i], base[i]); printf("\n\nNow PUSH one right finger at a time — it flags which finger and how hard:\n\n"); for (int k = 0; k < 120; k++) { right.SetPosition(qopen); usleep(3000); int rf = robustRead(*sp, 0x2E, 1, force, 1.0, true); if (rf == 0) { char line[256]; int p = 0; bool pushed = false; for (int i = 0; i < 6; i++) { double dev = force(i) - base[i]; if (dev > THRESH || dev < -THRESH) { pushed = true; p += sprintf(line + p, "%s:%+.0fg ", NM[i], dev); } } if (pushed) printf("k%3d PUSH -> %s\n", k, line); } usleep(120000); } printf("(done)\n"); return 0; }