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.
1O que vai num MotorCmd_: mode, q, dq, tau, kp, kd
2Rampa × degrau: o torque que cada um pede
3Watchdog: comando velho vira amortecimento
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.
01 · Trê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.
02 · O 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ô".
2. Cabeçalho
mode_pr = 0 (PR: pitch/roll em série), mode_machine copiado do primeiro LowState_, e crc = CRC().Crc(cmd) antes de publicar.
O simulador Python não confere o CRC e manda mode_machine = 0; o kit preenche os dois mesmo assim, como o exemplo oficial, para o código ir igual ao robô.
3. Laço de 2 ms
O exemplo oficial do G1 envia a cada 2 ms (control_dt_ = 0,002). A política pode ser mais lenta (50 Hz): o laço rápido reenvia o último alvo com os limites.
É nesse laço que o watchdog mora: ele vê quando o alvo envelhece.
03 · Rampa, 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.
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]
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.
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)
degrau · junta mais perto do limite: left_wrist_pitch (9 de 5 N·m, ≈ 170 %)
juntas que pediram acima do limite: 4
ciclo de envio: 2 ms · watchdog: amortecimento ativado
saída: 1
simulador: fim em t = 9.0 s · robô suspenso (pés fora do chão)
O mesmo alvo de uma vez: quatro juntas pedem acima do teto, e o punho pede quase o dobro do que tem. No robô real isso é tranco e motor saturado; o script sai com código 1.
04 · Prá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).
05 · Teste 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
Correto
O comando tem mode, q, dq, tau, kp e kd. Não há termo integral: o PID com Ki do curso antigo não corresponde ao SDK.
Não é essa
O comando tem mode, q, dq, tau, kp e kd. Não há termo integral: o PID com Ki do curso antigo não corresponde ao SDK.Rever: O que vai num comando
Pergunta 2 de 4
A política parou de mandar alvos. O que o watchdog do kit faz?
Correto
Comando velho é sinal de que algo travou. Amortecer é o modo seguro; voltar sozinho esconderia a falha.
O simulador não confere o CRC. Por que o kit preenche mesmo assim?
Correto
O exemplo oficial calcula CRC().Crc(cmd) e copia o mode_machine. O ensaio no simulador vale mais quando o código é o mesmo do real.
Não é essa
O exemplo oficial calcula CRC().Crc(cmd) e copia o mode_machine. O ensaio no simulador vale mais quando o código é o mesmo do real.Rever: O que vai num comando
Teste concluído
Você acertou {a} de {n}. Acertando todas, a aula é marcada como concluída.
Escolha uma alternativa. A explicação aparece depois da sua tentativa.
06 · Em 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.