DFX_inspire_service/example/hand_forcetest.cpp
2026-08-04 16:09:17 +04:00

136 lines
5.0 KiB
C++

/**
* @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 <cstdio>
#include <cstdint>
#include <memory>
#include <vector>
#include <unistd.h>
// 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<double, 6, 1> &out, double scale, bool sign)
{
std::vector<uint8_t> 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<SerialPort>(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<double, 6, 1> 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;
}