FTH 4 · Operar um humanoide real|INEMA.CLUB-PRO

Aula 4 · 20 min

Comandar em baixo nível sem quebrar nada

Mandar um alvo para 29 motores é fácil; o difícil é o que acontece quando o alvo está longe, fora do limite ou para de chegar. Nesta aula você comanda o G1 suspenso com três proteções (limite do MJCF, rampa e watchdog) e vê, no mesmo script, o degrau pedir mais torque do que o motor tem.

Começar a aula
Joelho e perna de um robô humanoide suspenso num pórtico, com um cabo até uma placa de driver de motor na bancada.

Nesta aula você vai

  1. 1O que vai num MotorCmd_: mode, q, dq, tau, kp, kd
  2. 2Rampa × degrau: o torque que cada um pede
  3. 3Watchdog: comando velho vira amortecimento
  4. 4CRC e mode_machine, que o robô real cobra

Objetivo: comandar as 29 juntas do G1 com limite, rampa e watchdog, e ver o comando em degrau pedir torque acima do limite.

01Três proteções entre a política e o motor

Clique em cada bloco.

Clique em cada bloco do diagrama para ver o que ele faz.

O watchdog do kit é seu, no seu controlador. O que o firmware do robô faz sem comando não está documentado no SDK: não conte com ele. E ele roda no mesmo processo do envio: se o processo morrer, quem segura é a parada física e o pórtico.

02O que vai num comando

Clique em cada parte.

1. MotorCmd_

mode (1 habilita, 0 desabilita), q (alvo), dq (velocidade-alvo), tau (torque somado), kp e kd. Não há Ki nem modo global de "posição" ou "torque".

Rígido = kp alto; só torque = kp e kd zero e tau preenchido; amortecimento = kp zero e kd pequeno.

Ganhos do exemplo oficialPernas 60/60/60/100/40/40, cintura 60/40/40, braços 40; kd 1 (joelho 2). Ponto de partida do exemplo, não "padrão do robô".

03Rampa, limites e watchdog no G1 suspenso

6 s de comando: rampa de 3 s até a pose de trabalho (joelhos e cotovelos dobrados), segura, e em t = 4,5 s a "política" trava de propósito.

Terminal · simulador + rampa
F=${FTH:-$HOME/fth}; cd $F/operar && . $F/.venv/bin/activate
python3 kit/sim.py --s 9 --suspenso &
python3 kit/rampa.py; echo "saída: $?"
wait
Trecho · kit/rampa.py
    idade = t_ciclo - comp["carimbo"]
    if not amortecendo and idade > IDADE_MAX:
        amortecendo = True
        print(f"política sem resposta desde t = {a.trava_em:.1f} s")
        print(f"watchdog: comando velho há mais de {IDADE_MAX * 1000:.0f} ms → amortecimento ativado (kp=0, kd={KD_AMORTECER:g})")
    cmd.mode_pr, cmd.mode_machine = 0, modo
    for i in range(op.N):
        m_ = cmd.motor_cmd[i]
        m_.mode, m_.dq, m_.tau = 1, 0.0, 0.0
        if amortecendo:
            m_.q, m_.kp, m_.kd = 0.0, 0.0, KD_AMORTECER
        else:
            m_.q, m_.kp, m_.kd = comp["alvo"][i], op.KP[i], op.KD[i]
Terminal · o erro comum: degrau
F=${FTH:-$HOME/fth}; cd $F/operar && . $F/.venv/bin/activate
python3 kit/sim.py --s 9 --suspenso &
python3 kit/rampa.py --sem-rampa; echo "saída: $?"
wait
Exemplo do repositório
simulador: G1 29 motores · DDS domínio 1 em lo · 9 s · suspenso: sim
estado recebido: 29 juntas · pose inicial lida · mode_machine = 0
limites: 29/29 alvos já dentro da faixa do MJCF (margem 0.05 rad), 0 recortados
política sem resposta desde t = 4.5 s
watchdog: comando velho há mais de 100 ms → amortecimento ativado (kp=0, kd=2)
rampa de 3 s · todas as juntas pediram menos de 50 % do torque máximo
juntas que pediram acima do limite: 0
ciclo de envio: 2 ms · watchdog: amortecimento ativado
saída: 0
simulador: fim em t = 9.0 s · robô suspenso (pés fora do chão)

Com rampa, todas as juntas ficam abaixo da metade do teto. A política trava, o watchdog vê o comando envelhecer e amortece.

04Prática

As três proteções, medidas.

E1 · Rampa com watchdog

5 min

Rode o bloco da rampa e localize na saída o momento em que o watchdog age.

Pronto quando: python3 kit/rampa.py; echo "saída: $?" → juntas que pediram acima do limite: 0, watchdog: amortecimento ativado e saída: 0.

E2 · Ver o degrau falhar

5 min

Rode o bloco do erro comum e diga qual junta passou mais do limite e por que justo ela.

Pronto quando: python3 kit/rampa.py --sem-rampa; echo "saída: $?" → juntas que pediram acima do limite: 4 e saída: 1.

E3 · Ler o limite no MJCF

5 min

Ache no MJCF do simulador o teto de torque do punho que estourou no degrau.

Pronto quando: grep -c 'ctrlrange="-5 5"' ~/fth/unitree_mujoco/unitree_robots/g1/g1_29dof.xml → 4 (pitch e yaw dos dois punhos, teto de 5 N·m).

05Teste da aula

A explicação aparece depois da sua resposta.

Pergunta 1 de 4

Qual campo NÃO existe num MotorCmd_ do G1?competência

06Em três frases

LimiteAlvo recortado na faixa do MJCF; torque com teto no ctrlrange.
RampaDo ponto atual ao alvo em segundos, nunca de uma vez.
WatchdogComando velho vira amortecimento e não religa sozinho.

Para ir além

Aula anteriorPróxima aula