Update 2026-08-04 16:09:16
This commit is contained in:
parent
d6c4eae9bc
commit
6b850c7826
@ -32,4 +32,15 @@ add_executable(inspire_g1 inspire_g1.cpp)
|
||||
add_executable(inspire_h1 inspire_h1.cpp)
|
||||
|
||||
# example
|
||||
add_executable(hand_example example/hand_example.cpp)
|
||||
add_executable(hand_setid example/hand_setid.cpp)
|
||||
add_executable(hand_example example/hand_example.cpp)
|
||||
add_executable(hand_gestures example/hand_gestures.cpp)
|
||||
add_executable(arm_raise example/arm_raise.cpp)
|
||||
add_executable(arm_action example/arm_action.cpp)
|
||||
add_executable(greet example/greet.cpp)
|
||||
add_executable(handshake example/handshake.cpp)
|
||||
add_executable(thumbup example/thumbup.cpp)
|
||||
add_executable(hand_pose example/hand_pose.cpp)
|
||||
add_executable(hand_record example/hand_record.cpp)
|
||||
add_executable(hand_bridge example/hand_bridge.cpp)
|
||||
add_executable(like example/like.cpp)
|
||||
311
README.md
311
README.md
@ -1,21 +1,202 @@
|
||||
<div align="center">
|
||||
<h1 align="center">DFX Inspire Hand service</h1>
|
||||
<a href="https://www.unitree.com/" target="_blank">
|
||||
<img src="https://www.unitree.com/images/0079f8938336436e955ea3a98c4e1e59.svg" alt="Unitree LOGO" width="15%">
|
||||
</a>
|
||||
</div>
|
||||
# Inspire RH56 dual-hand stack for the Unitree G1
|
||||
|
||||
# 1. 📦 Introduction
|
||||
Runs the two Inspire RH56DFX hands on the G1's PC2 and puts a web dashboard in front of
|
||||
them: finger sliders, saved shapes, force-follow, live diagnostics, arm actions, and
|
||||
**arm + hand record / replay**.
|
||||
|
||||
[Unitree Robot RH56DFX Inspire Hand](https://support.unitree.com/home/en/H1_developer/Dexterous_hand) Controller.
|
||||
Everything runs in **one Docker container on the robot**. The workstation is only where you
|
||||
edit the source and push it.
|
||||
|
||||
<div align="center">
|
||||
<img src="doc/img/RH56.png" width="300"/>
|
||||
</div>
|
||||
Forked from Unitree's [DFX inspire hand service](https://support.unitree.com/home/en/H1_developer/Dexterous_hand);
|
||||
the service protocol section at the bottom is theirs.
|
||||
|
||||
---
|
||||
|
||||
The user sends `unitree_go::msg::dds::MotorCmds_` messages to the `rt/inspire/cmd` topic to control the dexterous hand,
|
||||
and receives `unitree_go::msg::dds::MotorStates_` messages from the `rt/inspire/state` topic to obtain its status.
|
||||
## Run it
|
||||
|
||||
```bash
|
||||
./start.sh
|
||||
```
|
||||
|
||||
That is the whole thing. It builds the image the first time (a few minutes), starts the
|
||||
container, waits until the dashboard actually answers, and prints the URL:
|
||||
|
||||
```
|
||||
>> up
|
||||
service=True bridge=True iface=eth0 ports=/dev/ttyUSB1, /dev/ttyUSB2
|
||||
recorder: ready (record/replay panel enabled)
|
||||
http://192.168.123.164:8088
|
||||
http://10.255.254.88:8088
|
||||
```
|
||||
|
||||
| command | does |
|
||||
|---|---|
|
||||
| `./start.sh` | start (builds the image if missing) |
|
||||
| `./start.sh stop` | stop the container |
|
||||
| `./start.sh restart` | stop + start |
|
||||
| `./start.sh status` | running? serving what? hands alive? |
|
||||
| `./start.sh logs` | follow the container log |
|
||||
| `./start.sh rebuild` | force an image rebuild, then start |
|
||||
|
||||
**Run it on the robot.** Run it on the workstation and it rsyncs this folder to the robot
|
||||
and runs itself there — the hands, the DDS link to the arm and Docker are all on the robot,
|
||||
so there is nothing to run locally. Override the target with `ROBOT=unitree@10.255.254.88`.
|
||||
|
||||
Only `./start.sh` is meant to be run by hand. `docker/start.sh` is the container's internal
|
||||
entrypoint; running it directly starts the services natively, outside Docker.
|
||||
|
||||
---
|
||||
|
||||
## What you get at `:8088`
|
||||
|
||||
| card | what it does |
|
||||
|---|---|
|
||||
| **Fingers** | 12 sliders, presets, save/load named shapes |
|
||||
| **Force follow** | press a fingertip and that finger closes under your hand — the RH56 cannot be back-driven, so this admittance loop is the only way to shape it by hand |
|
||||
| **Joint tracker** | angle traces + per-finger force, current, force limit, temperature, ERROR/STATUS |
|
||||
| **Diagnostics** | live read-back and a close→open self-test, reported per hand |
|
||||
| **Read back** | copy the hand's current pose into the sliders |
|
||||
| **Arm + hand combo** | built-in arm actions fused with a hand pose ⚠ arm moves |
|
||||
| **Record / replay** | record the arm + hand, replay it, manage the library ⚠ arm moves |
|
||||
| **Library** | manage saved shapes and combos |
|
||||
|
||||
---
|
||||
|
||||
## Record / replay
|
||||
|
||||
Runs [`recorder/g1_record_replay.py`](recorder/g1_record_replay.py) as a child process over a
|
||||
pty — the same script you would run from a terminal, so a take made in the browser and one
|
||||
made from the CLI are the same file in `DataG1/`.
|
||||
|
||||
**A take:** arms hold for ~3 s, then go **limp** so you pose them by hand. Fingers *cannot*
|
||||
be posed by hand, so they are driven by the in-take keys or your saved shapes. At the end the
|
||||
recorder offers a preview (⚠ replays the take — the arm moves) and then a save; both are
|
||||
answered in the panel.
|
||||
|
||||
**Stop** sends SIGINT, so the recorder walks the arm home and releases it. It does not kill.
|
||||
|
||||
**Replay** has ⏸ Pause / ▶ Resume. Pause freezes the playback clock but keeps publishing the
|
||||
frame it stopped on — the arm holds the pose rather than dropping, because `rt/arm_sdk` needs
|
||||
a continuous command.
|
||||
|
||||
### In-take keys — and when they do nothing
|
||||
|
||||
`o` both to rest · `c` both closed · `[` `]` right open/close · `;` `'` left open/close ·
|
||||
`f` arm/disarm follow · `1`-`9` your saved shapes.
|
||||
|
||||
Which of them the recorder acts on depends on `--fingers`. Measured against the real recorder
|
||||
while watching `rt/inspire/cmd`:
|
||||
|
||||
| `--fingers` | what the keys do | records |
|
||||
|---|---|---|
|
||||
| `touch` *(default)* | **nothing** — the recorder holds the rest pose all take | how far a finger closes, from how hard you press it |
|
||||
| `position` | drive the hand for real | the finger's measured angle |
|
||||
| `external` | nothing — the recorder publishes no hand commands at all | the angle reached by the `:8088` sliders |
|
||||
| `follow` | only `f` and the shape keys reach the hand | the angle you push a finger into |
|
||||
|
||||
The panel greys out keys the current mode ignores and says why, so a dead button is never a
|
||||
mystery. Note `[` and `;` also un-park thumb_rot, while `o` returns it to tucked.
|
||||
|
||||
### The take library
|
||||
|
||||
Per take: **▶ replay · ⬇ download · ⧉ duplicate · ✎ rename · 🗑 delete**, plus **⬆ Upload**
|
||||
(validated: the first line must be the recorder's own meta header) and **🗑 Delete all**.
|
||||
`arm_home.jsonl` is hidden and protected — it is the home pose every take returns through,
|
||||
not a recording.
|
||||
|
||||
Takes live on the **host** at `~/hand_data/DataG1`, bind-mounted into the container.
|
||||
`docker/run.sh` begins with `docker rm -f`, so anything kept inside the image would be
|
||||
destroyed on every restart.
|
||||
|
||||
---
|
||||
|
||||
## Where things are
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Workstation (canonical source) | `~/Robotics_workspace/yslootahtech/Project/G1/DFX_inspire_service` |
|
||||
| Robot | `~/DFX_inspire_service` |
|
||||
| In the container | `/opt/hand` (service + dashboard) · `/opt/recorder` (recorder + `DataG1`) |
|
||||
| Host data (survives rebuilds) | `~/hand_data` — `hand_poses.txt`, `hand_combos.json`, `DataG1/` |
|
||||
|
||||
```
|
||||
inspire_g1 RS-485 -> both hands, publishes rt/inspire/state
|
||||
hand_bridge TCP 127.0.0.1:7799 -> rt/inspire/cmd, plus the force-follow loop at 30Hz
|
||||
hand_web.py the dashboard on :8088, and it spawns the recorder
|
||||
```
|
||||
|
||||
All three run inside the single `inspire-hand` container (`--network host --privileged
|
||||
-v /dev:/dev` — DDS needs the host network, the CH340 adapters re-enumerate).
|
||||
|
||||
### What is in the image
|
||||
|
||||
Self-contained from a clean checkout: `recorder/` (the recorder + home pose),
|
||||
`vendor/unitree_sdk2_python/`, `web/`, `example/`, `include/`.
|
||||
|
||||
The build still reads three things from the **robot's own system install**, because they are
|
||||
compiled libraries rather than source:
|
||||
|
||||
- `~/unitree_sdk2` — the C++ static lib the binaries link against
|
||||
- `/usr/local/{include,lib}` — CycloneDDS headers and runtime
|
||||
- `~/cyclonedds/install/include/idl` — IDL headers; the Python `cyclonedds` wheel compiles a
|
||||
`_idlpy` extension against them, and a normal CycloneDDS install does not put them in
|
||||
`/usr/local`
|
||||
|
||||
So: **runtime is 100% Docker; building the image needs the robot's SDK.** Override the
|
||||
locations with `UNITREE_SDK2_DIR`, `CYCLONEDDS_SRC`, `RECORDER_SRC`, `UNITREE_SDK2PY_DIR`.
|
||||
|
||||
`web/` is copied in the last layer, so editing the dashboard rebuilds in seconds instead of
|
||||
recompiling every binary.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**`recorder: NOT found`** — the image was built without `recorder/` or `vendor/`. Rebuild:
|
||||
`./start.sh rebuild`.
|
||||
|
||||
**Stop does nothing during a take** — the dashboard was started with SIGINT ignored (any
|
||||
process backgrounded by a non-interactive shell inherits `SIG_IGN`, and it survives `exec`).
|
||||
`hand_web.py` repairs this at startup; if the repair fails the panel says so. Restart it.
|
||||
|
||||
**Fingers don't move (thumb might)** — usually a latched actuator fault from two `inspire_g1`
|
||||
running at once. `./start.sh restart` re-runs `ClearError`. Still stuck: power-cycle the
|
||||
hands (24 V).
|
||||
|
||||
**"Port drift" warning** — the service opened different ttys than are live now; the CH340
|
||||
adapters re-enumerate on the hub. Restart.
|
||||
|
||||
**A finger reads as dead (0 current, no movement)** — its force-sensor zero has drifted past
|
||||
the grip-force limit, so the RH56 refuses to drive it. `inspire_g1` measures the resting
|
||||
offset at startup and raises that hand's limit to clear it; the log names the fingers. The
|
||||
real fix is re-zeroing the sensor with the hand unloaded.
|
||||
|
||||
**`rt/inspire/state` reads all zeros** — cosmetic; the CH340 adapters echo their own TX, so
|
||||
position read-back is unreliable. Commands are unaffected.
|
||||
|
||||
**Two `inspire_g1` instances** — they collide on the RS-485 bus. `docker/run.sh` kills
|
||||
host-native copies before starting the container. Kill with `pkill -x inspire_g1`, never
|
||||
`pkill -f`.
|
||||
|
||||
---
|
||||
|
||||
## Native (non-Docker) path
|
||||
|
||||
Kept for bring-up and debugging; `manage.sh` runs the services directly on the robot
|
||||
(`./manage.sh status|start|restart|dashboard|...`). It needs `./build.sh` first, since the
|
||||
compiled `build/` is not shipped. Do not run it while the container is up — two writers on
|
||||
the RS-485 bus corrupt the hands.
|
||||
|
||||
Serial setup, udev rules and hand-side wiring: [SETUP_G1.md](SETUP_G1.md).
|
||||
Docker specifics: [docker/README.md](docker/README.md).
|
||||
|
||||
---
|
||||
|
||||
## Service protocol (upstream)
|
||||
|
||||
Send `unitree_go::msg::dds::MotorCmds_` to `rt/inspire/cmd`; read
|
||||
`unitree_go::msg::dds::MotorStates_` from `rt/inspire/state`. Only `q` is meaningful —
|
||||
`1.00` = finger open, `0.00` = closed.
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
@ -23,101 +204,11 @@ A(user) --rt/inspire/cmd--> B(H1 or G1)
|
||||
B --rt/inspire/state--> A
|
||||
```
|
||||
|
||||
The IDL data is an array containing joint-level values for all 12 motors of both hands.
|
||||
Currently the dexterous hand only supports joint control, i.e. only the parameter `q` makes sense in the idl format. The others are reserved.
|
||||
| id | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
| hand | right | right | right | right | right | right | left | left | left | left | left | left |
|
||||
| joint | pinky | ring | middle | index | thumb-bend | thumb-rot | pinky | ring | middle | index | thumb-bend | thumb-rot |
|
||||
|
||||
|
||||
<div style="text-align: center;">
|
||||
<table border="1">
|
||||
<tr>
|
||||
<td>Id</td>
|
||||
<td>0</td>
|
||||
<td>1</td>
|
||||
<td>2</td>
|
||||
<td>3</td>
|
||||
<td>4</td>
|
||||
<td>5</td>
|
||||
<td>6</td>
|
||||
<td>7</td>
|
||||
<td>8</td>
|
||||
<td>9</td>
|
||||
<td>10</td>
|
||||
<td>11</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">Joint</td>
|
||||
<td colspan="6">Right Hand</td>
|
||||
<td colspan="6">Left Hand</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pinky</td>
|
||||
<td>ring</td>
|
||||
<td>middle</td>
|
||||
<td>index</td>
|
||||
<td>thumb-bend</td>
|
||||
<td>thumb-rotation</td>
|
||||
<td>pinky</td>
|
||||
<td>ring</td>
|
||||
<td>middle</td>
|
||||
<td>index</td>
|
||||
<td>thumb-bend</td>
|
||||
<td>thumb-rotation</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
# 2. 🚀 Launch
|
||||
|
||||
## unitree h1
|
||||
```bash
|
||||
sudo apt install libboost-all-dev libspdlog-dev
|
||||
# Build project
|
||||
mkdir build & cd build
|
||||
cmake ..
|
||||
make -j6
|
||||
# Terminal 1. Run h1 inspire hand service
|
||||
sudo ./inspire_h1 -s /dev/ttyUSB0
|
||||
# Terminal 2. Run example
|
||||
./hand_example
|
||||
```
|
||||
|
||||
## unitree g1
|
||||
```bash
|
||||
sudo apt install libboost-all-dev libspdlog-dev
|
||||
# Build project
|
||||
mkdir build & cd build
|
||||
cmake ..
|
||||
make -j6
|
||||
# Terminal 1. Run g1 inspire hand service
|
||||
# The serial port name is hard-coded; if it doesn’t match your setup, please edit it directly in the source.
|
||||
sudo ./inspire_g1
|
||||
# Terminal 2. Run example
|
||||
./hand_example
|
||||
```
|
||||
|
||||
# FAQ
|
||||
1. Error when `make -j6`
|
||||
```bash
|
||||
...
|
||||
/usr/bin/ld: inspire_ctrl.cpp:(.text._Z14serialize_intoIN10unitree_go3msg4dds_12MotorStates_EN3org7eclipse10cyclonedds4core3cdr14xcdr_v2_streamEEbPvmRKT_b[_Z14serialize_intoIN10unitree_go3msg4dds_12MotorStates_EN3org7eclipse10cyclonedds4core3cdr14xcdr_v2_streamEEbPvmRKT_b]+0x2be): undefined reference to `org::eclipse::cyclonedds::core::cdr::xcdr_v2_stream::finish_member(org::eclipse::cyclonedds::core::cdr::entity_properties&, bool)'
|
||||
/usr/bin/ld: inspire_ctrl.cpp:(.text._Z14serialize_intoIN10unitree_go3msg4dds_12MotorStates_EN3org7eclipse10cyclonedds4core3cdr14xcdr_v2_streamEEbPvmRKT_b[_Z14serialize_intoIN10unitree_go3msg4dds_12MotorStates_EN3org7eclipse10cyclonedds4core3cdr14xcdr_v2_streamEEbPvmRKT_b]+0x2d9): undefined reference to `org::eclipse::cyclonedds::core::cdr::xcdr_v2_stream::finish_struct(org::eclipse::cyclonedds::core::cdr::entity_properties&)'
|
||||
|
||||
```
|
||||
please compile and install `unitree_sdk2`:
|
||||
```bash
|
||||
cd ~
|
||||
git clone https://github.com/unitreerobotics/unitree_sdk2
|
||||
cd unitree_sdk2
|
||||
mkdir build & cd build
|
||||
cmake ..
|
||||
sudo make install
|
||||
```
|
||||
2. Error when run `sudo ./inspire_h1 -s /dev/ttyUSB0` or `sudo ./inspire_g1`
|
||||
```bash
|
||||
--- Unitree Robotics ---
|
||||
Inspire Hand Controller
|
||||
Open serial port /dev/ttyUSB* failed
|
||||
```
|
||||
For **Unitree h1**, use the `-s` parameter to change the serial port name.
|
||||
For **Unitree g1**, modify the serial port name directly in the source code.
|
||||
`hand_bridge` also serves this over TCP on `127.0.0.1:7799` (`S` = state+force, `R` = state,
|
||||
`F` = force-follow), which is how the dashboard talks to the hands without a DDS stack of its
|
||||
own.
|
||||
|
||||
104
SETUP_G1.md
Normal file
104
SETUP_G1.md
Normal file
@ -0,0 +1,104 @@
|
||||
# Inspire RH56 dual-hand bring-up on Unitree G1 (PC2)
|
||||
|
||||
Setup notes specific to **this** robot. Upstream README assumes a clean
|
||||
`unitree_sdk2` install in `/usr/local` and hard-codes `/dev/ttyUSB1`+`/dev/ttyUSB2`;
|
||||
neither holds here, so we adjust as below.
|
||||
|
||||
Canonical (workstation): `…/yslootahtech/Project/G1/DFX_inspire_service`
|
||||
Deploy to PC2 `unitree@192.168.123.164:~/DFX_inspire_service` via `rsync`, then `./build.sh`.
|
||||
(wifi `10.255.254.86` is flaky; the eth0 IP `192.168.123.164` is the reliable path.)
|
||||
|
||||
## 0. Easiest way to drive everything — `manage.sh`
|
||||
```bash
|
||||
./manage.sh # status: service + devices + adapters
|
||||
./manage.sh start|stop|restart
|
||||
./manage.sh open|close|box|menu # fingers only
|
||||
./manage.sh like|handshake|thumbup # arm + hand (ARM MOVES)
|
||||
./manage.sh arm "shake hand" # built-in arm action; armlist to list
|
||||
./manage.sh help
|
||||
```
|
||||
It keeps exactly **one** `inspire_g1` running (duplicates corrupt the RS-485 bus) and
|
||||
auto-starts the service for gesture commands.
|
||||
|
||||
## Architecture (unchanged from upstream)
|
||||
`hand_example`/your app → DDS topic `rt/inspire/cmd` (`MotorCmds_`, 12 motors:
|
||||
0–5 right, 6–11 left) → **`inspire_g1`** → RS-485 (CH340 USB adapters, 115200 8N1,
|
||||
Inspire slave id 1) → hands. State flows back on `rt/inspire/state`.
|
||||
Finger order per hand: pinky, ring, middle, index, thumb-bend, thumb-rotation.
|
||||
`q` ∈ [0,1]: **0 = closed, 1 = open**.
|
||||
|
||||
## 1. Build (no system changes)
|
||||
`unitree_sdk2` in `/usr/local` is stale (no go2 IDL). `build.sh` links against the
|
||||
newer `~/unitree_sdk2` source tree instead:
|
||||
```bash
|
||||
cd ~/DFX_inspire_service
|
||||
./build.sh # -> build/inspire_g1, inspire_h1, hand_example
|
||||
```
|
||||
|
||||
## 2. Stable serial names + no-sudo access (one-time, needs sudo)
|
||||
Both hand adapters are CH340s with identical USB serial, so we pin names by
|
||||
physical port and grant access via udev:
|
||||
```bash
|
||||
sudo cp ~/DFX_inspire_service/udev/99-inspire-hands.rules /etc/udev/rules.d/
|
||||
sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
ls -l /dev/inspire_right /dev/inspire_left # both should now exist
|
||||
```
|
||||
`inspire_g1.cpp` opens `/dev/inspire_right` + `/dev/inspire_left`.
|
||||
Mapping (corrected after live test): right → USB port `1-2.2.1.1`, left → `1-2.2.3`.
|
||||
|
||||
## 3. Run + test
|
||||
```bash
|
||||
cd ~/DFX_inspire_service/build
|
||||
./inspire_g1 # Terminal 1 (no sudo needed after the udev rule)
|
||||
./hand_example # Terminal 2 -> both hands open/close ~1 Hz
|
||||
```
|
||||
Stop with Ctrl+C in each. If a hand doesn't move: check 24 V power, RS-485 A/B
|
||||
polarity, and that the hand is at Inspire slave id 1.
|
||||
|
||||
## Record / replay panel (dashboard)
|
||||
|
||||
The dashboard's **Record / replay** card runs `g1_record_replay.py` as a child process — the
|
||||
same script as the CLI, so a take made in the browser and one made from a terminal are the
|
||||
same file in `DataG1/`. It needs the recorder present on whatever host serves the dashboard:
|
||||
|
||||
```bash
|
||||
# where g1_record_replay.py lives (searched: ../Manual_Recorder, ~/Manual_Recorder)
|
||||
export RECORDER_DIR=~/Manual_Recorder
|
||||
# an interpreter that can import unitree_sdk2py (on a workstation: the g1_env conda python)
|
||||
export RECORDER_PY=python3
|
||||
./manage.sh dashboard # prints the resolved recorder path, or NOT FOUND
|
||||
```
|
||||
|
||||
The panel starts a take, relays the in-take keys (`o c [ ] ; '`, `f`, and the saved shapes as
|
||||
keys 1-9), answers the recorder's preview/save prompts, and lists `DataG1/` for replay,
|
||||
rename and delete. Two things it works around, both load-bearing:
|
||||
|
||||
- **Keys are paced ~150 ms apart.** The recorder reads them with `select()` + buffered
|
||||
`sys.stdin.read(1)`; a burst lands in Python's buffer, `select()` then reports nothing
|
||||
ready and every key after the first is stranded. Measured: 3 keys 10 ms apart → 2 arrived.
|
||||
- **Stop sends SIGINT, and the dashboard repairs SIGINT first.** A process backgrounded by a
|
||||
non-interactive shell inherits `SIGINT = SIG_IGN`, which survives `exec` — and `manage.sh`
|
||||
starts the dashboard exactly that way, so without the repair Stop would silently do
|
||||
nothing. The panel shows a warning if the repair did not hold. SIGINT (not SIGKILL) is
|
||||
what lets the recorder walk the arm home and release it.
|
||||
|
||||
Replay and preview **move the arm** and both require an explicit confirmation. Starting a
|
||||
take disarms force-follow, since the bridge and the recorder would otherwise both publish
|
||||
`rt/inspire/cmd` every frame.
|
||||
|
||||
## If you move an adapter to a different USB socket
|
||||
The udev `KERNELS` value changes. Re-discover and update the rule:
|
||||
```bash
|
||||
udevadm info -a -n /dev/ttyUSB0 | grep -m1 'KERNELS=="[0-9]'
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
- **`/dev/inspire_*` missing / no CH340 in `lsusb`** → the hand USB-RS485 adapters are
|
||||
unplugged (or robot rebooted with them out). Re-plug them; udev recreates the names.
|
||||
- **Fingers don't move (thumb might)** → usually a latched actuator fault from running
|
||||
two `inspire_g1` at once. `inspire_g1` now runs `ClearError` + sets speed/force on
|
||||
startup; `./manage.sh restart` re-applies it. If still stuck, power-cycle the hands (24 V).
|
||||
- **Two `inspire_g1` instances** → they collide on the serial bus; `./manage.sh status`
|
||||
flags it, `restart` fixes it. Kill with `pkill -x inspire_g1` (never `pkill -f`).
|
||||
- **`rt/inspire/state` reads all-zeros** → cosmetic; CH340 adapters echo their TX so
|
||||
position read-back is unreliable. Does not affect commands sent to the hand.
|
||||
29
build.sh
Executable file
29
build.sh
Executable file
@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build DFX_inspire_service on the G1 onboard PC (PC2 / Jetson, aarch64).
|
||||
#
|
||||
# Why the extra flags: the factory unitree_sdk2 installed in /usr/local is stale
|
||||
# and lacks the go2 IDL headers (MotorCmds_/MotorStates_) + matching symbols.
|
||||
# We point the compiler/linker at the newer unitree_sdk2 source tree instead,
|
||||
# without touching /usr/local (no `sudo make install`).
|
||||
#
|
||||
# Override the SDK location with: UNITREE_SDK2_DIR=/path/to/unitree_sdk2 ./build.sh
|
||||
set -euo pipefail
|
||||
|
||||
SDK="${UNITREE_SDK2_DIR:-$HOME/unitree_sdk2}"
|
||||
ARCH="$(uname -m)" # aarch64 on the G1 Jetson
|
||||
|
||||
if [ ! -f "${SDK}/lib/${ARCH}/libunitree_sdk2.a" ]; then
|
||||
echo "ERROR: unitree_sdk2 not found at ${SDK} (expected ${SDK}/lib/${ARCH}/libunitree_sdk2.a)" >&2
|
||||
echo " Set UNITREE_SDK2_DIR to the unitree_sdk2 source tree." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
mkdir -p build && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_CXX_FLAGS="-I${SDK}/include" \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-L${SDK}/lib/${ARCH}"
|
||||
make -j"$(nproc)"
|
||||
|
||||
echo
|
||||
echo "Built: $(pwd)/inspire_g1 inspire_h1 hand_example"
|
||||
70
docker/Dockerfile
Normal file
70
docker/Dockerfile
Normal file
@ -0,0 +1,70 @@
|
||||
# Inspire hand service + web dashboard, self-contained (aarch64 / Jetson).
|
||||
# Build context is assembled by build_image.sh (pulls unitree_sdk2 + CycloneDDS
|
||||
# from the robot). Run with: --network host --privileged -v /dev:/dev
|
||||
FROM arm64v8/ubuntu:20.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive TZ=UTC
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential cmake \
|
||||
libboost-all-dev libspdlog-dev libeigen3-dev \
|
||||
python3 python3-flask \
|
||||
iproute2 procps ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# CycloneDDS (ddscxx + iceoryx) headers & runtime libs from the robot's /usr/local
|
||||
COPY deps/usr_local_include/ /usr/local/include/
|
||||
COPY deps/usr_local_lib/ /usr/local/lib/
|
||||
RUN ldconfig
|
||||
|
||||
# unitree_sdk2 headers + prebuilt static lib (for build.sh linking)
|
||||
COPY deps/unitree_sdk2/ /opt/unitree_sdk2/
|
||||
|
||||
# Record/replay panel: the recorder is a python child process that speaks DDS itself, so
|
||||
# the image needs the bindings as well as the script. Skipped cleanly when build_image.sh
|
||||
# could not find the sources (empty dirs) — the panel then reports "recorder not found".
|
||||
# NOTE: this layer pip-installs, so the robot needs network access at BUILD time. Offline
|
||||
# alternative: copy the robot's own site-packages in the same way the C libs are copied.
|
||||
COPY deps/recorder/ /opt/recorder/
|
||||
COPY deps/unitree_sdk2_python/ /opt/unitree_sdk2_python/
|
||||
# cyclonedds is pinned to what unitree_sdk2py demands (0.10.2) — installing anything else
|
||||
# just gets downgraded when the SDK lands. It is built from sdist here, so it compiles
|
||||
# against the robot's own CycloneDDS headers (0.10.5) and links its libddsc.
|
||||
ARG CYCLONEDDS_PY=0.10.2
|
||||
ENV CYCLONEDDS_HOME=/usr/local
|
||||
# The SDK is COPIED into dist-packages rather than pip-installed, and both alternatives
|
||||
# were tried on the robot first:
|
||||
# * a wheel install loses four subpackages — b2, comm, g1, h1 ship with no __init__.py,
|
||||
# so find_packages() drops them and the package's own
|
||||
# `from . import idl, utils, core, rpc, go2, b2` dies with "cannot import name 'b2'";
|
||||
# * `pip install -e` reports success (runs setup.py develop) but never lands on sys.path
|
||||
# in this image — the very next line still gets "No module named 'unitree_sdk2py'".
|
||||
# A copy is deterministic and keeps every subdirectory, including the ones that resolve as
|
||||
# implicit namespace packages. numpy comes from apt; opencv-python (its other declared
|
||||
# dependency, ~100MB+) is skipped because nothing in the SDK imports cv2 — verified.
|
||||
# The destination is derived from the freshly-installed cyclonedds rather than from
|
||||
# sysconfig: on Debian/Ubuntu sysconfig's purelib is /usr/lib/python3.8/site-packages,
|
||||
# which is not even on sys.path (it is dist-packages here), so the copy landed nowhere.
|
||||
RUN if [ -d /opt/unitree_sdk2_python/unitree_sdk2py ]; then \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
python3-pip python3-dev python3-numpy && \
|
||||
pip3 install --no-cache-dir "cyclonedds==${CYCLONEDDS_PY}" && \
|
||||
cp -r /opt/unitree_sdk2_python/unitree_sdk2py \
|
||||
"$(python3 -c 'import cyclonedds,os;print(os.path.dirname(os.path.dirname(cyclonedds.__file__)))')/" && \
|
||||
python3 -c "import unitree_sdk2py, cyclonedds; print('python DDS ok')" && \
|
||||
rm -rf /var/lib/apt/lists/* ; \
|
||||
else echo "no unitree_sdk2_python in context — record/replay disabled"; fi
|
||||
ENV RECORDER_DIR=/opt/recorder RECORDER_PY=python3
|
||||
|
||||
# the service sources (everything except web/), then build the binaries in-image
|
||||
COPY app/ /opt/hand/
|
||||
WORKDIR /opt/hand
|
||||
RUN chmod +x build.sh docker/start.sh manage.sh 2>/dev/null; \
|
||||
UNITREE_SDK2_DIR=/opt/unitree_sdk2 ./build.sh
|
||||
|
||||
# The dashboard goes in LAST, on purpose: it is the part that changes every other day, and
|
||||
# from here a redeploy is a seconds-long layer copy instead of a full C++ recompile.
|
||||
COPY app_web/ /opt/hand/web/
|
||||
|
||||
ENV HAND_REPO=/opt/hand
|
||||
EXPOSE 8088
|
||||
CMD ["/opt/hand/docker/start.sh"]
|
||||
57
docker/README.md
Normal file
57
docker/README.md
Normal file
@ -0,0 +1,57 @@
|
||||
# Dockerized Inspire hand service + dashboard
|
||||
|
||||
One self-contained image (aarch64) running `inspire_g1` + `hand_bridge` + the Flask
|
||||
dashboard. Build ON the robot (it pulls `unitree_sdk2` + CycloneDDS from the host).
|
||||
|
||||
## Build (once, on the robot)
|
||||
```bash
|
||||
cd ~/DFX_inspire_service
|
||||
./docker/build_image.sh # assembles context + docker build -> inspire-hand:latest
|
||||
```
|
||||
|
||||
## Run
|
||||
```bash
|
||||
./docker/run.sh # or: docker compose -f docker/docker-compose.yml up -d
|
||||
# dashboard -> http://<robot-ip>:8088
|
||||
./docker/stop.sh
|
||||
```
|
||||
|
||||
`run.sh` first stops any host-native `inspire_g1`/`hand_bridge` — running both the
|
||||
container and the host service would put **two writers on the RS-485 bus** and
|
||||
corrupt the hands.
|
||||
|
||||
## Why these flags
|
||||
- `--network host` — CycloneDDS (rt/inspire/cmd) and the arm actions (rt/arm_sdk,
|
||||
reaching the G1 motion controller on eth0) need the host network.
|
||||
- `--privileged -v /dev:/dev` — the CH340 `ttyUSB*` adapters re-enumerate on the hub;
|
||||
mounting `/dev` + privileged lets the in-container dynamic detection find them.
|
||||
- `IFACE=eth0` — interface for arm actions (must be eth0). Fingers work on either.
|
||||
|
||||
## Record / replay in the image
|
||||
The dashboard's Record/Replay card runs `g1_record_replay.py` as a child process, so the
|
||||
image needs the script **and** a python that can import `unitree_sdk2py`. `build_image.sh`
|
||||
pulls both into the context:
|
||||
|
||||
```bash
|
||||
RECORDER_SRC=~/Manual_Recorder \
|
||||
UNITREE_SDK2PY_DIR=~/unitree_sdk2_python \
|
||||
./docker/build_image.sh
|
||||
```
|
||||
|
||||
Neither is required — leave them out and the image still builds, with the panel reporting
|
||||
*"recorder not found"*. `start.sh` prints which case you got.
|
||||
|
||||
- **That layer pip-installs (`cyclonedds`, `unitree_sdk2py`), so the robot needs network at
|
||||
BUILD time.** Offline alternative: copy the robot's own python site-packages into the
|
||||
image the same way `build_image.sh` copies the C libs.
|
||||
- **Takes are a host volume** — `run.sh` mounts `$HAND_DATA_DIR/DataG1` to
|
||||
`/opt/recorder/DataG1`, because `run.sh` starts with `docker rm -f` and would otherwise
|
||||
destroy every recording ever made.
|
||||
- **`arm_home.jsonl` is seeded on first start**, not baked into `DataG1/` — the bind-mount
|
||||
would hide a baked copy, and without it every take skips its return-to-home. It is hidden
|
||||
from the takes list and cannot be deleted from the panel: it is a home pose, not a take.
|
||||
|
||||
## Notes
|
||||
- Sudo/udev not needed inside the container (privileged).
|
||||
- Saved poses/combos persist via `-v $HAND_DATA_DIR:/opt/hand/data` + `HAND_DATA` (set by
|
||||
`run.sh`). They used to live in the image and were wiped by every rebuild.
|
||||
80
docker/build_image.sh
Executable file
80
docker/build_image.sh
Executable file
@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
# Assemble the build context (pull unitree_sdk2 + CycloneDDS from this robot) and
|
||||
# build the self-contained image. Run ON the robot (aarch64).
|
||||
# ./docker/build_image.sh
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)" # .../DFX_inspire_service/docker
|
||||
REPO="$(dirname "$HERE")" # .../DFX_inspire_service
|
||||
SDK="${UNITREE_SDK2_DIR:-$HOME/unitree_sdk2}"
|
||||
CTX="$HERE/.ctx"
|
||||
IMG="${IMG:-inspire-hand:latest}"
|
||||
|
||||
[ -f "$SDK/lib/aarch64/libunitree_sdk2.a" ] || { echo "ERROR: unitree_sdk2 not at $SDK"; exit 1; }
|
||||
|
||||
echo ">> assembling build context in $CTX"
|
||||
rm -rf "$CTX"
|
||||
mkdir -p "$CTX/deps/usr_local_include" "$CTX/deps/usr_local_lib" "$CTX/deps/unitree_sdk2" "$CTX/app"
|
||||
|
||||
# unitree_sdk2 headers + static lib
|
||||
cp -r "$SDK/include" "$CTX/deps/unitree_sdk2/"
|
||||
cp -r "$SDK/lib" "$CTX/deps/unitree_sdk2/"
|
||||
|
||||
# CycloneDDS headers: C (dds, ddsc), C++ (ddscxx) and iceoryx
|
||||
for d in dds ddsc ddscxx iceoryx; do cp -r "/usr/local/include/$d" "$CTX/deps/usr_local_include/"; done
|
||||
|
||||
# The IDL headers (idl/, idlc/) are needed ONLY by the python binding: pip building
|
||||
# cyclonedds compiles a _idlpy extension against idl/retcode.h, and `make install` of the
|
||||
# C++ side does not put them in /usr/local/include. Without them the image build dies at
|
||||
# idlpy/src/context.h:17: fatal error: idl/retcode.h: No such file or directory
|
||||
# CYCLONEDDS_SRC points at the checkout whose install/ prefix has them (0.10.5 here).
|
||||
CDDS_SRC="${CYCLONEDDS_SRC:-$HOME/cyclonedds}"
|
||||
for d in idl idlc; do
|
||||
if [ -d "/usr/local/include/$d" ]; then cp -r "/usr/local/include/$d" "$CTX/deps/usr_local_include/"
|
||||
elif [ -d "$CDDS_SRC/install/include/$d" ]; then cp -r "$CDDS_SRC/install/include/$d" "$CTX/deps/usr_local_include/"
|
||||
fi
|
||||
done
|
||||
# CycloneDDS shared runtime libs
|
||||
cp -P /usr/local/lib/libddsc* /usr/local/lib/libddscxx* \
|
||||
/usr/local/lib/libcyclonedds* /usr/local/lib/libdds_security_* \
|
||||
"$CTX/deps/usr_local_lib/" 2>/dev/null || true
|
||||
|
||||
# The app, with web/ split into its own context dir. The Dockerfile copies web/ AFTER the
|
||||
# C++ build, so editing the dashboard rebuilds in seconds instead of recompiling every
|
||||
# binary — and the dashboard is what changes most often.
|
||||
rsync -a --exclude 'build/' --exclude 'docker/.ctx/' --exclude 'web/' "$REPO/" "$CTX/app/"
|
||||
rsync -a "$REPO/web/" "$CTX/app_web/"
|
||||
cp "$HERE/Dockerfile" "$CTX/Dockerfile"
|
||||
|
||||
# ---- recorder for the dashboard's Record/Replay panel ---------------------------------
|
||||
# The panel runs g1_record_replay.py as a CHILD PROCESS, so the script and a python that
|
||||
# can import unitree_sdk2py both have to be inside the image. Both dirs are always created
|
||||
# (empty is fine) because the Dockerfile COPYs them unconditionally — with an empty one the
|
||||
# image still builds and the panel simply reports "recorder not found".
|
||||
# Both live IN this project (recorder/ and vendor/), so a clean checkout builds a complete
|
||||
# image with no environment set and nothing fetched from elsewhere on the machine. The env
|
||||
# vars remain as overrides for anyone pointing at their own working copy.
|
||||
REC="${RECORDER_SRC:-$REPO/recorder}"
|
||||
SDKPY="${UNITREE_SDK2PY_DIR:-$REPO/vendor/unitree_sdk2_python}"
|
||||
mkdir -p "$CTX/deps/recorder/seed" "$CTX/deps/unitree_sdk2_python"
|
||||
if [ -f "$REC/g1_record_replay.py" ] && [ -f "$SDKPY/setup.py" ]; then
|
||||
cp "$REC/g1_record_replay.py" "$CTX/deps/recorder/"
|
||||
# The home pose is seeded rather than shipped in DataG1/, because run.sh bind-mounts
|
||||
# DataG1 over the top and would hide anything baked there.
|
||||
for h in "$REC/arm_home.jsonl" "$REC/DataG1/arm_home.jsonl"; do
|
||||
[ -f "$h" ] && { cp "$h" "$CTX/deps/recorder/seed/"; break; }
|
||||
done
|
||||
rsync -a --exclude '.git/' --exclude '*.egg-info/' "$SDKPY/" "$CTX/deps/unitree_sdk2_python/"
|
||||
echo ">> recorder included: $REC + unitree_sdk2py: $SDKPY"
|
||||
else
|
||||
echo ">> NOTE: record/replay panel will be DISABLED in this image."
|
||||
[ -f "$REC/g1_record_replay.py" ] || echo " missing $REC/g1_record_replay.py (set RECORDER_SRC)"
|
||||
[ -f "$SDKPY/setup.py" ] || echo " missing $SDKPY/setup.py (set UNITREE_SDK2PY_DIR)"
|
||||
fi
|
||||
|
||||
echo ">> docker build -t $IMG (this compiles the binaries in-image; takes a few min)"
|
||||
cd "$CTX"
|
||||
docker build -t "$IMG" .
|
||||
rm -rf "$CTX"
|
||||
echo ">> done: $IMG"
|
||||
echo " run with: $REPO/docker/run.sh"
|
||||
18
docker/docker-compose.yml
Normal file
18
docker/docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
||||
# Run the pre-built image (build first: ./docker/build_image.sh).
|
||||
# docker compose -f docker/docker-compose.yml up -d
|
||||
services:
|
||||
inspire-hand:
|
||||
image: inspire-hand:latest
|
||||
container_name: inspire-hand
|
||||
network_mode: host # CycloneDDS + arm actions need the host network (eth0)
|
||||
privileged: true # + /dev mount so the container sees the CH340 ttyUSB*
|
||||
volumes:
|
||||
- /dev:/dev
|
||||
# Compose does NOT expand a bare ~ in a volume path (it would create a directory
|
||||
# literally named "~"), so the default goes through $HOME.
|
||||
- ${HAND_DATA_DIR:-${HOME}/hand_data}:/opt/hand/data # shapes + combos
|
||||
- ${HAND_DATA_DIR:-${HOME}/hand_data}/DataG1:/opt/recorder/DataG1 # takes
|
||||
environment:
|
||||
- IFACE=eth0
|
||||
- HAND_DATA=/opt/hand/data
|
||||
restart: unless-stopped
|
||||
42
docker/run.sh
Executable file
42
docker/run.sh
Executable file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
# Run the containerized hand stack (service + bridge + dashboard).
|
||||
# Stops any host-native inspire_g1/bridge first — two services would collide on
|
||||
# the RS-485 bus. Needs --network host (DDS) + --privileged -v /dev:/dev (serial).
|
||||
set -e
|
||||
IMG="${IMG:-inspire-hand:latest}"
|
||||
IFACE="${IFACE:-eth0}"
|
||||
|
||||
echo ">> removing old container, then killing host-native services (avoid double inspire_g1)"
|
||||
docker rm -f inspire-hand 2>/dev/null || true # kill container's procs first
|
||||
pkill -x inspire_g1 2>/dev/null || true # now only host natives remain
|
||||
pkill -x hand_bridge 2>/dev/null || true
|
||||
pkill -f hand_web.py 2>/dev/null || true
|
||||
sleep 1; pkill -9 -x inspire_g1 2>/dev/null || true
|
||||
|
||||
# INSPIRE_RIGHT_PATH pins which physical USB socket is the RIGHT hand. Both hands answer on
|
||||
# RS-485 id 1, so without this the side is inferred from USB path ORDER — correct today, but
|
||||
# it would flip undetected if the two dongles were swapped between sockets.
|
||||
# Operator-verified at the robot 2026-08-03: usb 1-2.2.1.1 is the physical RIGHT hand.
|
||||
# (An earlier wiggle test concluded the opposite; the operator watching the robot corrected
|
||||
# it. Flip this one value if the sides ever read swapped again — nothing else needs changing.)
|
||||
RIGHT_PATH="${INSPIRE_RIGHT_PATH:-1-2.2.1.1}"
|
||||
# Saved shapes/combos on the HOST, so rebuilding the image no longer wipes the library.
|
||||
DATA_DIR="${HAND_DATA_DIR:-$HOME/hand_data}"
|
||||
# Recordings live on the HOST for the same reason the shape library does: a `docker rm -f`
|
||||
# in this script would otherwise destroy every take ever made.
|
||||
mkdir -p "$DATA_DIR" "$DATA_DIR/DataG1"
|
||||
|
||||
docker run -d --name inspire-hand --restart unless-stopped \
|
||||
--network host --privileged -v /dev:/dev \
|
||||
-v "$DATA_DIR":/opt/hand/data \
|
||||
-v "$DATA_DIR/DataG1":/opt/recorder/DataG1 \
|
||||
-e HAND_DATA=/opt/hand/data \
|
||||
-e INSPIRE_RIGHT_PATH="$RIGHT_PATH" \
|
||||
-e IFACE="$IFACE" "$IMG"
|
||||
echo ">> right hand pinned to usb $RIGHT_PATH · data dir $DATA_DIR · takes $DATA_DIR/DataG1"
|
||||
|
||||
sleep 4
|
||||
docker logs --tail 24 inspire-hand || true
|
||||
echo ">> inspire_g1 instances (want 1, the container's): $(pgrep -xc inspire_g1)"
|
||||
ip=$(hostname -I | awk '{print $1}')
|
||||
echo ">> dashboard: http://$ip:8088"
|
||||
44
docker/start.sh
Executable file
44
docker/start.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Container entrypoint: supervised inspire_g1 + hand_bridge + Flask dashboard.
|
||||
set -u
|
||||
cd /opt/hand
|
||||
export HAND_REPO=/opt/hand
|
||||
IFACE="${IFACE:-eth0}"
|
||||
echo "[inspire-hand] iface=$IFACE ttyUSB: $(ls /dev/ttyUSB* 2>/dev/null | tr '\n' ' ')"
|
||||
|
||||
# Supervisor: (re)start inspire_g1 whenever the CH340 adapters are present but the
|
||||
# service isn't running. Self-heals across the flaky-hub disconnect/reconnect cycles.
|
||||
(
|
||||
while true; do
|
||||
if ! pgrep -x inspire_g1 >/dev/null 2>&1; then
|
||||
if ls /dev/ttyUSB* >/dev/null 2>&1; then
|
||||
echo "[supervisor] adapters present, starting inspire_g1: $(ls /dev/ttyUSB* | tr '\n' ' ')"
|
||||
./build/inspire_g1 >/tmp/inspire_g1.log 2>&1 &
|
||||
sleep 2
|
||||
sed 's/^/[inspire_g1] /' /tmp/inspire_g1.log
|
||||
fi
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
) &
|
||||
|
||||
# TCP->DDS bridge for the dashboard (stays up regardless; commands no-op if service down)
|
||||
setsid ./build/hand_bridge "$IFACE" 7799 >/tmp/hand_bridge.log 2>&1 </dev/null &
|
||||
sleep 1
|
||||
sed 's/^/[bridge] /' /tmp/hand_bridge.log
|
||||
|
||||
# Seed the arm home pose into the mounted takes dir on first run. run.sh bind-mounts
|
||||
# DataG1 from the host, which hides the copy baked into the image — without this every
|
||||
# take would skip its return-to-home and print "home file not found".
|
||||
if [ -f /opt/recorder/seed/arm_home.jsonl ] && [ ! -f /opt/recorder/DataG1/arm_home.jsonl ]; then
|
||||
mkdir -p /opt/recorder/DataG1 && cp /opt/recorder/seed/arm_home.jsonl /opt/recorder/DataG1/ \
|
||||
&& echo "[inspire-hand] seeded arm_home.jsonl into DataG1"
|
||||
fi
|
||||
if [ -f /opt/recorder/g1_record_replay.py ]; then
|
||||
echo "[inspire-hand] recorder: /opt/recorder ($(ls /opt/recorder/DataG1/*.jsonl 2>/dev/null | grep -vc arm_home) takes)"
|
||||
else
|
||||
echo "[inspire-hand] recorder: NOT in image — record/replay panel disabled"
|
||||
fi
|
||||
|
||||
echo "[inspire-hand] dashboard on :8088"
|
||||
exec python3 web/hand_web.py --port 8088
|
||||
2
docker/stop.sh
Executable file
2
docker/stop.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
docker rm -f inspire-hand 2>/dev/null && echo "inspire-hand stopped" || echo "inspire-hand not running"
|
||||
91
example/arm_action.cpp
Normal file
91
example/arm_action.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @file arm_action.cpp
|
||||
* @brief Trigger Unitree's built-in G1 upper-body actions (shake hand, etc.).
|
||||
*
|
||||
* Uses unitree_sdk2 G1ArmActionClient. The action server drives rt/arm_sdk for
|
||||
* you (balance-aware, Unitree-designed motions) — do NOT run arm_raise at the
|
||||
* same time (error 7400 = rt/arm_sdk occupied).
|
||||
*
|
||||
* ./arm_action list # list actions
|
||||
* ./arm_action "shake hand" # by name
|
||||
* ./arm_action 27 [iface] # by id (default iface: eth0)
|
||||
* ./arm_action "release arm" # = 99, returns the arm to normal
|
||||
*
|
||||
* After most actions the arm HOLDS until you send "release arm" (99).
|
||||
* Actions require the robot FSM id in {500,501,801} (check rt/sportmodestate).
|
||||
*/
|
||||
|
||||
#include "unitree/robot/g1/arm/g1_arm_action_client.hpp"
|
||||
#include "unitree/robot/g1/arm/g1_arm_action_error.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
using namespace unitree::robot::g1;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
std::cout << "Usage: ./arm_action <list | id | \"name\"> [networkInterface]\n";
|
||||
return 1;
|
||||
}
|
||||
std::string action = argv[1];
|
||||
std::string iface = argc > 2 ? argv[2] : "eth0";
|
||||
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
auto client = std::make_shared<G1ArmActionClient>();
|
||||
client->Init();
|
||||
client->SetTimeout(10.f);
|
||||
|
||||
if (action == "list") {
|
||||
std::cout << "Built-in actions (id name):\n";
|
||||
for (const auto &kv : client->action_map)
|
||||
std::cout << " " << kv.second << "\t" << kv.first << "\n";
|
||||
std::string data;
|
||||
if (client->GetActionList(data) == 0)
|
||||
std::cout << "\nServer-reported list:\n" << data << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Resolve action id from a number or a name.
|
||||
int32_t id = 0;
|
||||
try {
|
||||
id = std::stoi(action);
|
||||
} catch (const std::exception &) {
|
||||
auto it = client->action_map.find(action);
|
||||
if (it == client->action_map.end()) {
|
||||
std::cerr << "Unknown action '" << action << "'. Try: ./arm_action list\n";
|
||||
return 1;
|
||||
}
|
||||
id = it->second;
|
||||
}
|
||||
|
||||
std::cout << "Executing action id " << id << " ..." << std::endl;
|
||||
int32_t ret = client->ExecuteAction(id);
|
||||
if (ret == 0) {
|
||||
std::cout << "OK. (Arm holds until you send \"release arm\" / 99.)" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case UT_ROBOT_ARM_ACTION_ERR_ARMSDK:
|
||||
std::cerr << "Error 7400: " << UT_ROBOT_ARM_ACTION_ERR_ARMSDK_DESC
|
||||
<< " (something else holds rt/arm_sdk — e.g. arm_raise)." << std::endl;
|
||||
break;
|
||||
case UT_ROBOT_ARM_ACTION_ERR_HOLDING:
|
||||
std::cerr << "Error 7401: " << UT_ROBOT_ARM_ACTION_ERR_HOLDING_DESC << std::endl;
|
||||
break;
|
||||
case UT_ROBOT_ARM_ACTION_ERR_INVALID_ACTION_ID:
|
||||
std::cerr << "Error 7402: " << UT_ROBOT_ARM_ACTION_ERR_INVALID_ACTION_ID_DESC << std::endl;
|
||||
break;
|
||||
case UT_ROBOT_ARM_ACTION_ERR_INVALID_FSM_ID:
|
||||
std::cerr << "Error 7404: invalid FSM id. Actions need fsm id {500,501,801} "
|
||||
"(check rt/sportmodestate; in 801 only fsm mode {0,3})." << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Execute action failed, error code: " << ret << std::endl;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
170
example/arm_raise.cpp
Normal file
170
example/arm_raise.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/**
|
||||
* @file arm_raise.cpp
|
||||
* @brief SAFE standalone test: raise the G1 RIGHT arm via the arm_sdk interface.
|
||||
*
|
||||
* Based on unitree_sdk2 example g1_arm7_sdk_dds_example.cpp, hardened for safety:
|
||||
* - aborts if rt/lowstate is not received (never commands from bogus zeros)
|
||||
* - ENTER-gated phases (engage -> raise -> lower)
|
||||
* - Ctrl+C ramps the blend weight to 0 (gracefully hands the arm back)
|
||||
*
|
||||
* Moves ONLY the right arm; left arm + waist are held at their measured pose.
|
||||
*
|
||||
* ./arm_raise [networkInterface] (default: eth0)
|
||||
*
|
||||
* !!! THE ARM PHYSICALLY MOVES. Clear the space, stop any other arm controller,
|
||||
* keep the E-stop in hand. !!!
|
||||
*/
|
||||
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include <unitree/idl/hg/LowCmd_.hpp>
|
||||
#include <unitree/idl/hg/LowState_.hpp>
|
||||
#include <unitree/robot/channel/channel_publisher.hpp>
|
||||
#include <unitree/robot/channel/channel_subscriber.hpp>
|
||||
|
||||
static const std::string kTopicArmSDK = "rt/arm_sdk";
|
||||
static const std::string kTopicState = "rt/lowstate";
|
||||
|
||||
enum JointIndex {
|
||||
kLeftHipPitch, kLeftHipRoll, kLeftHipYaw, kLeftKnee, kLeftAnkle, kLeftAnkleRoll,
|
||||
kRightHipPitch, kRightHipRoll, kRightHipYaw, kRightKnee, kRightAnkle, kRightAnkleRoll,
|
||||
kWaistYaw, kWaistRoll, kWaistPitch,
|
||||
kLeftShoulderPitch, kLeftShoulderRoll, kLeftShoulderYaw, kLeftElbow,
|
||||
kLeftWristRoll, kLeftWristPitch, kLeftWristYaw,
|
||||
kRightShoulderPitch, kRightShoulderRoll, kRightShoulderYaw, kRightElbow,
|
||||
kRightWristRoll, kRightWristPitch, kRightWristYaw,
|
||||
kNotUsedJoint, kNotUsedJoint1, kNotUsedJoint2, kNotUsedJoint3, kNotUsedJoint4, kNotUsedJoint5
|
||||
};
|
||||
|
||||
static std::atomic<bool> g_stop{false};
|
||||
static void onSigint(int) { g_stop = true; }
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const std::string iface = argc > 1 ? argv[1] : "eth0";
|
||||
std::signal(SIGINT, onSigint);
|
||||
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
|
||||
unitree::robot::ChannelPublisherPtr<unitree_hg::msg::dds_::LowCmd_> pub;
|
||||
pub.reset(new unitree::robot::ChannelPublisher<unitree_hg::msg::dds_::LowCmd_>(kTopicArmSDK));
|
||||
pub->InitChannel();
|
||||
|
||||
static unitree_hg::msg::dds_::LowState_ state;
|
||||
std::atomic<bool> got{false};
|
||||
unitree::robot::ChannelSubscriberPtr<unitree_hg::msg::dds_::LowState_> sub;
|
||||
sub.reset(new unitree::robot::ChannelSubscriber<unitree_hg::msg::dds_::LowState_>(kTopicState));
|
||||
sub->InitChannel([&](const void *m) {
|
||||
std::memcpy(&state, m, sizeof(state));
|
||||
got = true;
|
||||
}, 1);
|
||||
|
||||
// SAFETY 1: require fresh state before touching the arm.
|
||||
std::cout << "Waiting for " << kTopicState << " on '" << iface << "' ..." << std::endl;
|
||||
for (int i = 0; i < 300 && !got; i++) std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
if (!got) {
|
||||
std::cerr << "ERROR: no " << kTopicState << " received. Is the robot controller up, and is '"
|
||||
<< iface << "' the interface to the robot? Aborting (no arm command sent)." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const std::array<JointIndex, 17> arm = {
|
||||
kLeftShoulderPitch, kLeftShoulderRoll, kLeftShoulderYaw, kLeftElbow,
|
||||
kLeftWristRoll, kLeftWristPitch, kLeftWristYaw,
|
||||
kRightShoulderPitch, kRightShoulderRoll, kRightShoulderYaw, kRightElbow,
|
||||
kRightWristRoll, kRightWristPitch, kRightWristYaw,
|
||||
kWaistYaw, kWaistRoll, kWaistPitch};
|
||||
const int RIGHT0 = 7; // right arm occupies arm[7..13]
|
||||
|
||||
const float kp = 60.f, kd = 1.5f, dt = 0.02f;
|
||||
const float max_delta = 0.5f * dt; // 0.5 rad/s velocity limit
|
||||
const auto sleep_t = std::chrono::milliseconds(20);
|
||||
|
||||
std::array<float, 17> start{};
|
||||
for (int i = 0; i < 17; i++) start[i] = state.motor_state().at(arm[i]).q();
|
||||
|
||||
// Right-arm raise target [ShPitch, ShRoll, ShYaw, Elbow, WrRoll, WrPitch, WrYaw].
|
||||
// Conservative greeting raise (arm out + forearm up). Tune here.
|
||||
const std::array<float, 7> rraise = {0.0f, -1.0f, 0.0f, 1.4f, 0.0f, 0.0f, 0.0f};
|
||||
std::array<float, 17> target = start;
|
||||
for (int j = 0; j < 7; j++) target[RIGHT0 + j] = rraise[j];
|
||||
|
||||
std::array<float, 17> des = start;
|
||||
float weight = 0.f;
|
||||
unitree_hg::msg::dds_::LowCmd_ msg;
|
||||
|
||||
auto publish = [&](float w) {
|
||||
msg.motor_cmd().at(kNotUsedJoint).q(w);
|
||||
for (int i = 0; i < 17; i++) {
|
||||
auto &mc = msg.motor_cmd().at(arm[i]);
|
||||
mc.q(des[i]); mc.dq(0.f); mc.kp(kp); mc.kd(kd); mc.tau(0.f);
|
||||
}
|
||||
pub->Write(msg);
|
||||
};
|
||||
|
||||
auto release = [&]() {
|
||||
std::cout << "Releasing arm (weight -> 0) ..." << std::endl;
|
||||
while (weight > 0.f) {
|
||||
weight = std::max(0.f, weight - 0.015f);
|
||||
publish(weight);
|
||||
std::this_thread::sleep_for(sleep_t);
|
||||
}
|
||||
publish(0.f);
|
||||
};
|
||||
|
||||
// Move 'des' toward 'goal' (velocity limited). Returns false if interrupted.
|
||||
auto move_to = [&](const std::array<float, 17> &goal, int hold_steps) -> bool {
|
||||
for (int step = 0; step < 600; step++) {
|
||||
if (g_stop) return false;
|
||||
float maxerr = 0.f;
|
||||
for (int i = 0; i < 17; i++) {
|
||||
float d = std::clamp(goal[i] - des[i], -max_delta, max_delta);
|
||||
des[i] += d;
|
||||
maxerr = std::max(maxerr, std::abs(goal[i] - des[i]));
|
||||
}
|
||||
publish(1.f);
|
||||
std::this_thread::sleep_for(sleep_t);
|
||||
if (maxerr < 1e-3f) { // arrived -> hold
|
||||
for (int h = 0; h < hold_steps && !g_stop; h++) {
|
||||
publish(1.f);
|
||||
std::this_thread::sleep_for(sleep_t);
|
||||
}
|
||||
return !g_stop;
|
||||
}
|
||||
}
|
||||
return !g_stop;
|
||||
};
|
||||
|
||||
std::cout << "\n*** G1 RIGHT-ARM RAISE TEST ***\n"
|
||||
<< "The right arm WILL move. Ensure clear space + E-stop ready.\n"
|
||||
<< "Press ENTER to engage the arm (no motion yet) ... " << std::flush;
|
||||
std::cin.get();
|
||||
if (g_stop) { release(); return 0; }
|
||||
|
||||
// Phase 1: engage — ramp weight to 1 while commanding the measured pose (no motion).
|
||||
while (weight < 1.f && !g_stop) {
|
||||
weight = std::min(1.f, weight + 0.015f);
|
||||
publish(weight);
|
||||
std::this_thread::sleep_for(sleep_t);
|
||||
}
|
||||
if (g_stop) { release(); return 0; }
|
||||
|
||||
std::cout << "Engaged. Press ENTER to RAISE the right arm ... " << std::flush;
|
||||
std::cin.get();
|
||||
if (g_stop || !move_to(target, 100)) { release(); return 0; }
|
||||
|
||||
std::cout << "Raised. Press ENTER to LOWER the arm ... " << std::flush;
|
||||
std::cin.get();
|
||||
move_to(start, 25);
|
||||
|
||||
release();
|
||||
std::cout << "Done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
28
example/greet.cpp
Normal file
28
example/greet.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @file greet.cpp
|
||||
* @brief Combined entry point for the fused arm+hand greetings (see also the
|
||||
* standalone ./handshake and ./thumbup binaries).
|
||||
*
|
||||
* ./greet [handshake|thumbup] [networkInterface] (default iface: eth0)
|
||||
*
|
||||
* Needs ./inspire_g1 running for the fingers. The ARM physically moves —
|
||||
* clear space + E-stop ready.
|
||||
*/
|
||||
#include "greet_common.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const std::string what = argc > 1 ? argv[1] : "handshake";
|
||||
const std::string iface = argc > 2 ? argv[2] : "eth0";
|
||||
|
||||
auto arm = greet_init(iface);
|
||||
Hand hand;
|
||||
usleep(300000);
|
||||
|
||||
if (what == "handshake") runHandshake(*arm, hand);
|
||||
else if (what == "thumbup") runThumbup(*arm, hand);
|
||||
else { std::cout << "Usage: ./greet [handshake|thumbup] [networkInterface]\n"; return 1; }
|
||||
|
||||
std::cout << "done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
102
example/greet_common.hpp
Normal file
102
example/greet_common.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @file greet_common.hpp
|
||||
* @brief Shared arm-action + Inspire-hand greeting routines (handshake / thumbup).
|
||||
*
|
||||
* Arm uses Unitree's built-in actions (G1ArmActionClient, balance-aware).
|
||||
* Hand uses the Inspire DDS bridge -> REQUIRES ./inspire_g1 running for fingers.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "unitree/robot/g1/arm/g1_arm_action_client.hpp"
|
||||
#include "unitree/robot/g1/arm/g1_arm_action_error.hpp"
|
||||
#include <unitree/idl/go2/MotorCmds_.hpp>
|
||||
#include <unitree/robot/channel/channel_publisher.hpp>
|
||||
|
||||
#include <eigen3/Eigen/Dense>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
using Vec6 = Eigen::Matrix<float, 6, 1>;
|
||||
|
||||
// Inspire hand command publisher (open-loop; needs inspire_g1 running).
|
||||
class Hand
|
||||
{
|
||||
public:
|
||||
Hand()
|
||||
{
|
||||
pub_ = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>("rt/inspire/cmd");
|
||||
pub_->InitChannel();
|
||||
cmd_.cmds().resize(12);
|
||||
}
|
||||
void set(const Vec6 &right, const Vec6 &left)
|
||||
{
|
||||
for (size_t i = 0; i < 6; i++) { cmd_.cmds()[i].q() = right(i); cmd_.cmds()[i + 6].q() = left(i); }
|
||||
pub_->Write(cmd_);
|
||||
}
|
||||
private:
|
||||
unitree_go::msg::dds_::MotorCmds_ cmd_;
|
||||
unitree::robot::ChannelPublisherPtr<unitree_go::msg::dds_::MotorCmds_> pub_;
|
||||
};
|
||||
|
||||
inline Vec6 gv(float p, float r, float m, float i, float tb, float tr) { Vec6 v; v << p, r, m, i, tb, tr; return v; }
|
||||
inline void ghold(int ms) { usleep(ms * 1000); }
|
||||
|
||||
// q in [0,1], 0=closed 1=open; order pinky,ring,middle,index,thumb_bend,thumb_rot
|
||||
static const Vec6 G_OPEN = gv(1, 1, 1, 1, 1, 1);
|
||||
static const Vec6 G_THUMBUP = gv(0, 0, 0, 0, 1, 1);
|
||||
static const Vec6 G_SHAKE_READY = gv(0.85, 0.85, 0.85, 0.85, 0.85, 0.6);
|
||||
static const Vec6 G_SHAKE_GRIP = gv(0.2, 0.2, 0.2, 0.2, 0.25, 0.1);
|
||||
|
||||
// Execute a built-in arm action; print a helpful message on failure.
|
||||
inline bool arm_do(unitree::robot::g1::G1ArmActionClient &arm, int id, const char *name)
|
||||
{
|
||||
using namespace unitree::robot::g1;
|
||||
std::cout << "arm: " << name << " (" << id << ") ..." << std::endl;
|
||||
int32_t ret = arm.ExecuteAction(id);
|
||||
if (ret != 0) {
|
||||
std::cerr << " arm action '" << name << "' failed, code " << ret;
|
||||
if (ret == UT_ROBOT_ARM_ACTION_ERR_ARMSDK) std::cerr << " (rt/arm_sdk occupied)";
|
||||
else if (ret == UT_ROBOT_ARM_ACTION_ERR_INVALID_FSM_ID) std::cerr << " (need fsm {500,501,801})";
|
||||
else if (ret == UT_ROBOT_ARM_ACTION_ERR_HOLDING) std::cerr << " (arm holding; send release 99)";
|
||||
std::cerr << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// arm reaches out -> hand grips -> thumbs-up -> arm releases
|
||||
inline void runHandshake(unitree::robot::g1::G1ArmActionClient &arm, Hand &hand)
|
||||
{
|
||||
hand.set(G_SHAKE_READY, G_OPEN); // present an open hand
|
||||
if (!arm_do(arm, 27, "shake hand")) { hand.set(G_OPEN, G_OPEN); return; }
|
||||
ghold(300);
|
||||
std::cout << "hand: grip" << std::endl;
|
||||
hand.set(G_SHAKE_GRIP, G_OPEN); ghold(1500);
|
||||
std::cout << "hand: thumbs-up" << std::endl;
|
||||
hand.set(G_THUMBUP, G_OPEN); ghold(1200);
|
||||
hand.set(G_OPEN, G_OPEN); ghold(400);
|
||||
arm_do(arm, 99, "release arm");
|
||||
}
|
||||
|
||||
// raise right hand -> hand thumbs-up -> arm releases
|
||||
inline void runThumbup(unitree::robot::g1::G1ArmActionClient &arm, Hand &hand)
|
||||
{
|
||||
if (!arm_do(arm, 23, "right hand up")) { hand.set(G_OPEN, G_OPEN); return; }
|
||||
ghold(300);
|
||||
std::cout << "hand: thumbs-up" << std::endl;
|
||||
hand.set(G_THUMBUP, G_OPEN); ghold(2500);
|
||||
hand.set(G_OPEN, G_OPEN); ghold(400);
|
||||
arm_do(arm, 99, "release arm");
|
||||
}
|
||||
|
||||
// Shared setup: init DDS + arm client + hand, then return the arm client.
|
||||
inline std::shared_ptr<unitree::robot::g1::G1ArmActionClient> greet_init(const std::string &iface)
|
||||
{
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
auto arm = std::make_shared<unitree::robot::g1::G1ArmActionClient>();
|
||||
arm->Init();
|
||||
arm->SetTimeout(10.f);
|
||||
return arm;
|
||||
}
|
||||
208
example/hand_bridge.cpp
Normal file
208
example/hand_bridge.cpp
Normal file
@ -0,0 +1,208 @@
|
||||
/**
|
||||
* @file hand_bridge.cpp
|
||||
* @brief Local TCP <-> DDS bridge for the web dashboard.
|
||||
* - "v0 v1 ... v11\n" -> publish MotorCmds_ to rt/inspire/cmd (q in [0,1], or <0 = release)
|
||||
* - "R\n" -> reply with the 12 latest rt/inspire/state q values (read-back / capture)
|
||||
* - "S\n" -> reply with 24 values: 12 angles then 12 forces (joint tracker)
|
||||
* Persistent publisher + state subscriber. Needs ./inspire_g1 running.
|
||||
*
|
||||
* ./hand_bridge [iface] [port] (default eth0 7799)
|
||||
*/
|
||||
#include <unitree/idl/go2/MotorCmds_.hpp>
|
||||
#include <unitree/idl/go2/MotorStates_.hpp>
|
||||
#include <unitree/robot/channel/channel_publisher.hpp>
|
||||
#include <unitree/robot/channel/channel_subscriber.hpp>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::string iface = argc > 1 ? argv[1] : "eth0";
|
||||
int port = argc > 2 ? std::atoi(argv[2]) : 7799;
|
||||
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
auto pub = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>("rt/inspire/cmd");
|
||||
pub->InitChannel();
|
||||
unitree_go::msg::dds_::MotorCmds_ cmd;
|
||||
cmd.cmds().resize(12);
|
||||
|
||||
// Subscribe to hand state for read-back / capture.
|
||||
std::mutex mtx;
|
||||
double state[12] = {0};
|
||||
double force[12] = {0};
|
||||
double cur[12] = {0}, fset[12] = {0}; // dq = current mA, ddq = force limit
|
||||
double temp[12] = {0}, err[12] = {0}, sta[12] = {0}, lost[12] = {0};
|
||||
double rate = 0; int rn = 0; auto rt0 = std::chrono::steady_clock::now();
|
||||
|
||||
// ---- force-follow (admittance) --------------------------------------------------
|
||||
// The RH56 cannot be back-driven, so pushing a finger moves it 0.000. This closes the
|
||||
// loop in software: read the press, drive the finger that way, hold when you stop. It
|
||||
// lives here rather than in the web layer because the loop needs the 30Hz state stream
|
||||
// and the command publisher in the same place -- polling over HTTP is far too slow.
|
||||
std::atomic<bool> follow{false};
|
||||
std::atomic<double> fgain{0.0006}, fdead{60.0}, fmaxrate{0.35}, fforce{400.0};
|
||||
double ftarget[12] = {0}, fbase[12] = {0};
|
||||
std::atomic<bool> fcal{false}; // tau_est, in grams — the joint tracker needs BOTH angle and
|
||||
// force, because 'force moved but angle did not' is the whole
|
||||
// signature of a finger that cannot be back-driven.
|
||||
auto sub = std::make_shared<unitree::robot::ChannelSubscriber<unitree_go::msg::dds_::MotorStates_>>("rt/inspire/state");
|
||||
sub->InitChannel([&](const void *m) {
|
||||
auto s = (const unitree_go::msg::dds_::MotorStates_ *)m;
|
||||
std::lock_guard<std::mutex> lk(mtx);
|
||||
for (int i = 0; i < 12 && i < (int)s->states().size(); i++) {
|
||||
state[i] = s->states()[i].q();
|
||||
force[i] = s->states()[i].tau_est();
|
||||
cur[i] = s->states()[i].dq(); // mA
|
||||
fset[i] = s->states()[i].ddq(); // grip force limit
|
||||
temp[i] = s->states()[i].temperature();
|
||||
err[i] = s->states()[i].reserve()[0];
|
||||
sta[i] = s->states()[i].reserve()[1];
|
||||
lost[i] = s->states()[i].lost();
|
||||
}
|
||||
// Measure the ACTUAL publish rate here — a hand whose bus has died keeps serving
|
||||
// cached values, so a healthy-looking readout with a collapsed rate is the tell.
|
||||
if (++rn >= 20) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
double dt = std::chrono::duration<double>(now - rt0).count();
|
||||
if (dt > 0) rate = rn / dt;
|
||||
rn = 0; rt0 = now;
|
||||
}
|
||||
});
|
||||
|
||||
// Admittance thread: only publishes while follow is on, so it never fights the
|
||||
// dashboard, the recorder, or anything else driving the hand.
|
||||
std::thread ftick([&]{
|
||||
auto prev = std::chrono::steady_clock::now();
|
||||
while (true) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(33));
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
double dt = std::chrono::duration<double>(now - prev).count(); prev = now;
|
||||
if (!follow.load()) continue;
|
||||
if (dt > 0.2) dt = 0.2;
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(mtx);
|
||||
if (fcal.exchange(false)) { // arm: zero on the current force
|
||||
for (int i = 0; i < 12; i++) { fbase[i] = force[i]; ftarget[i] = state[i]; }
|
||||
}
|
||||
for (int i = 0; i < 12; i++) {
|
||||
double dev = force[i] - fbase[i];
|
||||
if (std::abs(dev) <= fdead.load()) continue;
|
||||
dev -= (dev > 0 ? fdead.load() : -fdead.load());
|
||||
double step = -fgain.load() * dev * dt; // press pad (+force) -> close
|
||||
double cap = fmaxrate.load() * dt;
|
||||
if (step > cap) step = cap;
|
||||
if (step < -cap) step = -cap;
|
||||
ftarget[i] += step;
|
||||
if (ftarget[i] < 0.0) ftarget[i] = 0.0;
|
||||
if (ftarget[i] > 1.0) ftarget[i] = 1.0;
|
||||
}
|
||||
for (int i = 0; i < 12; i++) {
|
||||
cmd.cmds()[i].q() = ftarget[i];
|
||||
cmd.cmds()[i].kp() = fforce.load();
|
||||
}
|
||||
}
|
||||
pub->Write(cmd);
|
||||
}
|
||||
});
|
||||
ftick.detach();
|
||||
|
||||
int srv = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int opt = 1;
|
||||
setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
addr.sin_port = htons(port);
|
||||
if (bind(srv, (sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return 1; }
|
||||
listen(srv, 8);
|
||||
std::cout << "hand_bridge listening on 127.0.0.1:" << port << " (iface " << iface << ")" << std::endl;
|
||||
|
||||
char buf[1024];
|
||||
while (true)
|
||||
{
|
||||
int c = accept(srv, nullptr, nullptr);
|
||||
if (c < 0) continue;
|
||||
int n = read(c, buf, sizeof(buf) - 1);
|
||||
if (n > 0)
|
||||
{
|
||||
buf[n] = 0;
|
||||
if (buf[0] == 'F' || buf[0] == 'f') // follow: "F 1 gain dead maxrate force" | "F 0"
|
||||
{
|
||||
std::istringstream iss(buf + 1);
|
||||
int on = 0; double g = 0, d = 0, mr = 0, fo = 0;
|
||||
iss >> on;
|
||||
if (iss >> g && g > 0) fgain.store(g);
|
||||
if (iss >> d && d > 0) fdead.store(d);
|
||||
if (iss >> mr && mr > 0) fmaxrate.store(mr);
|
||||
if (iss >> fo && fo > 0) fforce.store(fo);
|
||||
if (on) fcal.store(true); // re-zero the baseline each time it arms
|
||||
follow.store(on != 0);
|
||||
std::string o = std::string("follow ") + (on ? "on" : "off") + "\n";
|
||||
(void)!write(c, o.c_str(), o.size());
|
||||
}
|
||||
else if (buf[0] == 'D' || buf[0] == 'd') // full diagnostics: 8x12 + rate
|
||||
{
|
||||
std::string out;
|
||||
{ std::lock_guard<std::mutex> lk(mtx);
|
||||
char t[32];
|
||||
const double *blocks[8] = {state, force, cur, fset, temp, err, sta, lost};
|
||||
for (int b = 0; b < 8; b++)
|
||||
for (int i = 0; i < 12; i++) { snprintf(t, sizeof(t), "%.3f ", blocks[b][i]); out += t; }
|
||||
snprintf(t, sizeof(t), "%.2f ", rate); out += t; }
|
||||
out += "\n";
|
||||
(void)!write(c, out.c_str(), out.size());
|
||||
}
|
||||
else if (buf[0] == 'S' || buf[0] == 's') // angle + force: 24 values
|
||||
{
|
||||
std::string out;
|
||||
{ std::lock_guard<std::mutex> lk(mtx);
|
||||
char t[32];
|
||||
for (int i = 0; i < 12; i++) { snprintf(t, sizeof(t), "%.3f ", state[i]); out += t; }
|
||||
for (int i = 0; i < 12; i++) { snprintf(t, sizeof(t), "%.1f ", force[i]); out += t; } }
|
||||
out += "\n";
|
||||
(void)!write(c, out.c_str(), out.size());
|
||||
}
|
||||
else if (buf[0] == 'R' || buf[0] == 'r') // read-back request (12 angles, legacy)
|
||||
{
|
||||
std::string out;
|
||||
{ std::lock_guard<std::mutex> lk(mtx);
|
||||
char t[32];
|
||||
for (int i = 0; i < 12; i++) { snprintf(t, sizeof(t), "%.3f ", state[i]); out += t; } }
|
||||
out += "\n";
|
||||
(void)!write(c, out.c_str(), out.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::istringstream iss(buf);
|
||||
std::vector<float> v; float x;
|
||||
while (iss >> x) v.push_back(x);
|
||||
if (v.size() == 12)
|
||||
{
|
||||
for (int i = 0; i < 12; i++) cmd.cmds()[i].q() = v[i];
|
||||
for (int k = 0; k < 3; k++) { pub->Write(cmd); usleep(8000); }
|
||||
(void)!write(c, "ok\n", 3);
|
||||
}
|
||||
else (void)!write(c, "err\n", 4);
|
||||
}
|
||||
}
|
||||
close(c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
290
example/hand_diag.cpp
Normal file
290
example/hand_diag.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
/**
|
||||
* @file hand_diag.cpp
|
||||
* @brief Read the Inspire RH56 fault registers per finger: ERROR, STATUS, TEMP,
|
||||
* CURRENT. Tells you exactly WHY a finger won't move (locked rotor,
|
||||
* over-temperature, over-current, ...) instead of guessing.
|
||||
*
|
||||
* Register map (from the Inspire Modbus map; this serial protocol encodes the
|
||||
* address as low,high in bytes 5,6 — verified: CLEAR_ERROR 1004 = 0x03EC = {0xEC,0x03}):
|
||||
* CURRENT 1594 (0x063A, 12 bytes) ERROR 1606 (0x0646, 6)
|
||||
* STATUS 1612 (0x064C, 6) TEMP 1618 (0x0652, 6)
|
||||
* CLEAR_ERROR 1004 (0x03EC) RESET_PARA 1006 (0x03EE)
|
||||
*
|
||||
* g++ -std=c++17 -Iinclude example/hand_diag.cpp -o /tmp/hand_diag
|
||||
* /tmp/hand_diag /dev/ttyUSB1 [clear] # 'clear' also sends CLEAR_ERROR
|
||||
*
|
||||
* Needs the port free (stop the container first).
|
||||
*/
|
||||
#include "SerialPort.h"
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
|
||||
static const char *FING[6] = {"pinky", "ring", "mid", "index", "thumbB", "thumbR"};
|
||||
|
||||
static uint8_t cksum(const uint8_t *d, int len)
|
||||
{
|
||||
uint8_t s = 0;
|
||||
for (int i = 2; i < len - 1; i++) s += d[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
// Read `n` bytes from register `addr`, robustly (flush + re-query).
|
||||
static bool readReg(SerialPort &sp, uint16_t addr, uint8_t n, uint8_t *out, uint8_t id = 1)
|
||||
{
|
||||
uint8_t q[9] = {0xEB, 0x90, id, 0x04, 0x11,
|
||||
(uint8_t)(addr & 0xFF), (uint8_t)(addr >> 8), n, 0x00};
|
||||
q[8] = cksum(q, 9);
|
||||
uint8_t buf[128];
|
||||
for (int att = 0; att < 8; att++)
|
||||
{
|
||||
sp.flush();
|
||||
sp.send(q, 9);
|
||||
usleep(8000);
|
||||
size_t got = sp.recv(buf, sizeof(buf));
|
||||
for (size_t off = 0; off + 7 + n <= got; off++)
|
||||
{
|
||||
if (!((buf[off] == 0x90 && buf[off + 1] == 0xEB) ||
|
||||
(buf[off] == 0xEB && buf[off + 1] == 0x90))) continue;
|
||||
if (buf[off + 4] != 0x11) continue;
|
||||
uint16_t got_addr = buf[off + 5] | (buf[off + 6] << 8);
|
||||
if (got_addr != addr) continue;
|
||||
int frame = 7 + n + 1; // header+addr+data+checksum
|
||||
if (off + frame > got) continue;
|
||||
if (buf[off + frame - 1] != cksum(buf + off, frame)) continue;
|
||||
memcpy(out, buf + off + 7, n);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void writeReg16(SerialPort &sp, uint16_t addr, uint16_t val, uint8_t id = 1)
|
||||
{
|
||||
uint8_t c[11] = {0xEB, 0x90, id, 0x06, 0x12,
|
||||
(uint8_t)(addr & 0xFF), (uint8_t)(addr >> 8),
|
||||
(uint8_t)(val & 0xFF), (uint8_t)(val >> 8), 0x00, 0x00};
|
||||
c[9] = cksum(c, 10);
|
||||
sp.send(c, 10);
|
||||
usleep(5000);
|
||||
uint8_t b[32];
|
||||
sp.recv(b, sizeof(b));
|
||||
}
|
||||
|
||||
static std::string errStr(uint8_t e)
|
||||
{
|
||||
if (!e) return "OK";
|
||||
std::string s;
|
||||
if (e & 0x01) s += "LOCKED_ROTOR ";
|
||||
if (e & 0x02) s += "OVER_TEMPERATURE ";
|
||||
if (e & 0x04) s += "OVER_CURRENT ";
|
||||
if (e & 0x08) s += "ABNORMAL_OPERATION ";
|
||||
if (e & 0x10) s += "COMMUNICATION_ERROR ";
|
||||
return s;
|
||||
}
|
||||
|
||||
// Command all 6 fingers to a position (ANGLE_SET 1486 = 0x05CE, 12 bytes).
|
||||
static void setAll(SerialPort &sp, int16_t val, uint8_t id = 1)
|
||||
{
|
||||
uint8_t c[20];
|
||||
c[0] = 0xEB; c[1] = 0x90; c[2] = id; c[3] = 0x0F; c[4] = 0x12;
|
||||
c[5] = 0xCE; c[6] = 0x05;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
c[7 + 2 * i] = val & 0xFF;
|
||||
c[8 + 2 * i] = (val >> 8) & 0xFF;
|
||||
}
|
||||
c[19] = cksum(c, 20);
|
||||
sp.send(c, 20);
|
||||
usleep(5000);
|
||||
uint8_t b[32];
|
||||
sp.recv(b, sizeof(b));
|
||||
}
|
||||
|
||||
// Write all 6 force limits (FORCE_SET 1498 = 0x05DA, 12 bytes).
|
||||
static void setForceAll(SerialPort &sp, uint16_t val, uint8_t id = 1)
|
||||
{
|
||||
uint8_t c[20];
|
||||
c[0] = 0xEB; c[1] = 0x90; c[2] = id; c[3] = 0x0F; c[4] = 0x12;
|
||||
c[5] = 0xDA; c[6] = 0x05;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
c[7 + 2 * i] = val & 0xFF;
|
||||
c[8 + 2 * i] = (val >> 8) & 0xFF;
|
||||
}
|
||||
c[19] = cksum(c, 20);
|
||||
sp.send(c, 20);
|
||||
usleep(5000);
|
||||
uint8_t b[32];
|
||||
sp.recv(b, sizeof(b));
|
||||
}
|
||||
|
||||
// Does the motor actually energize when told to move? current>0 => it's trying
|
||||
// (mechanically blocked); current==0 => it never energizes.
|
||||
//
|
||||
// IMPORTANT: current==0 alone does NOT mean the actuator is dead. The RH56 stops driving a
|
||||
// finger the instant its MEASURED force (FORCE_ACT 1582) reaches its force LIMIT
|
||||
// (FORCE_SET 1498), so a finger whose force-sensor zero has drifted above the limit draws
|
||||
// 0 mA and is indistinguishable from a dead motor. This test used to inherit whatever limit
|
||||
// the service last wrote (500g) and so reproduced exactly that failure while looking like an
|
||||
// independent raw-serial check — it is how the G1's right mid+index were wrongly called dead
|
||||
// when they in fact run their full range at a 1000g limit. It now sweeps the limit itself.
|
||||
static void moveTest(SerialPort &sp, uint16_t force)
|
||||
{
|
||||
printf("\n=== MOVE TEST: force limit %ug, command CLOSE, watch current + force + angle ===\n",
|
||||
force);
|
||||
setForceAll(sp, force);
|
||||
setAll(sp, 1000); // open first
|
||||
usleep(800000);
|
||||
|
||||
uint8_t f0[12] = {0};
|
||||
if (readReg(sp, 1582, 12, f0))
|
||||
{
|
||||
printf("resting force vs the %ug limit (>= limit => the driver refuses to move it):\n ",
|
||||
force);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
int16_t F = (int16_t)(f0[2 * i] | (f0[2 * i + 1] << 8));
|
||||
printf("%s=%dg%s ", FING[i], F, (F >= (int)force || -F >= (int)force) ? "<<GATED" : "");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
setAll(sp, 0); // CLOSE
|
||||
for (int k = 0; k < 6; k++)
|
||||
{
|
||||
usleep(400000);
|
||||
uint8_t ang[12] = {0}, cur[12] = {0}, sta[6] = {0};
|
||||
bool ra = readReg(sp, 1546, 12, ang);
|
||||
bool rc = readReg(sp, 1594, 12, cur);
|
||||
bool rs = readReg(sp, 1612, 6, sta);
|
||||
printf("t=%.1fs reads: angle=%s current=%s status=%s\n",
|
||||
k * 0.4, ra ? "ok" : "FAIL", rc ? "ok" : "FAIL", rs ? "ok" : "FAIL");
|
||||
if (!(ra || rc || rs)) continue;
|
||||
printf(" ");
|
||||
for (int i = 0; i < 6; i++) // ALL fingers: healthy ones are the control
|
||||
{
|
||||
uint16_t A = ang[2 * i] | (ang[2 * i + 1] << 8);
|
||||
int16_t C = (int16_t)(cur[2 * i] | (cur[2 * i + 1] << 8));
|
||||
printf("%s:a=%u,i=%d,s=%d ", FING[i], A, C, sta[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
setAll(sp, 1000);
|
||||
usleep(500000);
|
||||
setForceAll(sp, 500); // restore the service default
|
||||
printf("\nIf a finger stayed put at 500g but moves here, it is NOT dead — its force-sensor\n"
|
||||
"zero has drifted. Re-zero the sensor with the hand unloaded (FORCE_SENSOR_CALIB),\n"
|
||||
"or keep its limit above the offset. Compare: '%s move' vs '%s move 1000'.\n",
|
||||
"hand_diag <port>", "hand_diag <port>");
|
||||
}
|
||||
|
||||
// Are the dead channels merely CONFIGURED not to drive? A speed / force / current
|
||||
// limit of 0 would give exactly the observed signature: no motion, no current, no
|
||||
// error, status "reached target". That would be software-fixable.
|
||||
static void paramDump(SerialPort &sp)
|
||||
{
|
||||
struct { const char *name; uint16_t addr; uint8_t bytes; } regs[] = {
|
||||
{"ANGLE_SET ", 1486, 12},
|
||||
{"FORCE_SET ", 1498, 12},
|
||||
{"SPEED_SET ", 1522, 12},
|
||||
{"CURRENT_LIM ", 1020, 12},
|
||||
{"ANGLE_ACT ", 1546, 12},
|
||||
};
|
||||
printf("%-13s", "register");
|
||||
for (int i = 0; i < 6; i++) printf("%9s", FING[i]);
|
||||
printf("\n");
|
||||
for (auto &r : regs)
|
||||
{
|
||||
uint8_t b[16] = {0};
|
||||
bool ok = readReg(sp, r.addr, r.bytes, b);
|
||||
printf("%-13s", r.name);
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!ok) { printf("%9s", "FAIL"); continue; }
|
||||
printf("%9d", (int16_t)(b[2 * i] | (b[2 * i + 1] << 8)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n(a 0 in SPEED_SET / FORCE_SET / CURRENT_LIM for a finger would explain\n"
|
||||
" no motion + no current + no error, and would be software-fixable.)\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *dev = argc > 1 ? argv[1] : "/dev/ttyUSB1";
|
||||
std::string opt = argc > 2 ? argv[2] : "";
|
||||
bool doClear = (opt == "clear");
|
||||
bool doMove = (opt == "move");
|
||||
SerialPort sp(dev, B115200, 8);
|
||||
if (opt == "params") { paramDump(sp); return 0; }
|
||||
// Command a CLOSE, then read ANGLE_SET back: does the setpoint actually LAND in
|
||||
// the dead channels? ANGLE_SET=0 but no motion => setpoint accepted, motor dead.
|
||||
// ANGLE_SET stays 1000 => the channel rejects the write.
|
||||
if (opt == "setclose")
|
||||
{
|
||||
printf("commanding CLOSE (ANGLE_SET=0) ...\n\n");
|
||||
setAll(sp, 0);
|
||||
usleep(1500000);
|
||||
paramDump(sp);
|
||||
setAll(sp, 1000);
|
||||
return 0;
|
||||
}
|
||||
// 'move [force]' — force defaults to the RH56 max so a drifted sensor zero can't
|
||||
// silently gate a healthy finger off and make it look dead.
|
||||
if (doMove)
|
||||
{
|
||||
uint16_t f = argc > 3 ? (uint16_t)atoi(argv[3]) : 1000;
|
||||
moveTest(sp, f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (doClear)
|
||||
{
|
||||
printf("sending CLEAR_ERROR (1004) ...\n");
|
||||
writeReg16(sp, 1004, 1);
|
||||
usleep(300000);
|
||||
}
|
||||
|
||||
uint8_t err[6] = {0}, sta[6] = {0}, tmp[6] = {0}, cur[12] = {0};
|
||||
uint8_t fact[12] = {0}, fset[12] = {0};
|
||||
bool eok = readReg(sp, 1606, 6, err);
|
||||
bool sok = readReg(sp, 1612, 6, sta);
|
||||
bool tok = readReg(sp, 1618, 6, tmp);
|
||||
bool cok = readReg(sp, 1594, 12, cur);
|
||||
bool faok = readReg(sp, 1582, 12, fact); // FORCE_ACT — measured
|
||||
bool fsok = readReg(sp, 1498, 12, fset); // FORCE_SET — the limit
|
||||
|
||||
printf("port %s (error=%s status=%s temp=%s current=%s force=%s limit=%s)\n\n", dev,
|
||||
eok ? "ok" : "FAIL", sok ? "ok" : "FAIL", tok ? "ok" : "FAIL", cok ? "ok" : "FAIL",
|
||||
faok ? "ok" : "FAIL", fsok ? "ok" : "FAIL");
|
||||
printf("%-8s %6s %8s %6s %9s %8s %7s %s\n",
|
||||
"finger", "err", "status", "temp", "current", "force", "limit", "meaning");
|
||||
bool anyGated = false;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
int16_t c = cok ? (int16_t)(cur[2 * i] | (cur[2 * i + 1] << 8)) : 0;
|
||||
int16_t fa = faok ? (int16_t)(fact[2 * i] | (fact[2 * i + 1] << 8)) : 0;
|
||||
int16_t fs = fsok ? (int16_t)(fset[2 * i] | (fset[2 * i + 1] << 8)) : 0;
|
||||
// THE check that was missing: a finger already at/over its force limit is gated off
|
||||
// by the driver and will read 0 current with no error — identical to a dead motor.
|
||||
bool gated = faok && fsok && fs > 0 && (fa >= fs || -fa >= fs);
|
||||
if (gated) anyGated = true;
|
||||
std::string mean = eok ? errStr(err[i]) : "?";
|
||||
if (gated) mean = "FORCE-GATED (not dead: force >= limit)";
|
||||
printf("%-8s 0x%02X %8d %5d\xC2\xB0 %8d %7dg %6dg %s\n",
|
||||
FING[i], eok ? err[i] : 0, sok ? sta[i] : -1, tok ? tmp[i] : -1, c,
|
||||
fa, fs, mean.c_str());
|
||||
}
|
||||
if (anyGated)
|
||||
printf("\n>> One or more fingers is FORCE-GATED: its measured force already meets its\n"
|
||||
">> limit, so the driver refuses to energise it (0 current, no error). This is a\n"
|
||||
">> drifted force-sensor zero, NOT a dead actuator. Confirm with:\n"
|
||||
">> %s %s move 1000\n"
|
||||
">> Fix by re-zeroing the sensor with the hand unloaded, or raise the limit.\n",
|
||||
argv[0], dev);
|
||||
return 0;
|
||||
}
|
||||
135
example/hand_forcetest.cpp
Normal file
135
example/hand_forcetest.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/**
|
||||
* @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;
|
||||
}
|
||||
188
example/hand_gestures.cpp
Normal file
188
example/hand_gestures.cpp
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* @file hand_gestures.cpp
|
||||
* @brief Named gestures for the Inspire RH56 hands on G1, over DDS (rt/inspire/cmd).
|
||||
*
|
||||
* Requires the service running in another terminal: ./inspire_g1
|
||||
*
|
||||
* Usage:
|
||||
* ./hand_gestures # interactive menu (pick gestures repeatedly)
|
||||
* ./hand_gestures <gesture> [iface] # run one gesture and exit
|
||||
* gesture = open | close | box | thumbup | handshake | combo | demo
|
||||
*
|
||||
* Per-hand DOF order: [pinky, ring, middle, index, thumb_bend, thumb_rotation]
|
||||
* q in [0,1]: 0 = closed, 1 = open. Indices 0-5 = right hand, 6-11 = left hand.
|
||||
*
|
||||
* NOTE: this controls the HAND (fingers) only. Raising the arm is a separate
|
||||
* subsystem (G1 arm joints) and is not driven here.
|
||||
*/
|
||||
|
||||
#include <unitree/idl/go2/MotorCmds_.hpp>
|
||||
#include <unitree/idl/go2/MotorStates_.hpp>
|
||||
#include <unitree/robot/channel/channel_publisher.hpp>
|
||||
#include <unitree/robot/channel/channel_subscriber.hpp>
|
||||
#include <unitree/common/thread/thread.hpp>
|
||||
|
||||
#include <eigen3/Eigen/Dense>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <unistd.h>
|
||||
|
||||
using Vec6 = Eigen::Matrix<float, 6, 1>;
|
||||
|
||||
class HandController
|
||||
{
|
||||
public:
|
||||
HandController() { Init(); }
|
||||
|
||||
void set(const Vec6 &right, const Vec6 &left)
|
||||
{
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
{
|
||||
cmd.cmds()[i].q() = right(i);
|
||||
cmd.cmds()[i + 6].q() = left(i);
|
||||
}
|
||||
handcmd->Write(cmd);
|
||||
}
|
||||
void setBoth(const Vec6 &q) { set(q, q); }
|
||||
|
||||
unitree_go::msg::dds_::MotorCmds_ cmd;
|
||||
unitree_go::msg::dds_::MotorStates_ state;
|
||||
|
||||
private:
|
||||
void Init()
|
||||
{
|
||||
handcmd = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>("rt/inspire/cmd");
|
||||
handcmd->InitChannel();
|
||||
cmd.cmds().resize(12);
|
||||
handstate = std::make_shared<unitree::robot::ChannelSubscriber<unitree_go::msg::dds_::MotorStates_>>("rt/inspire/state");
|
||||
handstate->InitChannel([this](const void *message) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
state = *(unitree_go::msg::dds_::MotorStates_ *)message;
|
||||
});
|
||||
state.states().resize(12);
|
||||
}
|
||||
|
||||
std::mutex mtx;
|
||||
unitree::robot::ChannelPublisherPtr<unitree_go::msg::dds_::MotorCmds_> handcmd;
|
||||
unitree::robot::ChannelSubscriberPtr<unitree_go::msg::dds_::MotorStates_> handstate;
|
||||
};
|
||||
|
||||
static Vec6 V(float pinky, float ring, float middle, float index, float thumb_bend, float thumb_rot)
|
||||
{
|
||||
Vec6 v; v << pinky, ring, middle, index, thumb_bend, thumb_rot; return v;
|
||||
}
|
||||
static void hold(int ms) { usleep(ms * 1000); }
|
||||
|
||||
// --- Pose library (tune freely; values are [0,1], 0=closed 1=open) ---
|
||||
static const Vec6 OPEN = V(1, 1, 1, 1, 1, 1);
|
||||
static const Vec6 CLOSE = V(0, 0, 0, 0, 0, 0);
|
||||
static const Vec6 BOX = V(0.5, 0.5, 0.5, 0.5, 0.4, 0.1);
|
||||
static const Vec6 THUMBUP = V(0, 0, 0, 0, 1, 1);
|
||||
static const Vec6 SHAKE_READY = V(0.85, 0.85, 0.85, 0.85, 0.85, 0.6);
|
||||
static const Vec6 SHAKE_GRIP = V(0.2, 0.2, 0.2, 0.2, 0.25, 0.1);
|
||||
|
||||
// --- Gestures (social ones use the RIGHT hand, left held open) ---
|
||||
static void g_pose(HandController &h, const Vec6 &q, const char *name, int ms = 1500)
|
||||
{
|
||||
std::cout << " [" << name << "]" << std::endl;
|
||||
h.setBoth(q);
|
||||
hold(ms);
|
||||
}
|
||||
static void g_thumbup(HandController &h, int ms = 2000)
|
||||
{
|
||||
std::cout << " [thumbup] (right hand)" << std::endl;
|
||||
h.set(THUMBUP, OPEN);
|
||||
hold(ms);
|
||||
}
|
||||
static void g_handshake(HandController &h)
|
||||
{
|
||||
std::cout << " [handshake] (right hand)" << std::endl;
|
||||
h.set(SHAKE_READY, OPEN); hold(1200); // reach out, open
|
||||
h.set(SHAKE_GRIP, OPEN); hold(800); // grip
|
||||
for (int k = 0; k < 3; k++) // a few firm "shakes"
|
||||
{
|
||||
h.set(SHAKE_GRIP * 0.85f, OPEN); hold(180);
|
||||
h.set(SHAKE_GRIP, OPEN); hold(180);
|
||||
}
|
||||
h.set(THUMBUP, OPEN); hold(1500); // finish with a thumbs-up
|
||||
h.set(OPEN, OPEN); hold(600); // relax
|
||||
}
|
||||
static void g_demo(HandController &h)
|
||||
{
|
||||
g_pose(h, OPEN, "open");
|
||||
g_pose(h, CLOSE, "close");
|
||||
g_pose(h, BOX, "box");
|
||||
g_pose(h, OPEN, "open");
|
||||
g_thumbup(h);
|
||||
g_handshake(h);
|
||||
g_pose(h, OPEN, "open");
|
||||
}
|
||||
|
||||
// Dispatch by name or menu number. Returns false only on quit.
|
||||
static bool runGesture(HandController &h, const std::string &g)
|
||||
{
|
||||
if (g == "open" || g == "1") g_pose(h, OPEN, "open");
|
||||
else if (g == "close" || g == "2") g_pose(h, CLOSE, "close");
|
||||
else if (g == "box" || g == "3") g_pose(h, BOX, "box");
|
||||
else if (g == "thumbup" || g == "4") g_thumbup(h);
|
||||
else if (g == "handshake" || g == "5") g_handshake(h);
|
||||
else if (g == "combo" || g == "6") { g_thumbup(h); g_handshake(h); }
|
||||
else if (g == "demo" || g == "7") g_demo(h);
|
||||
else if (g == "q" || g == "quit" || g == "0") return false;
|
||||
else std::cout << " unknown option: '" << g << "'" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void printMenu()
|
||||
{
|
||||
std::cout << "\n=== Inspire Hand Gestures ===\n"
|
||||
<< " 1) open\n"
|
||||
<< " 2) close (fist)\n"
|
||||
<< " 3) box (power grasp)\n"
|
||||
<< " 4) thumbup (right hand)\n"
|
||||
<< " 5) handshake (right hand, ends thumbs-up)\n"
|
||||
<< " 6) combo (thumbup + handshake)\n"
|
||||
<< " 7) demo (run all)\n"
|
||||
<< " q) quit\n"
|
||||
<< "Select: " << std::flush;
|
||||
}
|
||||
|
||||
static std::string trim(std::string s)
|
||||
{
|
||||
const char *ws = " \t\r\n";
|
||||
size_t a = s.find_first_not_of(ws);
|
||||
size_t b = s.find_last_not_of(ws);
|
||||
return a == std::string::npos ? "" : s.substr(a, b - a + 1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::string arg1 = argc > 1 ? argv[1] : "";
|
||||
std::string iface = argc > 2 ? argv[2] : "";
|
||||
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
auto hand = std::make_shared<HandController>();
|
||||
usleep(300000); // let DDS match the service
|
||||
|
||||
// Direct mode: run one gesture and exit (backward compatible).
|
||||
if (!arg1.empty())
|
||||
{
|
||||
runGesture(*hand, arg1);
|
||||
std::cout << "done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Interactive menu: fire gestures repeatedly over one DDS connection.
|
||||
std::string line;
|
||||
while (true)
|
||||
{
|
||||
printMenu();
|
||||
if (!std::getline(std::cin, line)) break; // EOF / Ctrl-D
|
||||
line = trim(line);
|
||||
if (line.empty()) continue;
|
||||
if (!runGesture(*hand, line)) break;
|
||||
}
|
||||
std::cout << "bye." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
61
example/hand_pose.cpp
Normal file
61
example/hand_pose.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file hand_pose.cpp
|
||||
* @brief Live finger-pose tuner for the Inspire hand (right hand). Needs ./inspire_g1.
|
||||
*
|
||||
* ./hand_pose [networkInterface] (default iface: eth0)
|
||||
*
|
||||
* Then type 6 numbers (q in [0,1], 0=closed 1=open):
|
||||
* pinky ring middle index thumb_bend thumb_rot
|
||||
* e.g. 0 0 0 0 1 1 -> try a thumbs-up and tweak the last two values
|
||||
* Shortcuts: open | close | q(uit)
|
||||
* The pose is applied to the RIGHT hand (left held open) and holds until the next entry.
|
||||
*/
|
||||
#include <unitree/idl/go2/MotorCmds_.hpp>
|
||||
#include <unitree/robot/channel/channel_publisher.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const std::string iface = argc > 1 ? argv[1] : "eth0";
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
|
||||
auto pub = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>("rt/inspire/cmd");
|
||||
pub->InitChannel();
|
||||
unitree_go::msg::dds_::MotorCmds_ cmd;
|
||||
cmd.cmds().resize(12);
|
||||
usleep(300000);
|
||||
|
||||
// right = indices 0-5, left = 6-11 (held open)
|
||||
auto apply = [&](const std::vector<float> &r) {
|
||||
for (int i = 0; i < 6; i++) { cmd.cmds()[i].q() = r[i]; cmd.cmds()[i + 6].q() = 1.0f; }
|
||||
for (int n = 0; n < 12; n++) { pub->Write(cmd); usleep(30000); } // ~0.36s of repeats so it lands + moves
|
||||
};
|
||||
|
||||
std::cout << "Inspire RIGHT-hand pose tuner. Order: pinky ring middle index thumb_bend thumb_rot\n"
|
||||
<< "q in [0,1], 0=closed 1=open. Type 6 numbers, or 'open'/'close'/'q'.\n";
|
||||
|
||||
std::string line;
|
||||
while (true) {
|
||||
std::cout << "pose> " << std::flush;
|
||||
if (!std::getline(std::cin, line)) break;
|
||||
if (line == "q" || line == "quit") break;
|
||||
if (line == "open") { apply({1, 1, 1, 1, 1, 1}); continue; }
|
||||
if (line == "close") { apply({0, 0, 0, 0, 0, 0}); continue; }
|
||||
|
||||
std::istringstream iss(line);
|
||||
std::vector<float> v; float x;
|
||||
while (iss >> x) v.push_back(x);
|
||||
if (v.size() != 6) { std::cout << " enter exactly 6 numbers (or open/close/q)\n"; continue; }
|
||||
apply(v);
|
||||
std::cout << " applied: pinky=" << v[0] << " ring=" << v[1] << " middle=" << v[2]
|
||||
<< " index=" << v[3] << " thumb_bend=" << v[4] << " thumb_rot=" << v[5] << "\n";
|
||||
}
|
||||
std::cout << "bye.\n";
|
||||
return 0;
|
||||
}
|
||||
49
example/hand_readtest.cpp
Normal file
49
example/hand_readtest.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file hand_readtest.cpp
|
||||
* @brief Low-level read diagnostic: send the Inspire "read angleAct" query on a
|
||||
* serial port and dump the RAW bytes that come back. Isolates whether the
|
||||
* hand answers position reads (writes are confirmed working).
|
||||
*
|
||||
* g++ -std=c++17 -Iinclude example/hand_readtest.cpp -o /tmp/hand_readtest
|
||||
* /tmp/hand_readtest /dev/ttyUSB0 [slaveid=1] [waitms=15]
|
||||
*
|
||||
* Needs the port free (stop inspire_g1 / the container first).
|
||||
*/
|
||||
#include "SerialPort.h"
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <unistd.h>
|
||||
|
||||
static uint8_t checksum(const uint8_t *d, int len)
|
||||
{
|
||||
uint8_t s = 0;
|
||||
for (int i = 2; i < len - 1; i++) s += d[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *dev = argc > 1 ? argv[1] : "/dev/ttyUSB0";
|
||||
int slave = argc > 2 ? atoi(argv[2]) : 1;
|
||||
int waitms = argc > 3 ? atoi(argv[3]) : 15;
|
||||
|
||||
SerialPort sp(dev, B115200, 40); // 40ms read timeout
|
||||
uint8_t q[9] = {0xEB, 0x90, (uint8_t)slave, 0x04, 0x11, 0x0A, 0x06, 0x0C, 0x00};
|
||||
q[8] = checksum(q, 9);
|
||||
|
||||
printf("port=%s slave=%d wait=%dms (query angleAct)\n", dev, slave, waitms);
|
||||
for (int t = 0; t < 8; t++)
|
||||
{
|
||||
sp.flush();
|
||||
sp.send(q, 9);
|
||||
usleep(waitms * 1000);
|
||||
uint8_t buf[128];
|
||||
size_t n = sp.recv(buf, sizeof(buf));
|
||||
printf(" try %d: %2zu bytes:", t, n);
|
||||
for (size_t i = 0; i < n; i++) printf(" %02X", buf[i]);
|
||||
printf("\n");
|
||||
usleep(150000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
185
example/hand_record.cpp
Normal file
185
example/hand_record.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
/**
|
||||
* @file hand_record.cpp
|
||||
* @brief Record & replay named hand poses (12 joint values: right 0-5, left 6-11).
|
||||
*
|
||||
* You sculpt a shape live (close/open individual fingers), name it, and it's saved
|
||||
* to a file. Records the COMMANDED values (the serial read-back is unreliable on
|
||||
* these CH340 adapters, and the hand holds whatever it's commanded anyway).
|
||||
* Needs ./inspire_g1 running.
|
||||
*
|
||||
* ./hand_record [iface] interactive recorder (default iface eth0)
|
||||
* ./hand_record play <name> [iface] command a saved pose and hold
|
||||
* ./hand_record list list saved poses
|
||||
*
|
||||
* Poses file: $HOME/DFX_inspire_service/hand_poses.txt (line: "name v0 .. v11")
|
||||
* Per-hand joint order: pinky ring middle index thumb_bend thumb_rot. q in [0,1].
|
||||
*/
|
||||
#include <unitree/idl/go2/MotorCmds_.hpp>
|
||||
#include <unitree/robot/channel/channel_publisher.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
|
||||
using Pose = std::array<float, 12>;
|
||||
|
||||
static std::string posesFile()
|
||||
{
|
||||
const char *h = getenv("HOME");
|
||||
return std::string(h ? h : ".") + "/DFX_inspire_service/hand_poses.txt";
|
||||
}
|
||||
|
||||
static std::map<std::string, Pose> loadPoses()
|
||||
{
|
||||
std::map<std::string, Pose> m;
|
||||
std::ifstream f(posesFile());
|
||||
std::string line;
|
||||
while (std::getline(f, line))
|
||||
{
|
||||
if (line.empty() || line[0] == '#') continue;
|
||||
std::istringstream iss(line);
|
||||
std::string name; iss >> name;
|
||||
Pose v{}; int i = 0; float x;
|
||||
while (i < 12 && (iss >> x)) v[i++] = x;
|
||||
if (i == 12) m[name] = v;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static void savePose(const std::string &name, const Pose &v)
|
||||
{
|
||||
auto m = loadPoses();
|
||||
m[name] = v; // add or overwrite
|
||||
std::ofstream f(posesFile(), std::ios::trunc);
|
||||
f << "# name <right: pinky ring middle index thumb_bend thumb_rot> <left: same>\n";
|
||||
for (const auto &kv : m)
|
||||
{
|
||||
f << kv.first;
|
||||
for (float x : kv.second) f << " " << x;
|
||||
f << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
class Hand
|
||||
{
|
||||
public:
|
||||
Hand()
|
||||
{
|
||||
pub_ = std::make_shared<unitree::robot::ChannelPublisher<unitree_go::msg::dds_::MotorCmds_>>("rt/inspire/cmd");
|
||||
pub_->InitChannel();
|
||||
cmd_.cmds().resize(12);
|
||||
}
|
||||
void apply(const Pose &v)
|
||||
{
|
||||
for (int i = 0; i < 12; i++) cmd_.cmds()[i].q() = v[i];
|
||||
for (int n = 0; n < 8; n++) { pub_->Write(cmd_); usleep(20000); } // ~0.16s so it lands
|
||||
}
|
||||
private:
|
||||
unitree_go::msg::dds_::MotorCmds_ cmd_;
|
||||
unitree::robot::ChannelPublisherPtr<unitree_go::msg::dds_::MotorCmds_> pub_;
|
||||
};
|
||||
|
||||
static void printPose(const Pose &v)
|
||||
{
|
||||
std::cout << " R:";
|
||||
for (int i = 0; i < 6; i++) std::cout << " " << v[i];
|
||||
std::cout << " L:";
|
||||
for (int i = 6; i < 12; i++) std::cout << " " << v[i];
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
static void printMenu()
|
||||
{
|
||||
std::cout <<
|
||||
"\n--- hand_record --- q in [0,1] (tune to taste), order: pinky ring middle index thumb_bend thumb_rot\n"
|
||||
" r <6 nums> set RIGHT hand l <6 nums> set LEFT hand b <6 nums> set BOTH\n"
|
||||
" f <0-11> <v> set one joint (0-5 right, 6-11 left) open | close all\n"
|
||||
" save <name> save current shape load <name> recall list | print | q\n";
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::string a1 = argc > 1 ? argv[1] : "";
|
||||
|
||||
if (a1 == "list")
|
||||
{
|
||||
auto m = loadPoses();
|
||||
std::cout << m.size() << " saved pose(s):\n";
|
||||
for (const auto &kv : m) { std::cout << " " << kv.first << ":"; printPose(kv.second); }
|
||||
return 0;
|
||||
}
|
||||
if (a1 == "play")
|
||||
{
|
||||
if (argc < 3) { std::cerr << "usage: hand_record play <name> [iface]\n"; return 1; }
|
||||
std::string name = argv[2], iface = argc > 3 ? argv[3] : "eth0";
|
||||
auto m = loadPoses();
|
||||
if (!m.count(name)) { std::cerr << "no pose '" << name << "'. try: hand_record list\n"; return 1; }
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
Hand hand; usleep(300000);
|
||||
std::cout << "playing '" << name << "'\n"; printPose(m[name]);
|
||||
hand.apply(m[name]); usleep(1500000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// interactive
|
||||
std::string iface = a1.empty() ? "eth0" : a1;
|
||||
unitree::robot::ChannelFactory::Instance()->Init(0, iface);
|
||||
Hand hand; usleep(300000);
|
||||
|
||||
Pose cur; cur.fill(1.0f); // start open
|
||||
hand.apply(cur);
|
||||
printMenu();
|
||||
|
||||
std::string line;
|
||||
while (true)
|
||||
{
|
||||
std::cout << "rec> " << std::flush;
|
||||
if (!std::getline(std::cin, line)) break;
|
||||
std::istringstream iss(line);
|
||||
std::string op; iss >> op;
|
||||
if (op.empty()) continue;
|
||||
|
||||
if (op == "q" || op == "quit") break;
|
||||
else if (op == "open") { cur.fill(1.0f); hand.apply(cur); printPose(cur); }
|
||||
else if (op == "close") { cur.fill(0.0f); hand.apply(cur); printPose(cur); }
|
||||
else if (op == "print") { printPose(cur); }
|
||||
else if (op == "list") { for (const auto &kv : loadPoses()) { std::cout << " " << kv.first << ":"; printPose(kv.second); } }
|
||||
else if (op == "r" || op == "l" || op == "b")
|
||||
{
|
||||
std::vector<float> v; float x; while (iss >> x) v.push_back(x);
|
||||
if (v.size() != 6) { std::cout << " need 6 numbers\n"; continue; }
|
||||
if (op == "r" || op == "b") for (int i = 0; i < 6; i++) cur[i] = v[i];
|
||||
if (op == "l" || op == "b") for (int i = 0; i < 6; i++) cur[i + 6] = v[i];
|
||||
hand.apply(cur); printPose(cur);
|
||||
}
|
||||
else if (op == "f")
|
||||
{
|
||||
int idx; float val;
|
||||
if (!(iss >> idx >> val) || idx < 0 || idx > 11) { std::cout << " usage: f <0-11> <val>\n"; continue; }
|
||||
cur[idx] = val; hand.apply(cur); printPose(cur);
|
||||
}
|
||||
else if (op == "save")
|
||||
{
|
||||
std::string name; iss >> name;
|
||||
if (name.empty()) { std::cout << " usage: save <name>\n"; continue; }
|
||||
savePose(name, cur);
|
||||
std::cout << " saved '" << name << "' -> " << posesFile() << "\n";
|
||||
}
|
||||
else if (op == "load")
|
||||
{
|
||||
std::string name; iss >> name;
|
||||
auto m = loadPoses();
|
||||
if (!m.count(name)) { std::cout << " no pose '" << name << "'\n"; continue; }
|
||||
cur = m[name]; hand.apply(cur); printPose(cur);
|
||||
}
|
||||
else std::cout << " ? see menu\n";
|
||||
}
|
||||
std::cout << "bye.\n";
|
||||
return 0;
|
||||
}
|
||||
119
example/hand_setid.cpp
Normal file
119
example/hand_setid.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @file hand_setid.cpp
|
||||
* @brief Give a hand a distinct RS-485 id, permanently, so left/right can never swap again.
|
||||
*
|
||||
* WHY THIS EXISTS
|
||||
* The RH56 has no handedness register — it cannot tell you whether it is a left or a right
|
||||
* unit. Both USB-RS485 dongles are CH340 1a86:7523 reporting the SAME USB serial. So the
|
||||
* only thing distinguishing the two hands was the ttyUSB number, which the kernel hands out
|
||||
* in enumeration order — and that changes across replugs, reboots and hub hiccups. When it
|
||||
* flips, left and right silently trade places: nothing errors, and you drive the wrong hand.
|
||||
* (Observed on this robot 2026-07-30: software "L.*" was in fact the robot's RIGHT hand.)
|
||||
*
|
||||
* Giving the two hands DIFFERENT ids fixes that at the root. inspire_g1 scans ids 1..4 on
|
||||
* each port and, when the ids differ, uses them as identity: id 1 = RIGHT, id 2 = LEFT.
|
||||
* That is wiring-independent and survives any replug.
|
||||
*
|
||||
* USAGE — run ONCE per robot, with the OTHER hand's dongle unplugged or on its own port:
|
||||
* g++ -std=c++17 -Iinclude example/hand_setid.cpp -o build/hand_setid
|
||||
* ./build/hand_setid /dev/ttyUSBx # just report which id answers
|
||||
* ./build/hand_setid /dev/ttyUSBx 1 2 # change id 1 -> 2 and SAVE it
|
||||
*
|
||||
* Convention: leave the RIGHT hand at id 1, give the LEFT hand id 2.
|
||||
* Needs the port free — stop the container first.
|
||||
*
|
||||
* Registers: HAND_ID 1000 (0x03E8), SAVE 1005 (0x03ED). The id change only survives a
|
||||
* power cycle if SAVE is written afterwards, which this does.
|
||||
*/
|
||||
#include "inspire.h"
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
|
||||
static uint8_t cks(const uint8_t *d, int len)
|
||||
{
|
||||
uint8_t s = 0;
|
||||
for (int i = 2; i < len - 1; i++) s += d[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
// Write the SAVE register (1005) so the new id survives a power cycle.
|
||||
static void saveParams(SerialPort &sp, uint8_t id)
|
||||
{
|
||||
uint8_t c[9] = {0xEB, 0x90, id, 0x04, 0x12, 0xED, 0x03, 0x01, 0x00};
|
||||
c[8] = cks(c, 9);
|
||||
sp.send(c, 9);
|
||||
usleep(300000);
|
||||
uint8_t b[32];
|
||||
sp.recv(b, sizeof(b));
|
||||
}
|
||||
|
||||
// Which id answers on this port? -1 if none.
|
||||
static int findId(SerialPort::SharedPtr sp)
|
||||
{
|
||||
for (int id = 1; id <= 4; id++)
|
||||
{
|
||||
inspire::InspireHand h(sp, (uint8_t)id);
|
||||
Eigen::Matrix<double, 6, 1> q;
|
||||
for (int t = 0; t < 3; t++)
|
||||
if (h.GetPosition(q) == 0) return id;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("usage: %s <port> [from_id to_id]\n"
|
||||
" %s /dev/ttyUSB0 report the id that answers\n"
|
||||
" %s /dev/ttyUSB0 1 2 change id 1 -> 2 and save\n",
|
||||
argv[0], argv[0], argv[0]);
|
||||
return 1;
|
||||
}
|
||||
const char *dev = argv[1];
|
||||
auto sp = std::make_shared<SerialPort>(dev, B115200, 8);
|
||||
|
||||
int cur = findId(sp);
|
||||
if (cur < 0)
|
||||
{
|
||||
printf("%s: no hand answered on ids 1-4.\n"
|
||||
" Is the container still holding the port? Is the hand powered?\n", dev);
|
||||
return 2;
|
||||
}
|
||||
printf("%s: hand answers at rs485 id %d\n", dev, cur);
|
||||
|
||||
if (argc < 4) return 0;
|
||||
|
||||
int from = atoi(argv[2]), to = atoi(argv[3]);
|
||||
if (from != cur)
|
||||
{
|
||||
printf("refusing: you said from=%d but this hand is at id %d.\n", from, cur);
|
||||
return 3;
|
||||
}
|
||||
if (to < 1 || to > 4)
|
||||
{
|
||||
printf("refusing: to_id must be 1-4.\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
printf("changing id %d -> %d ...\n", from, to);
|
||||
inspire::InspireHand h(sp, (uint8_t)from);
|
||||
h.ChangeID((uint8_t)from, (uint8_t)to);
|
||||
usleep(300000);
|
||||
saveParams(*sp, (uint8_t)to);
|
||||
usleep(300000);
|
||||
|
||||
int now = findId(sp);
|
||||
if (now == to)
|
||||
printf("OK — this hand is now id %d and it is saved.\n"
|
||||
" Convention: RIGHT hand stays id 1, LEFT hand becomes id 2.\n"
|
||||
" inspire_g1 will now identify the hands by id, and left/right can no longer\n"
|
||||
" swap however the USB ports enumerate.\n", now);
|
||||
else
|
||||
printf("FAILED — hand now answers at id %d (wanted %d). Nothing saved reliably;\n"
|
||||
" power-cycle the hand and re-check with: %s %s\n", now, to, argv[0], dev);
|
||||
return now == to ? 0 : 4;
|
||||
}
|
||||
57
example/hand_wrtest.cpp
Normal file
57
example/hand_wrtest.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file hand_wrtest.cpp
|
||||
* @brief Reproduce inspire_g1's write-then-read cycle standalone (no DDS) to
|
||||
* debug why GetPosition reads 0 inside the container but works natively.
|
||||
*
|
||||
* g++ -std=c++17 -Iinclude example/hand_wrtest.cpp -o /tmp/hand_wrtest
|
||||
* /tmp/hand_wrtest [rightPort=/dev/ttyUSB1] [leftPort=/dev/ttyUSB0]
|
||||
*
|
||||
* Needs the ports free (stop inspire_g1 / the container first).
|
||||
*/
|
||||
#include "inspire.h"
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace inspire;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *pr = argc > 1 ? argv[1] : "/dev/ttyUSB1"; // right
|
||||
const char *pl = argc > 2 ? argv[2] : "/dev/ttyUSB0"; // left
|
||||
|
||||
auto s1 = std::make_shared<SerialPort>(pr, B115200, 6);
|
||||
auto s2 = std::make_shared<SerialPort>(pl, B115200, 6);
|
||||
InspireHand right(s1, 1), left(s2, 1);
|
||||
|
||||
for (auto *h : {&right, &left})
|
||||
{
|
||||
h->ClearError();
|
||||
h->SetVelocity(1000, 1000, 1000, 1000, 1000, 1000);
|
||||
h->SetForce(500, 500, 500, 500, 500, 500);
|
||||
}
|
||||
|
||||
// TIGHT loop, no inter-cycle delay, alternating open/close — the worst case
|
||||
// that failed 300/300 with the old one-shot GetPosition. Verify the re-query
|
||||
// GetPosition holds up.
|
||||
Eigen::Matrix<double, 6, 1> qcmd, qr, ql;
|
||||
int rfail = 0, lfail = 0, N = 300;
|
||||
for (int cyc = 0; cyc < N; cyc++)
|
||||
{
|
||||
double v = ((cyc / 30) % 2 == 0) ? 1.0 : 0.0; // flip every 30 cycles
|
||||
for (int i = 0; i < 6; i++) qcmd(i) = v;
|
||||
right.SetPosition(qcmd);
|
||||
left.SetPosition(qcmd);
|
||||
usleep(3000);
|
||||
int rr = right.GetPosition(qr);
|
||||
usleep(2000);
|
||||
int rl = left.GetPosition(ql);
|
||||
if (rr != 0) rfail++;
|
||||
if (rl != 0) lfail++;
|
||||
if (cyc % 30 == 0)
|
||||
printf("cyc%3d v=%.0f R(ret%d): %.2f %.2f %.2f L(ret%d): %.2f %.2f %.2f\n",
|
||||
cyc, v, rr, qr(0), qr(1), qr(2), rl, ql(0), ql(1), ql(2));
|
||||
}
|
||||
printf("=== %d tight cycles: RIGHT read-fails=%d LEFT read-fails=%d ===\n", N, rfail, lfail);
|
||||
return 0;
|
||||
}
|
||||
23
example/handshake.cpp
Normal file
23
example/handshake.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file handshake.cpp
|
||||
* @brief G1 handshake: arm "shake hand"(27) -> Inspire hand grips -> thumbs-up -> release(99).
|
||||
*
|
||||
* ./handshake [networkInterface] (default iface: eth0)
|
||||
*
|
||||
* Needs ./inspire_g1 running for the fingers. The ARM physically moves —
|
||||
* clear space + E-stop ready.
|
||||
*/
|
||||
#include "greet_common.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const std::string iface = argc > 1 ? argv[1] : "eth0";
|
||||
auto arm = greet_init(iface);
|
||||
Hand hand;
|
||||
usleep(300000); // let DDS match the arm service + inspire_g1
|
||||
|
||||
std::cout << "*** HANDSHAKE (arm + hand). Clear space, E-stop ready. ***" << std::endl;
|
||||
runHandshake(*arm, hand);
|
||||
std::cout << "done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
56
example/like.cpp
Normal file
56
example/like.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file like.cpp
|
||||
* @brief Robot holds a thumbs-up "like" WHILE the built-in handshake arm action plays.
|
||||
*
|
||||
* A background thread republishes the 👍 continuously (so inspire_g1 always has a
|
||||
* fresh command and the fingers stay curled), while the main thread triggers the
|
||||
* handshake and holds it for a fixed window (ExecuteAction can return before the
|
||||
* arm actually finishes moving, so we don't gate on its return).
|
||||
*
|
||||
* ./like [thumb_bend] [thumb_rot] [networkInterface]
|
||||
* thumb_bend, thumb_rot in [0,1] (default 1 1). Tweak if 👍 isn't clean:
|
||||
* e.g. ./like 1 0 ./like 0.7 0.3
|
||||
* default iface: eth0
|
||||
*
|
||||
* Needs exactly one ./inspire_g1 running for the fingers. The ARM moves —
|
||||
* clear space, E-stop ready.
|
||||
*/
|
||||
#include "greet_common.hpp"
|
||||
#include <cstdlib>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const float tb = argc > 1 ? std::atof(argv[1]) : 1.0f; // thumb_bend (1 = extended)
|
||||
const float tr = argc > 2 ? std::atof(argv[2]) : 1.0f; // thumb_rot
|
||||
const std::string iface = argc > 3 ? argv[3] : "eth0";
|
||||
|
||||
auto arm = greet_init(iface);
|
||||
Hand hand;
|
||||
usleep(1500000); // 1.5s: let DDS match inspire_g1 + the arm service before commanding
|
||||
|
||||
// On these hands the 4 fingers close at q=1 (q=0 = extended, inverted vs SDK doc).
|
||||
const Vec6 like = gv(1, 1, 1, 1, tb, tr); // 4 fingers curled into a fist, thumb up
|
||||
|
||||
std::cout << "*** LIKE while handshake (arm + hand). Clear space, E-stop ready. ***\n"
|
||||
<< "hand: thumbs-up (thumb_bend=" << tb << " thumb_rot=" << tr << ")" << std::endl;
|
||||
|
||||
// Background thread: keep the 👍 published the whole time.
|
||||
std::atomic<bool> running{true};
|
||||
std::thread holder([&] { while (running) { hand.set(like, G_OPEN); ghold(40); } });
|
||||
|
||||
ghold(1200); // let the 👍 form before the arm starts
|
||||
|
||||
if (arm_do(*arm, 27, "shake hand")) {
|
||||
ghold(4500); // hold the 👍 while the handshake plays
|
||||
arm_do(*arm, 99, "release arm");
|
||||
ghold(500);
|
||||
}
|
||||
|
||||
running = false;
|
||||
holder.join();
|
||||
hand.set(G_OPEN, G_OPEN);
|
||||
std::cout << "done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
23
example/thumbup.cpp
Normal file
23
example/thumbup.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @file thumbup.cpp
|
||||
* @brief G1 thumbs-up: arm "right hand up"(23) -> Inspire hand thumbs-up -> release(99).
|
||||
*
|
||||
* ./thumbup [networkInterface] (default iface: eth0)
|
||||
*
|
||||
* Needs ./inspire_g1 running for the fingers. The ARM physically moves —
|
||||
* clear space + E-stop ready.
|
||||
*/
|
||||
#include "greet_common.hpp"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const std::string iface = argc > 1 ? argv[1] : "eth0";
|
||||
auto arm = greet_init(iface);
|
||||
Hand hand;
|
||||
usleep(300000); // let DDS match the arm service + inspire_g1
|
||||
|
||||
std::cout << "*** THUMBS-UP (arm + hand). Clear space, E-stop ready. ***" << std::endl;
|
||||
runThumbup(*arm, hand);
|
||||
std::cout << "done." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@ -13,6 +13,8 @@
|
||||
#include <memory>
|
||||
#include <chrono>
|
||||
#include <queue>
|
||||
#include <array> // recv_buf below is a std::array; without this, any TU that doesn't
|
||||
// pull <array> in transitively (e.g. via Eigen) fails to compile.
|
||||
|
||||
class SerialPort
|
||||
{
|
||||
@ -41,8 +43,9 @@ public:
|
||||
FD_ZERO(&rSet_);
|
||||
FD_SET(fd_, &rSet_);
|
||||
ssize_t recv_len = 0;
|
||||
timeval tv = timeout_; // local copy: select() mutates the timeval, keep timeout_ intact
|
||||
|
||||
switch (select(fd_ + 1, &rSet_, NULL, NULL, &timeout_))
|
||||
switch (select(fd_ + 1, &rSet_, NULL, NULL, &tv))
|
||||
{
|
||||
case -1: // error
|
||||
// std::cout << "communication error" << std::endl;
|
||||
@ -64,6 +67,8 @@ public:
|
||||
timeout_.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
}
|
||||
|
||||
void flush() { tcflush(fd_, TCIFLUSH); } // discard buffered/echoed input
|
||||
|
||||
private:
|
||||
void Init(std::string port, speed_t baudrate)
|
||||
{
|
||||
|
||||
@ -39,7 +39,17 @@ public:
|
||||
*/
|
||||
int16_t SetPosition(const Eigen::Matrix<double, 6, 1> & q)
|
||||
{
|
||||
Eigen::Matrix<int16_t, 6, 1> q_int16 = (q * 1000).cast<int16_t>().cwiseMax(0).cwiseMin(1000);
|
||||
Eigen::Matrix<int16_t, 6, 1> q_int16;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// 0xFFFF = "no change" (per the docstring above): the hand IGNORES this joint and keeps
|
||||
// driving it to its previous target. It does NOT release the motor — an earlier comment
|
||||
// here claimed it did, and a hand-pose recording mode was built on that before the
|
||||
// operator found the finger still locked. There is no release command on the RH56, and
|
||||
// the drive is a non-backdrivable worm gear, so no force setting frees it either.
|
||||
if (q(i) < 0.0) q_int16(i) = -1;
|
||||
else { double v = q(i) * 1000.0; q_int16(i) = (int16_t)(v < 0 ? 0 : (v > 1000 ? 1000 : v)); }
|
||||
}
|
||||
|
||||
uint8_t cmd[20];
|
||||
cmd[0] = 0xEB; // head
|
||||
@ -66,7 +76,7 @@ public:
|
||||
cmd[19] = CheckSum(cmd, 20);
|
||||
|
||||
serial_->send(cmd, 20);
|
||||
usleep(5000);
|
||||
usleep(1500); // was 5000 - recv() polls via select(), and reads flush() first
|
||||
serial_->recv(recvBuff, 9);
|
||||
return 0;
|
||||
}
|
||||
@ -78,23 +88,10 @@ public:
|
||||
*/
|
||||
int16_t GetPosition(Eigen::Matrix<double, 6, 1> & q)
|
||||
{
|
||||
std::vector<uint8_t> cmd = {0xEB, 0x90, id, 0x04, 0x11, 0x0A, 0x06, 0x0C, 0x00};
|
||||
cmd.back() = CheckSum(cmd.data(), cmd.size());
|
||||
serial_->send(cmd.data(), cmd.size());
|
||||
|
||||
usleep(5000);
|
||||
size_t len = serial_->recv(recvBuff, 20);
|
||||
|
||||
if(len != 20) return 1;
|
||||
if(recvBuff[19] != CheckSum(recvBuff, 20)) return 2;
|
||||
|
||||
q(0) = (recvBuff[7] | (recvBuff[8] << 8)) / 1000.;
|
||||
q(1) = (recvBuff[9] | (recvBuff[10] << 8)) / 1000.;
|
||||
q(2) = (recvBuff[11] | (recvBuff[12] << 8)) / 1000.;
|
||||
q(3) = (recvBuff[13] | (recvBuff[14] << 8)) / 1000.;
|
||||
q(4) = (recvBuff[15] | (recvBuff[16] << 8)) / 1000.;
|
||||
q(5) = (recvBuff[17] | (recvBuff[18] << 8)) / 1000.;
|
||||
|
||||
const uint8_t *b = Query12(0x0A); // angleAct
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++)
|
||||
q(i) = (b[7 + 2 * i] | (b[8 + 2 * i] << 8)) / 1000.;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -128,7 +125,7 @@ public:
|
||||
cmd[19] = CheckSum(cmd, 20);
|
||||
|
||||
serial_->send(cmd, 20);
|
||||
usleep(5000);
|
||||
usleep(1500); // was 5000 - recv() polls via select(), and reads flush() first
|
||||
serial_->recv(recvBuff, 9);
|
||||
}
|
||||
|
||||
@ -164,7 +161,7 @@ public:
|
||||
cmd[19] = CheckSum(cmd, 20);
|
||||
|
||||
serial_->send(cmd, 20);
|
||||
usleep(5000);
|
||||
usleep(1500); // was 5000 - recv() polls via select(), and reads flush() first
|
||||
serial_->recv(recvBuff, 9);
|
||||
}
|
||||
|
||||
@ -175,30 +172,87 @@ public:
|
||||
*/
|
||||
int16_t GetForce(Eigen::Matrix<double, 6, 1> & f)
|
||||
{
|
||||
std::vector<uint8_t> cmd = {0xEB, 0x90, id, 0x04, 0x11, 0x2E, 0x06, 0x0C, 0x00};
|
||||
cmd.back() = CheckSum(cmd.data(), cmd.size());
|
||||
serial_->send(cmd.data(), cmd.size());
|
||||
// Force sensor register 0x2E. Output = grams, SIGNED. Used for push-to-teach: a hand
|
||||
// push shows up as a force deviation even though the finger can't back-drive.
|
||||
const uint8_t *b = Query12(0x2E);
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++)
|
||||
f(i) = (double)(int16_t)(b[7 + 2 * i] | (b[8 + 2 * i] << 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
usleep(5000);
|
||||
size_t len = serial_->recv(recvBuff, 20);
|
||||
/**
|
||||
* @brief Read the per-finger ERROR register (1606).
|
||||
*
|
||||
* Bits: 0x01 locked rotor, 0x02 over-temperature, 0x04 over-current,
|
||||
* 0x08 abnormal operation, 0x10 communication error.
|
||||
*
|
||||
* The RH56 LATCHES these: once a finger stalls it refuses every subsequent motion
|
||||
* command — any target, any force limit, and a release (q<0) does not reset it — until
|
||||
* CLEAR_ERROR is sent. It keeps reporting a low force and a valid angle throughout, so
|
||||
* from the outside it just looks like a finger that stopped listening.
|
||||
*/
|
||||
int16_t GetError(uint8_t out[6])
|
||||
{
|
||||
const uint8_t *b = QueryReg(1606, 6);
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++) out[i] = b[7 + i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(len != 20) return 1;
|
||||
if(recvBuff[19] != CheckSum(recvBuff, 20)) return 2;
|
||||
/**
|
||||
* @brief Per-finger STATUS (1612). 0 unclenching, 1 grasping, 2 reached position,
|
||||
* 3 reached force, 5 current protection, 6 locked rotor, 7 fault.
|
||||
*/
|
||||
int16_t GetStatus(uint8_t out[6])
|
||||
{
|
||||
const uint8_t *b = QueryReg(1612, 6);
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++) out[i] = b[7 + i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
f(0) = int16_t(recvBuff[7] | (recvBuff[8] << 8)) / 1000. * 9.8;
|
||||
f(1) = int16_t(recvBuff[9] | (recvBuff[10] << 8)) / 1000. * 9.8;
|
||||
f(2) = int16_t(recvBuff[11] | (recvBuff[12] << 8)) / 1000. * 9.8;
|
||||
f(3) = int16_t(recvBuff[13] | (recvBuff[14] << 8)) / 1000. * 9.8;
|
||||
f(4) = int16_t(recvBuff[15] | (recvBuff[16] << 8)) / 1000. * 9.8;
|
||||
f(5) = int16_t(recvBuff[17] | (recvBuff[18] << 8)) / 1000. * 9.8;
|
||||
/// Per-finger motor temperature in degrees C (1618).
|
||||
int16_t GetTemp(uint8_t out[6])
|
||||
{
|
||||
const uint8_t *b = QueryReg(1618, 6);
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++) out[i] = b[7 + i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Per-finger motor CURRENT in mA (1594, 12 bytes / 6 int16).
|
||||
*
|
||||
* The single number that separates "dead" from "force-gated": a finger commanded to move
|
||||
* that draws 0 mA is not being driven at all, whereas one drawing current against a
|
||||
* mechanical block is trying and failing. Reading only angle and force cannot tell those
|
||||
* apart, which is how healthy fingers were once written off as dead actuators.
|
||||
*/
|
||||
int16_t GetCurrent(Eigen::Matrix<double, 6, 1> &c)
|
||||
{
|
||||
const uint8_t *b = QueryReg(1594, 12);
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++)
|
||||
c(i) = (double)(int16_t)(b[7 + 2 * i] | (b[8 + 2 * i] << 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Per-finger grip force LIMIT currently in the hand (FORCE_SET 1498). Shown next to the
|
||||
/// measured force so "force >= limit -> driver refuses to move" is visible, not deduced.
|
||||
int16_t GetForceSet(Eigen::Matrix<double, 6, 1> &f)
|
||||
{
|
||||
const uint8_t *b = QueryReg(1498, 12);
|
||||
if (!b) return 1;
|
||||
for (int i = 0; i < 6; i++)
|
||||
f(i) = (double)(int16_t)(b[7 + 2 * i] | (b[8 + 2 * i] << 8));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear error
|
||||
*
|
||||
* When the Inspire Hand has a fault such as a stall, overcurrent, or abnormality,
|
||||
*
|
||||
* When the Inspire Hand has a fault such as a stall, overcurrent, or abnormality,
|
||||
* the fault can be cleared by the clear fault command.
|
||||
*/
|
||||
void ClearError()
|
||||
@ -238,6 +292,67 @@ public:
|
||||
|
||||
uint8_t id = 1;
|
||||
private:
|
||||
/**
|
||||
* @brief Send a 12-byte read query for `addr` and wait for its reply, POLLING the port
|
||||
* rather than sleeping a fixed interval.
|
||||
*
|
||||
* The previous version slept a flat 8ms per attempt whether or not the reply had already
|
||||
* landed. With four of these per control cycle (2 hands x angle+force) that alone cost
|
||||
* ~32ms, which is why the 100Hz RecurrentThread actually published at a measured 28Hz.
|
||||
* select() inside recv() already returns the instant bytes arrive, so we accumulate until
|
||||
* a complete, checksum-valid frame is present or the budget expires — typically ~3ms.
|
||||
*
|
||||
* Still re-queries on failure: if the hand is briefly busy after a write it ignores a
|
||||
* single query and a one-shot read returns all-zeros. We only accept a reply whose cmd
|
||||
* (0x11) and address match, so a stray write-ack or echo can never be mis-parsed as 0.
|
||||
*
|
||||
* @return pointer to the 20-byte frame inside recvBuff, or nullptr if it never arrived.
|
||||
*/
|
||||
const uint8_t* QueryReg(uint16_t addr, uint8_t nbytes, int budget_us = 12000)
|
||||
{
|
||||
uint8_t query[9] = {0xEB, 0x90, id, 0x04, 0x11,
|
||||
(uint8_t)(addr & 0xFF), (uint8_t)(addr >> 8), nbytes, 0x00};
|
||||
query[8] = CheckSum(query, 9);
|
||||
const size_t frame = 7u + nbytes + 1u; // header+addr + data + checksum
|
||||
|
||||
for (int attempt = 0; attempt < 4; attempt++)
|
||||
{
|
||||
serial_->flush();
|
||||
serial_->send(query, 9);
|
||||
|
||||
size_t n = 0;
|
||||
auto t0 = std::chrono::steady_clock::now();
|
||||
while (n + 1 < sizeof(recvBuff))
|
||||
{
|
||||
ssize_t got = serial_->recv(recvBuff + n, sizeof(recvBuff) - n);
|
||||
if (got > 0)
|
||||
{
|
||||
n += (size_t)got;
|
||||
for (size_t off = 0; off + frame <= n; off++)
|
||||
{
|
||||
if (!((recvBuff[off] == 0x90 && recvBuff[off + 1] == 0xEB) ||
|
||||
(recvBuff[off] == 0xEB && recvBuff[off + 1] == 0x90))) continue;
|
||||
if (recvBuff[off + 4] != 0x11) continue;
|
||||
uint16_t got_addr = recvBuff[off + 5] | (recvBuff[off + 6] << 8);
|
||||
if (got_addr != addr) continue;
|
||||
if (recvBuff[off + frame - 1] != CheckSum(recvBuff + off, frame)) continue;
|
||||
return recvBuff + off;
|
||||
}
|
||||
}
|
||||
auto el = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - t0).count();
|
||||
if (el >= budget_us) break;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// 12-byte reads (angleAct 0x060A, forceAct 0x062E) keep their short spelling.
|
||||
const uint8_t* Query12(uint8_t addrLo, int budget_us = 12000)
|
||||
{
|
||||
return QueryReg((uint16_t)(0x0600 | addrLo), 12, budget_us);
|
||||
}
|
||||
|
||||
uint8_t CheckSum(const uint8_t* data, uint8_t len)
|
||||
{
|
||||
uint8_t sum = 0;
|
||||
|
||||
579
inspire_g1.cpp
579
inspire_g1.cpp
@ -7,17 +7,172 @@
|
||||
#include <unitree/idl/go2/MotorStates_.hpp>
|
||||
#include <unitree/common/thread/recurrent_thread.hpp>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
|
||||
// One detected CH340 (1a86:7523) USB-RS485 hand adapter.
|
||||
struct HandPort
|
||||
{
|
||||
std::string dev; // /dev/ttyUSBn — NOT stable across replug/reboot
|
||||
std::string path; // USB topology path, e.g. "1-2.2.3" — stable per physical socket
|
||||
};
|
||||
|
||||
// Find the two CH340 hand adapters and order them by PHYSICAL USB PATH.
|
||||
//
|
||||
// This used to sort by ttyUSB name and assign right = ports[1]. Both dongles are
|
||||
// 1a86:7523 and report the SAME USB serial, so the tty number is the only thing telling
|
||||
// them apart — and the kernel hands those out in enumeration order, which changes across
|
||||
// replugs, reboots and hub hiccups. When it flips, left and right silently trade places:
|
||||
// nothing errors, the dashboard's port check still says "ok", and you drive the wrong hand.
|
||||
// Observed live on 2026-07-30 — software "L.*" was in fact the robot's RIGHT hand.
|
||||
//
|
||||
// The USB topology path IS stable as long as a dongle stays in the same socket, so we
|
||||
// order by that instead. Override explicitly with INSPIRE_RIGHT_PATH / INSPIRE_LEFT_PATH
|
||||
// (e.g. INSPIRE_RIGHT_PATH=1-2.2.3) when the sockets are known.
|
||||
static std::vector<HandPort> findCH340Ports()
|
||||
{
|
||||
std::vector<std::string> ttys;
|
||||
if (DIR *d = opendir("/sys/class/tty"))
|
||||
{
|
||||
for (struct dirent *e; (e = readdir(d));)
|
||||
{
|
||||
std::string n = e->d_name;
|
||||
if (n.rfind("ttyUSB", 0) == 0) ttys.push_back(n);
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
std::vector<HandPort> ports;
|
||||
for (const auto &t : ttys)
|
||||
{
|
||||
// Resolve the device symlink, then walk UP to the USB device dir (first
|
||||
// ancestor that has an idVendor file) and check for the CH340 id.
|
||||
char real[4096];
|
||||
std::string link = "/sys/class/tty/" + t + "/device";
|
||||
if (!realpath(link.c_str(), real)) continue;
|
||||
std::string dir = real;
|
||||
while (dir.size() > 1)
|
||||
{
|
||||
std::ifstream vf(dir + "/idVendor");
|
||||
if (vf.good())
|
||||
{
|
||||
std::string vid, pid; vf >> vid;
|
||||
std::ifstream pf(dir + "/idProduct"); pf >> pid;
|
||||
if (vid == "1a86" && pid == "7523")
|
||||
{
|
||||
// The USB device dir's basename is the topology path ("1-2.2.3").
|
||||
auto s = dir.find_last_of('/');
|
||||
ports.push_back({"/dev/" + t, s == std::string::npos ? dir : dir.substr(s + 1)});
|
||||
}
|
||||
break;
|
||||
}
|
||||
auto slash = dir.find_last_of('/');
|
||||
if (slash == std::string::npos || slash == 0) break;
|
||||
dir.resize(slash);
|
||||
}
|
||||
}
|
||||
std::sort(ports.begin(), ports.end(),
|
||||
[](const HandPort &a, const HandPort &b) { return a.path < b.path; });
|
||||
return ports;
|
||||
}
|
||||
|
||||
class InspireRunner
|
||||
{
|
||||
public:
|
||||
/// One opened port plus the RS-485 id that actually answered on it (-1 = nothing answered).
|
||||
struct Opened
|
||||
{
|
||||
std::shared_ptr<inspire::InspireHand> hand;
|
||||
SerialPort::SharedPtr port;
|
||||
int id = -1;
|
||||
};
|
||||
|
||||
InspireRunner()
|
||||
{
|
||||
serial1 = std::make_shared<SerialPort>("/dev/ttyUSB1", B115200);
|
||||
serial2 = std::make_shared<SerialPort>("/dev/ttyUSB2", B115200);
|
||||
// Dynamically detect the two CH340 hand adapters (port-independent — survives
|
||||
// being moved to a hub / different USB ports). A generic udev rule grants 0666.
|
||||
auto ports = findCH340Ports();
|
||||
if (ports.size() < 2)
|
||||
{
|
||||
std::cerr << "ERROR: found " << ports.size()
|
||||
<< " CH340 hand adapter(s), need 2. Plug in both USB-RS485 dongles."
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
// --- Work out which physical hand is on which port -----------------------------------
|
||||
//
|
||||
// The RH56 has NO handedness register — it cannot tell you it is a left or a right unit
|
||||
// (checked: only HAND_ID 1000 exists, which is just the RS-485 slave address). Both
|
||||
// dongles are CH340 1a86:7523 with the same USB serial too, so there is nothing
|
||||
// intrinsic to key on. We therefore try three things, best first:
|
||||
//
|
||||
// 1. RS-485 ID. If the hands have been given DIFFERENT ids (see example/hand_setid),
|
||||
// that is a permanent, wiring-independent identity: id 1 = RIGHT, id 2 = LEFT.
|
||||
// This is the real fix — immune to enumeration order, replugs and hub changes.
|
||||
// 2. INSPIRE_RIGHT_PATH / INSPIRE_LEFT_PATH env — pin by physical USB socket.
|
||||
// 3. USB topology path order — stable per socket, unlike the ttyUSB number that this
|
||||
// used to sort by (which silently swapped left and right; observed 2026-07-30).
|
||||
Opened A = openAndIdentify(ports[0].dev, ports[0].path.c_str());
|
||||
Opened B = openAndIdentify(ports[1].dev, ports[1].path.c_str());
|
||||
|
||||
// If your left and right hand controls are reversed, you can swap the positions of `serial1` and `serial2` below.
|
||||
righthand = std::make_shared<inspire::InspireHand>(serial1, 1);
|
||||
lefthand = std::make_shared<inspire::InspireHand>(serial2, 1);
|
||||
int ri = 1, li = 0; // default: USB-path order (ports[1] = right)
|
||||
const char *how = "usb path order";
|
||||
|
||||
if (A.id > 0 && B.id > 0 && A.id != B.id)
|
||||
{
|
||||
// Distinct ids => unambiguous identity, whatever the ports did.
|
||||
ri = (A.id == 1) ? 0 : 1;
|
||||
li = 1 - ri;
|
||||
how = "RS-485 id (id1=right, id2=left)";
|
||||
}
|
||||
else if (std::getenv("INSPIRE_RIGHT_PATH") || std::getenv("INSPIRE_LEFT_PATH"))
|
||||
{
|
||||
if (const char *rp = std::getenv("INSPIRE_RIGHT_PATH"))
|
||||
for (size_t i = 0; i < ports.size(); i++)
|
||||
if (ports[i].path == rp) { ri = (int)i; li = (int)(1 - i); }
|
||||
if (const char *lp = std::getenv("INSPIRE_LEFT_PATH"))
|
||||
for (size_t i = 0; i < ports.size(); i++)
|
||||
if (ports[i].path == lp) { li = (int)i; ri = (int)(1 - i); }
|
||||
how = "INSPIRE_*_PATH env";
|
||||
}
|
||||
else if (std::getenv("INSPIRE_SWAP"))
|
||||
{
|
||||
ri = 0; li = 1;
|
||||
how = "usb path order + INSPIRE_SWAP";
|
||||
}
|
||||
|
||||
Opened &R = (ri == 0) ? A : B;
|
||||
Opened &L = (li == 0) ? A : B;
|
||||
serial1 = R.port; righthand = R.hand;
|
||||
serial2 = L.port; lefthand = L.hand;
|
||||
|
||||
std::cout << "Inspire hands identified by " << how << ":\n"
|
||||
<< " RIGHT = " << ports[ri].dev << " (usb " << ports[ri].path
|
||||
<< ", rs485 id " << R.id << ")\n"
|
||||
<< " LEFT = " << ports[li].dev << " (usb " << ports[li].path
|
||||
<< ", rs485 id " << L.id << ")" << std::endl;
|
||||
if (!(A.id > 0 && B.id > 0 && A.id != B.id))
|
||||
std::cout << " NOTE: both hands answer on the same RS-485 id, so identity is inferred\n"
|
||||
" from wiring. To make it self-identifying and permanent, run once:\n"
|
||||
" ./build/hand_setid <left-hand-port> 1 2\n"
|
||||
" (gives the LEFT hand id 2; then left/right can never swap again)"
|
||||
<< std::endl;
|
||||
|
||||
// Recover the actuators on startup: clear any latched fault (stall/overcurrent) and
|
||||
// ensure a non-zero speed/force (e.g. after the bad serial state from two services
|
||||
// fighting over the bus, which can leave fingers unresponsive).
|
||||
for (auto h : {righthand, lefthand})
|
||||
{
|
||||
h->ClearError();
|
||||
h->SetVelocity(1000, 1000, 1000, 1000, 1000, 1000);
|
||||
h->SetForce(500, 500, 500, 500, 500, 500);
|
||||
}
|
||||
|
||||
calibrateForceOffset();
|
||||
|
||||
// dds
|
||||
handcmd = std::make_shared<unitree::robot::SubscriptionBase<unitree_go::msg::dds_::MotorCmds_>>(
|
||||
@ -27,59 +182,427 @@ public:
|
||||
"rt/" + param::ns + "/state");
|
||||
handstate->msg_.states().resize(12);
|
||||
|
||||
// Start running
|
||||
// Start running.
|
||||
// 20ms, not 10ms: a cycle is 2 position writes + 4 register reads over a 115200 half-
|
||||
// duplex bus, which cannot finish in 10ms. Asking for 100Hz just made the thread run
|
||||
// back-to-back with no idle, and the measured publish rate was 28Hz. 50Hz is honest and
|
||||
// achievable, and leaves headroom so a retry doesn't push the whole loop late.
|
||||
thread = std::make_shared<unitree::common::RecurrentThread>(
|
||||
10000, std::bind(&InspireRunner::run, this)
|
||||
20000, std::bind(&InspireRunner::run, this)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Learn each finger's resting force, and raise that finger's force limit past it.
|
||||
*
|
||||
* The RH56 stops driving a finger the instant its MEASURED force reaches the force limit.
|
||||
* So a finger whose force-sensor zero has drifted above the limit can never be driven: it
|
||||
* draws 0 current and reads exactly like a dead motor. On this G1's right hand, R.mid rests
|
||||
* at ~856g and R.index at ~570g against a 500g limit — both were mis-diagnosed as dead
|
||||
* actuators until they ran their full range once the limit was raised to 1000g.
|
||||
*
|
||||
* We measure the offset with the hand open and unloaded, then (a) subtract it from the
|
||||
* published force so touch-detection works from a true zero, and (b) add it to that
|
||||
* finger's limit so the gate still trips at the same REAL force.
|
||||
*/
|
||||
void calibrateForceOffset()
|
||||
{
|
||||
std::cout << "Calibrating finger force baseline (hand open, unloaded) ..." << std::endl;
|
||||
Eigen::Matrix<double, 6, 1> open6;
|
||||
open6.setOnes();
|
||||
for (int k = 0; k < 10; k++)
|
||||
{
|
||||
righthand->SetPosition(open6);
|
||||
lefthand->SetPosition(open6);
|
||||
usleep(30000);
|
||||
}
|
||||
|
||||
Eigen::Matrix<double, 12, 1> acc;
|
||||
acc.setZero();
|
||||
int n = 0;
|
||||
Eigen::Matrix<double, 6, 1> ftmp;
|
||||
for (int k = 0; k < 12; k++)
|
||||
{
|
||||
bool ok = true;
|
||||
Eigen::Matrix<double, 12, 1> one;
|
||||
if (righthand->GetForce(ftmp) == 0) one.block<6, 1>(0, 0) = ftmp; else ok = false;
|
||||
if (lefthand->GetForce(ftmp) == 0) one.block<6, 1>(6, 0) = ftmp; else ok = false;
|
||||
if (ok) { acc += one; n++; }
|
||||
usleep(20000);
|
||||
}
|
||||
if (!n)
|
||||
{
|
||||
std::cerr << " WARNING: no force readings - skipping offset calibration. "
|
||||
"Fingers with a drifted sensor zero will not move." << std::endl;
|
||||
foff.setZero();
|
||||
applyForce(reqForceR, 0);
|
||||
applyForce(reqForceL, 6);
|
||||
return;
|
||||
}
|
||||
foff = acc / n;
|
||||
|
||||
static const char *FN[6] = {"pinky", "ring", "mid", "index", "thumbB", "thumbR"};
|
||||
for (int lo = 0; lo <= 6; lo += 6)
|
||||
{
|
||||
double req = (lo == 0) ? reqForceR : reqForceL;
|
||||
bool flagged = false;
|
||||
for (int i = lo; i < lo + 6; i++)
|
||||
{
|
||||
if (std::abs(foff(i)) > req - kForceMargin)
|
||||
{
|
||||
if (!flagged)
|
||||
{
|
||||
std::cout << " " << (lo == 0 ? "RIGHT" : "LEFT")
|
||||
<< " hand force-sensor ZERO HAS DRIFTED:" << std::endl;
|
||||
flagged = true;
|
||||
}
|
||||
std::cout << " " << FN[i - lo] << " rests at " << (int)foff(i)
|
||||
<< "g vs a " << (int)req << "g limit -> would read as DEAD (0 current). "
|
||||
<< "Raising its limit." << std::endl;
|
||||
}
|
||||
}
|
||||
if (flagged)
|
||||
std::cout << " (proper fix: re-zero the force sensor with the hand unloaded)"
|
||||
<< std::endl;
|
||||
applyForce(req, lo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Open a hand's serial port and confirm it actually ANSWERS, reopening if it doesn't.
|
||||
*
|
||||
* Measured repeatedly on this robot: after a (re)start one of the two RS-485 buses comes up
|
||||
* mute — every read for that hand fails for the whole session while the other is perfect,
|
||||
* and WHICH one is random (5 restarts: R dead, L dead, both ok, R dead, L dead). The port
|
||||
* always enumerates and open() always succeeds; the adapter just never replies, so nothing
|
||||
* upstream notices. Closing and reopening clears it.
|
||||
*
|
||||
* Probing here costs a few hundred ms at startup and turns "half the robot is silently dead
|
||||
* until someone notices" into "it retried and told you".
|
||||
*/
|
||||
/// SerialPort::Init calls exit(-1) if open() fails, so never hand it a path that is not
|
||||
/// currently openable — that turns a transient into a service-wide crash.
|
||||
static bool canOpen(const std::string &dev)
|
||||
{
|
||||
int fd = ::open(dev.c_str(), O_RDWR | O_NOCTTY);
|
||||
if (fd < 0) return false;
|
||||
::close(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Re-resolve a hand's tty from its (stable) USB path. Reopening a CH340 repeatedly can
|
||||
/// make the adapters re-enumerate, so a device name captured at startup can go stale
|
||||
/// mid-probe — which is exactly how the earlier probe crash-looped the service.
|
||||
static std::string resolveByPath(const std::string &usbpath, const std::string &fallback)
|
||||
{
|
||||
for (const auto &p : findCH340Ports())
|
||||
if (p.path == usbpath) return p.dev;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
Opened openAndIdentify(const std::string &dev_in, const char *usbpath)
|
||||
{
|
||||
Opened o;
|
||||
std::string dev = dev_in;
|
||||
// Two attempts, not four: each reopen churns the USB bus and can renumber BOTH adapters.
|
||||
// One retry recovers a genuinely stalled link; more just destabilises the other hand.
|
||||
for (int attempt = 1; attempt <= 2; attempt++)
|
||||
{
|
||||
dev = resolveByPath(usbpath, dev);
|
||||
if (!canOpen(dev))
|
||||
{
|
||||
std::cerr << " " << dev << " (usb " << usbpath << ") cannot be opened right now"
|
||||
<< std::endl;
|
||||
usleep(300000);
|
||||
dev = resolveByPath(usbpath, dev);
|
||||
if (!canOpen(dev))
|
||||
{
|
||||
// Everything downstream dereferences righthand/lefthand unconditionally, so a
|
||||
// null hand would segfault. Exit clearly instead and let the supervisor retry —
|
||||
// this self-heals as soon as the adapter is back.
|
||||
std::cerr << "FATAL: usb " << usbpath << " has no openable tty (" << dev << "). "
|
||||
"Adapter unplugged or re-enumerating. Exiting; supervisor will retry."
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
o.port = std::make_shared<SerialPort>(dev, B115200, 6);
|
||||
usleep(120000); // let the CH340 settle after open
|
||||
|
||||
// Scan the RS-485 ids. Normally only id 1 is used, but giving the two hands distinct
|
||||
// ids makes them self-identifying, so look for any of them.
|
||||
for (int id = 1; id <= 4 && !o.hand; id++)
|
||||
{
|
||||
auto h = std::make_shared<inspire::InspireHand>(o.port, (uint8_t)id);
|
||||
Eigen::Matrix<double, 6, 1> q;
|
||||
for (int t = 0; t < 2; t++)
|
||||
if (h->GetPosition(q) == 0) { o.hand = h; o.id = id; break; }
|
||||
}
|
||||
if (o.hand)
|
||||
{
|
||||
std::cout << " " << dev << " (usb " << usbpath << ") answered at rs485 id " << o.id
|
||||
<< (attempt > 1 ? " [after reopen #" + std::to_string(attempt) + "]" : "")
|
||||
<< std::endl;
|
||||
return o;
|
||||
}
|
||||
std::cerr << " " << dev << " (usb " << usbpath << ") is SILENT - reopening ("
|
||||
<< attempt << "/2)" << std::endl;
|
||||
o.port.reset(); // close before retrying
|
||||
usleep(250000); // brief release; longer churns the bus
|
||||
}
|
||||
// Give the caller a usable object regardless, so one dead hand does not take the other
|
||||
// down. The runtime watchdog keeps retrying and the warning fires once.
|
||||
dev = resolveByPath(usbpath, dev);
|
||||
if (!canOpen(dev))
|
||||
{
|
||||
std::cerr << "FATAL: usb " << usbpath << " has no openable tty (" << dev << ") after "
|
||||
"probing. Exiting; supervisor will retry." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
o.port = std::make_shared<SerialPort>(dev, B115200, 6);
|
||||
o.hand = std::make_shared<inspire::InspireHand>(o.port, 1);
|
||||
o.id = -1;
|
||||
std::cerr << " WARNING: " << dev << " (usb " << usbpath << ") never answered. Check its "
|
||||
"RS-485 cable/power. Continuing so the other hand still works." << std::endl;
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Refresh the diagnostic registers for both hands.
|
||||
*
|
||||
* These are what turn "the finger will not move" from a guess into an answer:
|
||||
* ERROR - locked rotor / over-temp / over-current, LATCHED until CLEAR_ERROR
|
||||
* STATUS - what the driver thinks it is doing
|
||||
* CURRENT- 0mA means it never energised; >0 means it is trying and blocked
|
||||
* FORCE_SET - the limit the measured force is being compared against
|
||||
*/
|
||||
void refreshDiag()
|
||||
{
|
||||
uint8_t e[6], st[6], tp[6];
|
||||
Eigen::Matrix<double, 6, 1> cu, fs;
|
||||
for (int lo = 0; lo <= 6; lo += 6)
|
||||
{
|
||||
auto h = (lo == 0) ? righthand : lefthand;
|
||||
if (h->GetError(e) == 0) for (int i = 0; i < 6; i++) dErr[lo + i] = e[i];
|
||||
if (h->GetStatus(st)== 0) for (int i = 0; i < 6; i++) dSta[lo + i] = st[i];
|
||||
if (h->GetTemp(tp) == 0) for (int i = 0; i < 6; i++) dTmp[lo + i] = tp[i];
|
||||
if (h->GetCurrent(cu) == 0) dCur.block<6,1>(lo,0) = cu;
|
||||
if (h->GetForceSet(fs) == 0) dFset.block<6,1>(lo,0) = fs;
|
||||
}
|
||||
}
|
||||
|
||||
/// Poll both hands' ERROR registers and auto-clear any latched fault.
|
||||
void checkFaults()
|
||||
{
|
||||
static const char *FN[6] = {"pinky", "ring", "mid", "index", "thumbB", "thumbR"};
|
||||
for (int lo = 0; lo <= 6; lo += 6)
|
||||
{
|
||||
auto h = (lo == 0) ? righthand : lefthand;
|
||||
uint8_t err[6] = {0};
|
||||
if (h->GetError(err) != 0) continue; // read failed; the link watchdog covers that
|
||||
|
||||
std::string hit;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (!err[i]) continue;
|
||||
hit += std::string(FN[i]) + "(0x";
|
||||
const char *hex = "0123456789ABCDEF";
|
||||
hit += hex[(err[i] >> 4) & 0xF];
|
||||
hit += hex[err[i] & 0xF];
|
||||
if (err[i] & 0x01) hit += " locked-rotor";
|
||||
if (err[i] & 0x02) hit += " over-temp";
|
||||
if (err[i] & 0x04) hit += " over-current";
|
||||
if (err[i] & 0x08) hit += " abnormal";
|
||||
if (err[i] & 0x10) hit += " comms";
|
||||
hit += ") ";
|
||||
}
|
||||
if (hit.empty()) continue;
|
||||
|
||||
faultClears[lo == 0 ? 0 : 1]++;
|
||||
std::cerr << "FAULT on " << (lo == 0 ? "RIGHT" : "LEFT") << " hand: " << hit
|
||||
<< "-> sending CLEAR_ERROR (clear #" << faultClears[lo == 0 ? 0 : 1] << ")"
|
||||
<< std::endl;
|
||||
h->ClearError();
|
||||
// A stall also drops the speed/force config on some units; restore both so the finger
|
||||
// actually moves again instead of silently staying at zero speed.
|
||||
h->SetVelocity(1000, 1000, 1000, 1000, 1000, 1000);
|
||||
applyForce(lo == 0 ? reqForceR : reqForceL, lo);
|
||||
}
|
||||
}
|
||||
|
||||
/// Per-finger force limit = requested + that finger's sensor offset, capped at the 1000g max.
|
||||
void applyForce(double req, int lo)
|
||||
{
|
||||
uint16_t f[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
double v = req + std::abs(foff(lo + i));
|
||||
f[i] = (uint16_t)(v > kForceMax ? kForceMax : (v < 0 ? 0 : v));
|
||||
}
|
||||
auto h = (lo == 0) ? righthand : lefthand;
|
||||
h->SetForce(f[0], f[1], f[2], f[3], f[4], f[5]);
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
// Set command
|
||||
// Set command (write BOTH hands first)
|
||||
if(!handcmd->isTimeout())
|
||||
{
|
||||
for(int i(0); i<12; i++)
|
||||
{
|
||||
qcmd(i) = handcmd->msg_.cmds()[i].q();
|
||||
}
|
||||
// Optional grip-force override via the cmd's kp field (<=0 = keep default).
|
||||
// Lets the teacher drop to a low, back-drivable force so the fingers can be
|
||||
// moved by hand for recording, then restore the strong default afterwards.
|
||||
// Only re-sent when the requested value changes (avoids serial spam).
|
||||
// Applied through applyForce() so each finger's sensor offset is still added on top
|
||||
// — otherwise an override would re-gate a drifted finger back to "dead".
|
||||
double rf = handcmd->msg_.cmds()[0].kp();
|
||||
double lf = handcmd->msg_.cmds()[6].kp();
|
||||
if(rf > 0 && rf != lastForceR)
|
||||
{ reqForceR = rf; applyForce(rf, 0); lastForceR = rf; }
|
||||
if(lf > 0 && lf != lastForceL)
|
||||
{ reqForceL = lf; applyForce(lf, 6); lastForceL = lf; }
|
||||
|
||||
righthand->SetPosition(qcmd.block<6, 1>(0, 0));
|
||||
lefthand->SetPosition(qcmd.block<6, 1>(6, 0));
|
||||
}
|
||||
|
||||
// Recv state
|
||||
// Recv state. GetPosition() is self-retrying: it flushes stale RX and re-sends the
|
||||
// angleAct query, recovering when the hand is briefly busy after a write (a single
|
||||
// one-shot query gets ignored and reads back all-zeros — worst inside Docker / a tight
|
||||
// loop). A short settle after the writes still helps the very first query land.
|
||||
Eigen::Matrix<double, 6, 1> qtemp;
|
||||
usleep(1500); // settle after the writes (was 3000)
|
||||
|
||||
if(righthand->GetPosition(qtemp) == 0)
|
||||
{
|
||||
qstate.block<6, 1>(0, 0) = qtemp;
|
||||
posFailR = 0;
|
||||
everOkR = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
posFailR++;
|
||||
for(int i(0); i<6; i++)
|
||||
{
|
||||
handstate->msg_.states()[i].lost()++;
|
||||
}
|
||||
// spdlog::debug("Failed to get right hand state");
|
||||
}
|
||||
|
||||
if(lefthand->GetPosition(qtemp) == 0)
|
||||
{
|
||||
qstate.block<6, 1>(6, 0) = qtemp;
|
||||
posFailL = 0;
|
||||
everOkL = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
posFailL++;
|
||||
for(int i(0); i<6; i++)
|
||||
{
|
||||
handstate->msg_.states()[i+6].lost()++;
|
||||
}
|
||||
// spdlog::debug("Failed to get left hand state");
|
||||
}
|
||||
|
||||
// Force (grams, signed) — published as tau_est. A push on a finger registers
|
||||
// here even though the non-backdrivable finger can't move; used for
|
||||
// push-to-teach. Reuses the robust re-query reader.
|
||||
//
|
||||
// A FAILED read used to silently keep the previous value and republish it as if it were
|
||||
// fresh, with no counter (positions had one, force did not). A frozen force channel is
|
||||
// indistinguishable from a genuinely still finger, so push-to-teach would quietly stop
|
||||
// detecting touches and nothing would say so. Now failures bump lost() and get logged.
|
||||
Eigen::Matrix<double, 6, 1> ftemp;
|
||||
bool fr = (righthand->GetForce(ftemp) == 0);
|
||||
if(fr) fstate.block<6, 1>(0, 0) = ftemp;
|
||||
bool fl = (lefthand->GetForce(ftemp) == 0);
|
||||
if(fl) fstate.block<6, 1>(6, 0) = ftemp;
|
||||
|
||||
if(!fr) { forceFailR++; for(int i(0); i<6; i++) handstate->msg_.states()[i].lost()++; }
|
||||
else { forceFailR = 0; everOkR = true; }
|
||||
if(!fl) { forceFailL++; for(int i(6); i<12; i++) handstate->msg_.states()[i].lost()++; }
|
||||
else { forceFailL = 0; everOkL = true; }
|
||||
|
||||
if(forceFailR == kStaleWarn)
|
||||
std::cerr << "WARNING: right hand force reads failing - published force is STALE "
|
||||
"(push-to-teach will not detect touches)" << std::endl;
|
||||
if(forceFailL == kStaleWarn)
|
||||
std::cerr << "WARNING: left hand force reads failing - published force is STALE "
|
||||
"(push-to-teach will not detect touches)" << std::endl;
|
||||
|
||||
// A hand whose reads all fail is either (a) a stale link that a reopen would fix, or
|
||||
// (b) physically gone — unplugged, unpowered, or not answering on RS-485.
|
||||
//
|
||||
// Only (a) is worth exiting for. Exiting on (b) would boot-loop forever: the supervisor
|
||||
// restarts us every 3s, the hand is still absent, we exit again. So restart ONLY if this
|
||||
// hand was working earlier in this process — that is the signature of a link that died
|
||||
// and might come back on a reopen. If it has never answered since startup, stay up and
|
||||
// keep serving the healthy hand, loudly and once.
|
||||
bool deadR = (forceFailR > kDeadCycles) && (posFailR > kDeadCycles);
|
||||
bool deadL = (forceFailL > kDeadCycles) && (posFailL > kDeadCycles);
|
||||
if((deadR && everOkR) || (deadL && everOkL))
|
||||
{
|
||||
std::cerr << "FATAL: " << ((deadR && everOkR) ? "right" : "left")
|
||||
<< " hand serial link DIED after working (" << kDeadCycles
|
||||
<< " consecutive failed reads). Exiting so the supervisor can restart and "
|
||||
"reopen/re-detect the adapters." << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if(deadR && !everOkR && !warnedNeverR)
|
||||
{ warnedNeverR = true;
|
||||
std::cerr << "WARNING: RIGHT hand has NEVER answered since startup - check its RS-485 "
|
||||
"cable/power. Continuing with the left hand only." << std::endl; }
|
||||
if(deadL && !everOkL && !warnedNeverL)
|
||||
{ warnedNeverL = true;
|
||||
std::cerr << "WARNING: LEFT hand has NEVER answered since startup - check its RS-485 "
|
||||
"cable/power. Continuing with the right hand only." << std::endl; }
|
||||
|
||||
if(handstate->trylock())
|
||||
{
|
||||
for(int i(0); i<12; i++)
|
||||
{
|
||||
handstate->msg_.states()[i].q() = qstate(i);
|
||||
// Piggyback the diagnostics on fields this hand never populates, so no IDL
|
||||
// change is needed: dq=current(mA), ddq=force limit, temperature=degC,
|
||||
// reserve[0]=ERROR bits, reserve[1]=STATUS.
|
||||
handstate->msg_.states()[i].dq() = dCur(i);
|
||||
handstate->msg_.states()[i].ddq() = dFset(i);
|
||||
handstate->msg_.states()[i].temperature() = dTmp[i];
|
||||
handstate->msg_.states()[i].reserve()[0] = dErr[i];
|
||||
handstate->msg_.states()[i].reserve()[1] = dSta[i];
|
||||
// Subtract the calibrated resting offset so a drifted sensor zero doesn't look
|
||||
// like a permanent 850g press, and touch deltas start from a true zero.
|
||||
handstate->msg_.states()[i].tau_est() = fstate(i) - foff(i);
|
||||
}
|
||||
handstate->unlockAndPublish();
|
||||
}
|
||||
|
||||
// Fault watchdog. ClearError() used to run ONLY in the constructor, so a finger that
|
||||
// stalled mid-session stayed latched and dead until the whole service was restarted —
|
||||
// it ignored every target at every force limit, and a release did not reset it, while
|
||||
// still reporting a plausible angle and a low force. Poll the ERROR register ~1x/s and
|
||||
// clear it automatically, naming the finger so a repeat offender is visible.
|
||||
if(cycles % 50 == 0)
|
||||
{
|
||||
refreshDiag();
|
||||
checkFaults();
|
||||
}
|
||||
|
||||
// Report the rate we ACTUALLY achieve, so the gap between the requested period and the
|
||||
// serial bus's real throughput is visible instead of assumed.
|
||||
if(++cycles % 250 == 0)
|
||||
{
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
double dt = std::chrono::duration<double>(now - lastReport).count();
|
||||
if(dt > 0)
|
||||
{
|
||||
pubHz = 250.0 / dt;
|
||||
std::cout << "[inspire_g1] " << pubHz << " Hz" << std::endl;
|
||||
}
|
||||
lastReport = now;
|
||||
}
|
||||
}
|
||||
|
||||
unitree::common::ThreadPtr thread;
|
||||
@ -89,7 +612,39 @@ public:
|
||||
SerialPort::SharedPtr serial2;
|
||||
std::shared_ptr<inspire::InspireHand> lefthand;
|
||||
std::shared_ptr<inspire::InspireHand> righthand;
|
||||
Eigen::Matrix<double, 12, 1> qcmd, qstate;
|
||||
Eigen::Matrix<double, 12, 1> qcmd, qstate, fstate;
|
||||
double lastForceR = -1, lastForceL = -1; // last grip force applied per hand (via cmd kp)
|
||||
|
||||
// Force-sensor zero offset per finger, measured at startup with the hand open+unloaded.
|
||||
// Subtracted from published force, and added to each finger's force limit.
|
||||
Eigen::Matrix<double, 12, 1> foff = Eigen::Matrix<double, 12, 1>::Zero();
|
||||
double reqForceR = 500.0, reqForceL = 500.0; // grip force asked for, before offset
|
||||
static constexpr double kForceMax = 1000.0; // RH56 hardware max
|
||||
static constexpr double kForceMargin = 250.0; // headroom kept above a drifted zero
|
||||
|
||||
// Read-failure tracking. Consecutive failures per hand; force used to have no counter at
|
||||
// all, so a dead force channel republished stale values indefinitely and looked healthy.
|
||||
int forceFailR = 0, forceFailL = 0, posFailR = 0, posFailL = 0;
|
||||
static constexpr int kStaleWarn = 25; // ~0.5s at 50Hz -> warn once
|
||||
static constexpr int kDeadCycles = 150; // ~3s of total silence -> link is gone, restart
|
||||
|
||||
// Has this hand EVER answered since this process started? Distinguishes a link that died
|
||||
// (worth exiting for, a reopen may fix it) from a hand that was never there (exiting would
|
||||
// just boot-loop every 3s). Set on any successful read.
|
||||
bool everOkR = false, everOkL = false;
|
||||
bool warnedNeverR = false, warnedNeverL = false; // warn once, not every cycle
|
||||
|
||||
// Slow-poll diagnostics: ERROR/STATUS/TEMP/CURRENT/FORCE_SET, refreshed ~1x/s and
|
||||
// published in MotorState_ fields this hand does not otherwise use. Costs one extra
|
||||
// register read per second per hand, not per cycle.
|
||||
uint8_t dErr[12] = {0}, dSta[12] = {0}, dTmp[12] = {0};
|
||||
Eigen::Matrix<double, 12, 1> dCur = Eigen::Matrix<double, 12, 1>::Zero();
|
||||
Eigen::Matrix<double, 12, 1> dFset = Eigen::Matrix<double, 12, 1>::Zero();
|
||||
double pubHz = 0.0;
|
||||
|
||||
long cycles = 0;
|
||||
long faultClears[2] = {0, 0}; // per hand; a climbing count = something keeps stalling
|
||||
std::chrono::steady_clock::time_point lastReport = std::chrono::steady_clock::now();
|
||||
|
||||
// dds
|
||||
std::unique_ptr<unitree::robot::RealTimePublisher<unitree_go::msg::dds_::MotorStates_>> handstate;
|
||||
|
||||
141
manage.sh
Executable file
141
manage.sh
Executable file
@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# manage.sh — test & manage the Inspire RH56 hands + G1 arm gestures (on PC2)
|
||||
#
|
||||
# ./manage.sh <command> [args]
|
||||
#
|
||||
# Service / status:
|
||||
# status show service, devices, adapters (default if no command)
|
||||
# devices list /dev/inspire_* + ttyUSB + CH340 adapters
|
||||
# build (re)build all binaries via build.sh
|
||||
# start start ONE inspire_g1 (detached); refuses if already running
|
||||
# stop stop inspire_g1
|
||||
# restart stop + start
|
||||
# logs tail the inspire_g1 log
|
||||
#
|
||||
# Hand only (needs the service; auto-starts it):
|
||||
# example Unitree open/close test (hand_example)
|
||||
# menu interactive finger menu (hand_gestures)
|
||||
# open|close|box a finger pose (hand_gestures <name>)
|
||||
# pose <6 nums> one-shot right-hand pose (hand_pose), e.g. pose 1 1 1 1 1 1
|
||||
# record sculpt & SAVE named hand shapes (hand_record; save/load live)
|
||||
# poses list saved shapes
|
||||
# play <name> command a saved shape onto the hands
|
||||
# dashboard start the web slider dashboard (http://<robot-ip>:8088)
|
||||
# dashboard-stop stop the dashboard
|
||||
#
|
||||
# Arm + hand fused (ARM MOVES — clear space, E-stop ready; needs the service):
|
||||
# like thumbs-up "like" held during the built-in handshake
|
||||
# handshake reach -> grip -> thumbs-up -> release
|
||||
# thumbup raise right hand -> thumbs-up -> release
|
||||
#
|
||||
# Arm only (built-in actions):
|
||||
# arm <id|name> run a built-in action (e.g. arm "shake hand", arm 99)
|
||||
# armlist list built-in actions
|
||||
#
|
||||
# Env: IFACE (default eth0)
|
||||
# =============================================================================
|
||||
set -uo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
BUILD="$HERE/build"
|
||||
IFACE="${IFACE:-eth0}"
|
||||
LOG="/tmp/inspire_g1.log"
|
||||
SVC="$BUILD/inspire_g1"
|
||||
|
||||
c_red=$'\e[31m'; c_grn=$'\e[32m'; c_yel=$'\e[33m'; c_rst=$'\e[0m'
|
||||
ok(){ echo "${c_grn}$*${c_rst}"; }
|
||||
warn(){ echo "${c_yel}$*${c_rst}"; }
|
||||
err(){ echo "${c_red}$*${c_rst}" >&2; }
|
||||
|
||||
svc_count(){ local n; n="$(pgrep -xc inspire_g1 2>/dev/null)"; echo "${n:-0}"; }
|
||||
svc_running(){ [ "$(svc_count)" -ge 1 ]; }
|
||||
have_devices(){ [ -e /dev/ttyUSB0 ] && [ -e /dev/ttyUSB1 ]; }
|
||||
writable(){ [ -w /dev/ttyUSB0 ] && [ -w /dev/ttyUSB1 ]; }
|
||||
need_build(){ [ -x "$SVC" ] || { err "binaries missing — run: ./manage.sh build"; exit 1; }; }
|
||||
|
||||
show_devices(){
|
||||
echo "Hand serial (ttyUSB0=right, ttyUSB1=left):"
|
||||
if have_devices; then
|
||||
ls -l /dev/ttyUSB0 /dev/ttyUSB1 2>&1 | sed 's/^/ /'
|
||||
writable || warn " NOT writable — run the udev rule (see SETUP_G1.md §2) or sudo chmod 666."
|
||||
else warn " /dev/ttyUSB0+1 MISSING — plug in the two CH340 hand adapters."; fi
|
||||
echo "CH340 adapters (lsusb):"
|
||||
lsusb | grep -i "1a86" | sed 's/^/ /' || warn " none detected"
|
||||
}
|
||||
|
||||
cmd_status(){
|
||||
local n; n="$(svc_count)"
|
||||
if [ "$n" -eq 0 ]; then warn "inspire_g1: NOT running"
|
||||
elif [ "$n" -eq 1 ]; then ok "inspire_g1: running ($(pgrep -x inspire_g1))"
|
||||
else err "inspire_g1: $n INSTANCES running — duplicates corrupt the serial bus! run: ./manage.sh restart"; fi
|
||||
show_devices
|
||||
}
|
||||
|
||||
cmd_wait(){
|
||||
echo "Waiting for hand adapters — plug in the two USB-RS485 dongles now (Ctrl+C to stop)..."
|
||||
while ! have_devices; do
|
||||
printf "\r CH340 on bus: %s ttyUSB0:%s ttyUSB1:%s " \
|
||||
"$(lsusb | grep -ci 1a86)" \
|
||||
"$([ -e /dev/ttyUSB0 ] && echo ✓ || echo ✗)" \
|
||||
"$([ -e /dev/ttyUSB1 ] && echo ✓ || echo ✗)"
|
||||
sleep 1
|
||||
done
|
||||
echo; ok "Adapters detected!"; show_devices
|
||||
}
|
||||
|
||||
cmd_stop(){ pkill -x inspire_g1 2>/dev/null; sleep 1; pkill -9 -x inspire_g1 2>/dev/null; ok "stopped"; }
|
||||
|
||||
cmd_start(){
|
||||
need_build
|
||||
if svc_running; then warn "already running ($(svc_count) instance(s)); use restart to reset"; return 0; fi
|
||||
have_devices || warn "WARNING: /dev/inspire_* missing — fingers won't move until adapters are plugged in."
|
||||
( cd "$BUILD" && setsid nohup "$SVC" >"$LOG" 2>&1 </dev/null & )
|
||||
sleep 2
|
||||
if svc_running; then ok "started (pid $(pgrep -x inspire_g1))"; sed 's/^/ /' "$LOG"
|
||||
else err "FAILED to start — log:"; cat "$LOG"; return 1; fi
|
||||
}
|
||||
|
||||
cmd_restart(){ cmd_stop; cmd_start; }
|
||||
|
||||
ensure_service(){ svc_running || { echo "(starting inspire_g1...)"; cmd_start || exit 1; }
|
||||
[ "$(svc_count)" -gt 1 ] && { warn "multiple instances; resetting"; cmd_restart; }; return 0; }
|
||||
|
||||
hand_gesture(){ need_build; ensure_service; "$BUILD/hand_gestures" "$@"; }
|
||||
fused(){ need_build; ensure_service; warn "ARM WILL MOVE — clear space, E-stop ready."; "$BUILD/$1" "${@:2}" "$IFACE"; }
|
||||
|
||||
cmd="${1:-status}"; shift || true
|
||||
case "$cmd" in
|
||||
status|st) cmd_status ;;
|
||||
devices|dev) show_devices ;;
|
||||
wait) cmd_wait ;;
|
||||
build) "$HERE/build.sh" ;;
|
||||
start) cmd_start ;;
|
||||
stop) cmd_stop ;;
|
||||
restart) cmd_restart ;;
|
||||
logs) tail -n 40 -f "$LOG" ;;
|
||||
example) need_build; ensure_service; "$BUILD/hand_example" "$IFACE" ;;
|
||||
menu) hand_gesture ;;
|
||||
open|close|box|combo|demo) hand_gesture "$cmd" ;;
|
||||
pose) need_build; ensure_service; "$BUILD/hand_pose" "$IFACE" ;;
|
||||
record) need_build; ensure_service; "$BUILD/hand_record" "$IFACE" ;;
|
||||
poses) need_build; "$BUILD/hand_record" list ;;
|
||||
play) need_build; ensure_service; "$BUILD/hand_record" play "$@" "$IFACE" ;;
|
||||
dashboard) need_build; ensure_service
|
||||
pkill -x hand_bridge 2>/dev/null; pkill -f "hand_web.py" 2>/dev/null; sleep 1
|
||||
setsid "$BUILD/hand_bridge" "$IFACE" 7799 >/tmp/hand_bridge.log 2>&1 </dev/null &
|
||||
setsid python3 "$HERE/web/hand_web.py" >/tmp/hand_web.log 2>&1 </dev/null &
|
||||
sleep 2
|
||||
ip=$(hostname -I | awk "{print \$1}")
|
||||
pgrep -x hand_bridge >/dev/null && echo " bridge: up" || { echo " bridge FAILED:"; sed "s/^/ /" /tmp/hand_bridge.log; }
|
||||
grep -q "Running on" /tmp/hand_web.log && ok ">> Dashboard: http://$ip:8088 (also the wifi IP:8088)" || { echo " web FAILED:"; sed "s/^/ /" /tmp/hand_web.log | tail -4; }
|
||||
exit 0 ;;
|
||||
dashboard-stop) pkill -x hand_bridge 2>/dev/null; pkill -f "hand_web.py" 2>/dev/null; ok "dashboard stopped" ;;
|
||||
like) fused like "$@" ;;
|
||||
handshake) fused handshake ;;
|
||||
thumbup) fused thumbup ;;
|
||||
arm) need_build; "$BUILD/arm_action" "$@" "$IFACE" ;;
|
||||
armlist) need_build; "$BUILD/arm_action" list "$IFACE" ;;
|
||||
help|-h|--help) sed -n '2,40p' "$0" | sed 's/^# \{0,1\}//' ;;
|
||||
*) err "unknown command: $cmd"; echo "run: ./manage.sh help"; exit 1 ;;
|
||||
esac
|
||||
BIN
recorder/__pycache__/g1_record_replay.cpython-313.pyc
Normal file
BIN
recorder/__pycache__/g1_record_replay.cpython-313.pyc
Normal file
Binary file not shown.
482
recorder/arm_home.jsonl
Normal file
482
recorder/arm_home.jsonl
Normal file
@ -0,0 +1,482 @@
|
||||
{"meta": {"hz": 60.0, "motors": 29}}
|
||||
{"t": 0.0, "q": [-0.3130820691585541, -0.01388593576848507, 0.015708694234490395, 0.6304575800895691, -0.326513409614563, 0.021098745986819267, -0.3218769133090973, 0.030117155984044075, -0.014771261252462864, 0.6223444938659668, -0.3365834653377533, -0.021014997735619545, 0.002691771136596799, 0.006411683280020952, -0.0298378374427557, 0.29042571783065796, 0.2159797102212906, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.0167, "q": [-0.3130394518375397, -0.01388593576848507, 0.015722084790468216, 0.6305854320526123, -0.3265092968940735, 0.02109152264893055, -0.3218769133090973, 0.030117155984044075, -0.01478465273976326, 0.6224552989006042, -0.3365916609764099, -0.021000416949391365, 0.002691771136596799, 0.006411683280020952, -0.0298378374427557, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.061706773936748505, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 0.0336, "q": [-0.31300538778305054, -0.01388593576848507, 0.015708694234490395, 0.6306195259094238, -0.3265010416507721, 0.021077075973153114, -0.32190245389938354, 0.030100110918283463, -0.01478465273976326, 0.6225661039352417, -0.3365834653377533, -0.02100047469139099, 0.002691771136596799, 0.006464851088821888, -0.029813440516591072, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.2237934172153473, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.0503, "q": [-0.3129883408546448, -0.013868890702724457, 0.015695301815867424, 0.6306791305541992, -0.3265010416507721, 0.021077075973153114, -0.32190245389938354, 0.03009158931672573, -0.014771261252462864, 0.6225916743278503, -0.3365834653377533, -0.02100047469139099, 0.002691771136596799, 0.006480046082288027, -0.029823286458849907, 0.2904616594314575, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.067, "q": [-0.3129883408546448, -0.013868890702724457, 0.015681909397244453, 0.6306791305541992, -0.3265092968940735, 0.02109152264893055, -0.32190245389938354, 0.03009158931672573, -0.014771261252462864, 0.622617244720459, -0.33660396933555603, -0.020978543907403946, 0.002731946762651205, 0.006480061449110508, -0.029862530529499054, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9791951179504395, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.0838, "q": [-0.3129883408546448, -0.013868890702724457, 0.015681909397244453, 0.6307047009468079, -0.3265092968940735, 0.02109152264893055, -0.3219280242919922, 0.030066022649407387, -0.014731084927916527, 0.6226428151130676, -0.33661219477653503, -0.020963944494724274, 0.0026783791836351156, 0.00641929917037487, -0.029891815036535263, 0.2904856503009796, 0.21596772968769073, -0.005201153922826052, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.1005, "q": [-0.31299686431884766, -0.013868890702724457, 0.01565512642264366, 0.6307217478752136, -0.3265175223350525, 0.021076949313282967, -0.32195359468460083, 0.030066022649407387, -0.014757868833839893, 0.6226428151130676, -0.33660808205604553, -0.02095671370625496, 0.002718554809689522, 0.00648766802623868, -0.02988707646727562, 0.2905096113681793, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.1172, "q": [-0.3130139112472534, -0.013843324035406113, 0.015601558610796928, 0.6307047009468079, -0.326513409614563, 0.021098745986819267, -0.32194507122039795, 0.030057501047849655, -0.014757868833839893, 0.6226342916488647, -0.33662450313568115, -0.02097111940383911, 0.0026783791836351156, 0.006510468199849129, -0.0299018993973732, 0.2905455529689789, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.29507559537887573, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.134, "q": [-0.31304797530174255, -0.013851847499608994, 0.015588166192173958, 0.6307047009468079, -0.326521635055542, 0.021084172651171684, -0.32203882932662964, 0.030048979446291924, -0.014757868833839893, 0.6226513385772705, -0.33662450313568115, -0.02097111940383911, 0.0027051628567278385, 0.00654088007286191, -0.02994132786989212, 0.2905455529689789, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950875759124756, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008832373656332493]}
|
||||
{"t": 0.1507, "q": [-0.31309911608695984, -0.013843324035406113, 0.015588166192173958, 0.6307047009468079, -0.326521635055542, 0.021084172651171684, -0.3220984637737274, 0.030040455982089043, -0.014731084927916527, 0.6226428151130676, -0.3366450071334839, -0.020963728427886963, 0.0026382035575807095, 0.006464953999966383, -0.03002951480448246, 0.2905455529689789, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29509955644607544, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18353840708732605, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 0.1676, "q": [-0.3131246864795685, -0.013851847499608994, 0.015574774704873562, 0.6307132244110107, -0.326521635055542, 0.021084172651171684, -0.32217517495155334, 0.03003193438053131, -0.01470430102199316, 0.6226428151130676, -0.336649090051651, -0.020941896364092827, 0.0027989062946289778, 0.006419417914003134, -0.030117813497781754, 0.2905455529689789, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2951115369796753, -0.22380541265010834, 0.023093601688742638, 0.9781045317649841, -0.1835503876209259, 0.05241899937391281, 0.008832373656332493]}
|
||||
{"t": 0.1843, "q": [-0.3132099211215973, -0.013851847499608994, 0.015574774704873562, 0.6307132244110107, -0.326521635055542, 0.021098682656884193, -0.32222631573677063, 0.03003193438053131, -0.01471769344061613, 0.6226428151130676, -0.3366532027721405, -0.020934605970978737, 0.0027721223887056112, 0.006389044225215912, -0.030147191137075424, 0.2905455529689789, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.0409141443669796, 0.2950875759124756, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.201, "q": [-0.3132610321044922, -0.013851847499608994, 0.015574774704873562, 0.6307047009468079, -0.326521635055542, 0.021098682656884193, -0.32230299711227417, 0.030014891177415848, -0.014677518047392368, 0.6226428151130676, -0.33665731549263, -0.020956380292773247, 0.002731946762651205, 0.006381465587764978, -0.03018156625330448, 0.29053357243537903, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15754462778568268, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.2177, "q": [-0.3133121728897095, -0.013851847499608994, 0.015601558610796928, 0.6307047009468079, -0.3265340030193329, 0.021091332659125328, -0.32239675521850586, 0.03002341277897358, -0.014637341722846031, 0.6226257681846619, -0.3366696238517761, -0.02094901166856289, 0.002691771136596799, 0.00633589131757617, -0.030201058834791183, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15755660831928253, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.02310558594763279, 0.9780685901641846, -0.18358634412288666, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.2345, "q": [-0.3133974075317383, -0.013851847499608994, 0.015614950098097324, 0.6307047009468079, -0.3265298902988434, 0.02109861932694912, -0.3224649131298065, 0.029997846111655235, -0.014610557816922665, 0.6226257681846619, -0.33667370676994324, -0.020985309034585953, 0.002718554809689522, 0.006320723332464695, -0.030250148847699165, 0.2904736399650574, 0.21594375371932983, -0.005201153922826052, 0.9791951179504395, 0.15762852132320404, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.2512, "q": [-0.3135252296924591, -0.013860369101166725, 0.015588166192173958, 0.6306791305541992, -0.3265340030193329, 0.021105842664837837, -0.3226012885570526, 0.030006367713212967, -0.014637341722846031, 0.6226257681846619, -0.33666959404945374, -0.02097807638347149, 0.0026649872306734324, 0.0062523758970201015, -0.030303962528705597, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.0409141443669796, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.2679, "q": [-0.3136274814605713, -0.013877412304282188, 0.015614950098097324, 0.6307047009468079, -0.3265257775783539, 0.02110590599477291, -0.32262685894966125, 0.029997846111655235, -0.014637341722846031, 0.6226342916488647, -0.33666959404945374, -0.02097807638347149, 0.002731946762651205, 0.006108071189373732, -0.03038698434829712, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 0.2846, "q": [-0.3136615753173828, -0.013894457370042801, 0.01562834158539772, 0.6307047009468079, -0.3265257775783539, 0.021091395989060402, -0.3226609230041504, 0.029997846111655235, -0.014677518047392368, 0.6226342916488647, -0.3366449773311615, -0.021021820604801178, 0.0026382035575807095, 0.006092881318181753, -0.030396757647395134, 0.29042571783065796, 0.21596772968769073, -0.005201153922826052, 0.9791830778121948, 0.15760454535484314, 0.06169478967785835, -0.04087819159030914, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.3014, "q": [-0.3137127161026001, -0.01388593576848507, 0.01565512642264366, 0.630696177482605, -0.3265133798122406, 0.02111327461898327, -0.32266944646835327, 0.030014891177415848, -0.014677518047392368, 0.6226257681846619, -0.3366490602493286, -0.021029053255915642, 0.0026783791836351156, 0.006054885685443878, -0.03038187511265278, 0.2904137372970581, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.1575925648212433, 0.06169478967785835, -0.04092612862586975, 0.295051634311676, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 0.3181, "q": [-0.31372976303100586, -0.013894457370042801, 0.01564173400402069, 0.6307047009468079, -0.326521635055542, 0.021113192662596703, -0.32267796993255615, 0.030014891177415848, -0.014677518047392368, 0.6226342916488647, -0.3366572856903076, -0.021014470607042313, 0.002731946762651205, 0.005994115956127644, -0.030401311814785004, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.3348, "q": [-0.3137127161026001, -0.01395411230623722, 0.01565512642264366, 0.6307047009468079, -0.326521635055542, 0.021113192662596703, -0.32268649339675903, 0.030014891177415848, -0.014664125628769398, 0.6226342916488647, -0.3366572856903076, -0.021014470607042313, 0.0026783791836351156, 0.0061156307347118855, -0.030323121696710587, 0.29044967889785767, 0.21594375371932983, -0.0051891696639359, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04086620733141899, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.3515, "q": [-0.31373828649520874, -0.01395411230623722, 0.015668518841266632, 0.6307047009468079, -0.326521635055542, 0.021113192662596703, -0.32267796993255615, 0.030014891177415848, -0.014677518047392368, 0.6226428151130676, -0.3366367518901825, -0.021050943061709404, 0.0027051628567278385, 0.006085248664021492, -0.030332839116454124, 0.29044967889785767, 0.21594375371932983, -0.005225121974945068, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 0.3683, "q": [-0.3137127161026001, -0.01394559070467949, 0.015668518841266632, 0.6307132244110107, -0.3265175223350525, 0.021105969324707985, -0.32266944646835327, 0.03002341277897358, -0.014690909534692764, 0.6226769089698792, -0.3366285562515259, -0.021036479622125626, 0.002731946762651205, 0.006153599359095097, -0.030288858339190483, 0.29040175676345825, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06169478967785835, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 0.3851, "q": [-0.3137127161026001, -0.01395411230623722, 0.015668518841266632, 0.6307047009468079, -0.3265133798122406, 0.02111327461898327, -0.3226609230041504, 0.03003193438053131, -0.014731084927916527, 0.6227110028266907, -0.3366244435310364, -0.02105829305946827, 0.002731946762651205, 0.006100435741245747, -0.03032306581735611, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.29499170184135437, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.0088803106918931]}
|
||||
{"t": 0.4018, "q": [-0.3136786222457886, -0.013962633907794952, 0.015695301815867424, 0.6307302713394165, -0.326521635055542, 0.021113192662596703, -0.3226523995399475, 0.03003193438053131, -0.01471769344061613, 0.6227365136146545, -0.33662036061286926, -0.02106558345258236, 0.0027453387156128883, 0.006123214494436979, -0.03029857575893402, 0.2904137372970581, 0.21594375371932983, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.29503965377807617, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.4185, "q": [-0.3136615753173828, -0.013962633907794952, 0.015681909397244453, 0.6307473182678223, -0.3265051543712616, 0.021113337948918343, -0.3226523995399475, 0.03003193438053131, -0.014731084927916527, 0.6228047013282776, -0.3366244435310364, -0.021072816103696823, 0.0026649872306734324, 0.006108025088906288, -0.030308350920677185, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.4352, "q": [-0.31363600492477417, -0.013971157371997833, 0.015735477209091187, 0.6308155059814453, -0.3265092670917511, 0.02110605128109455, -0.32263535261154175, 0.03003193438053131, -0.014690909534692764, 0.6228643655776978, -0.33662036061286926, -0.02106558345258236, 0.002691771136596799, 0.006100419443100691, -0.030293578281998634, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.452, "q": [-0.3136189579963684, -0.013971157371997833, 0.015722084790468216, 0.6308666467666626, -0.3265092670917511, 0.02110605128109455, -0.32262685894966125, 0.030040455982089043, -0.014690909534692764, 0.6229410767555237, -0.3366244435310364, -0.02105829305946827, 0.002691771136596799, 0.006138376891613007, -0.030239654704928398, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15765248239040375, 0.06167082488536835, -0.040890175849199295, 0.2950156629085541, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.4687, "q": [-0.31359341740608215, -0.013979678973555565, 0.015748869627714157, 0.6308922171592712, -0.326513409614563, 0.021098745986819267, -0.32262685894966125, 0.030014891177415848, -0.014677518047392368, 0.6229836940765381, -0.336632639169693, -0.021058233454823494, 0.002691771136596799, 0.006183940451592207, -0.030200503766536713, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04092612862586975, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 0.4854, "q": [-0.3135848939418793, -0.013979678973555565, 0.015748869627714157, 0.6309177875518799, -0.3265092670917511, 0.02110605128109455, -0.3226098120212555, 0.030014891177415848, -0.014677518047392368, 0.6230263113975525, -0.336640864610672, -0.021043652668595314, 0.0027051628567278385, 0.00623712595552206, -0.030205613002181053, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.5022, "q": [-0.3135763704776764, -0.013971157371997833, 0.015735477209091187, 0.6310114860534668, -0.3265092968940735, 0.02109152264893055, -0.3226012885570526, 0.030014891177415848, -0.014677518047392368, 0.6230774521827698, -0.3366326689720154, -0.02104371041059494, 0.002691771136596799, 0.006206746678799391, -0.030225161463022232, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.0088803106918931]}
|
||||
{"t": 0.519, "q": [-0.3135763704776764, -0.01395411230623722, 0.015708694234490395, 0.631071150302887, -0.326513409614563, 0.021098745986819267, -0.3226012885570526, 0.030014891177415848, -0.014690909534692764, 0.6231200098991394, -0.3366285562515259, -0.021065523847937584, 0.002718554809689522, 0.006183956749737263, -0.030229991301894188, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9791951179504395, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.5357, "q": [-0.31354227662086487, -0.013962633907794952, 0.015708694234490395, 0.6310626268386841, -0.3265092968940735, 0.02107701264321804, -0.32259276509284973, 0.029997846111655235, -0.014677518047392368, 0.6231285333633423, -0.3366367518901825, -0.02103642001748085, 0.002718554809689522, 0.006176367402076721, -0.03024470806121826, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.5524, "q": [-0.31355932354927063, -0.01394559070467949, 0.015681909397244453, 0.6311052441596985, -0.3265092968940735, 0.02109152264893055, -0.3226012885570526, 0.030006367713212967, -0.014690909534692764, 0.6231541037559509, -0.336649090051651, -0.021014530211687088, 0.0027721223887056112, 0.006252326536923647, -0.030215498059988022, 0.2905096113681793, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15765248239040375, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 0.5692, "q": [-0.31355080008506775, -0.013928545638918877, 0.015681909397244453, 0.6311222910881042, -0.3265175223350525, 0.021091459318995476, -0.3226183354854584, 0.029997846111655235, -0.014677518047392368, 0.6231541037559509, -0.336649090051651, -0.021000007167458534, 0.002718554809689522, 0.006290311459451914, -0.030210722237825394, 0.2904856503009796, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 0.5859, "q": [-0.31354227662086487, -0.013920024037361145, 0.015681909397244453, 0.63113933801651, -0.3265175223350525, 0.021091459318995476, -0.3226012885570526, 0.029997846111655235, -0.014664125628769398, 0.6231626272201538, -0.3366408944129944, -0.021014587953686714, 0.002731946762651205, 0.0062143742106854916, -0.03027925081551075, 0.29053357243537903, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 0.6026, "q": [-0.31355080008506775, -0.01395411230623722, 0.015668518841266632, 0.6311734318733215, -0.3265257775783539, 0.021091395989060402, -0.32259276509284973, 0.029997846111655235, -0.014650734141469002, 0.623145580291748, -0.3366449773311615, -0.021007297560572624, 0.0027989062946289778, 0.006176416762173176, -0.030333172529935837, 0.2905096113681793, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22378143668174744, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 0.6193, "q": [-0.31355080008506775, -0.01394559070467949, 0.015668518841266632, 0.6311819553375244, -0.326521635055542, 0.021098682656884193, -0.32257571816444397, 0.029997846111655235, -0.014637341722846031, 0.6231541037559509, -0.3366572856903076, -0.020985424518585205, 0.0027051628567278385, 0.006206796038895845, -0.030313625931739807, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.04090216010808945, 0.29507559537887573, -0.22378143668174744, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.6361, "q": [-0.3135848939418793, -0.013920024037361145, 0.01565512642264366, 0.6311904788017273, -0.326521635055542, 0.021084172651171684, -0.32264387607574463, 0.029997846111655235, -0.014637341722846031, 0.6231541037559509, -0.3366572856903076, -0.021014470607042313, 0.002691771136596799, 0.006199211813509464, -0.030338170006871223, 0.29053357243537903, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.29509955644607544, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.6529, "q": [-0.31359341740608215, -0.013928545638918877, 0.015668518841266632, 0.6311990022659302, -0.326521635055542, 0.021098682656884193, -0.32264387607574463, 0.029997846111655235, -0.014637341722846031, 0.6231541037559509, -0.3366531729698181, -0.021007239818572998, 0.0027051628567278385, 0.006077686324715614, -0.030396701768040657, 0.29053357243537903, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.6697, "q": [-0.3136104345321655, -0.01395411230623722, 0.015681909397244453, 0.6312075257301331, -0.3265175223350525, 0.021105969324707985, -0.32264387607574463, 0.029980802908539772, -0.014650734141469002, 0.623145580291748, -0.3366613984107971, -0.021007180213928223, 0.0027453387156128883, 0.006115671247243881, -0.03039192594587803, 0.29049763083457947, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.6864, "q": [-0.3136104345321655, -0.01394559070467949, 0.015681909397244453, 0.6312160491943359, -0.326521635055542, 0.021113192662596703, -0.32263535261154175, 0.029989324510097504, -0.014637341722846031, 0.6231285333633423, -0.3366408944129944, -0.021014587953686714, 0.002718554809689522, 0.0060701025649905205, -0.030421247705817223, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 0.7033, "q": [-0.3136274814605713, -0.01394559070467949, 0.015681909397244453, 0.6312330961227417, -0.3265175223350525, 0.021105969324707985, -0.3226523995399475, 0.029989324510097504, -0.014637341722846031, 0.6231370568275452, -0.3366449475288391, -0.021036362275481224, 0.0027051628567278385, 0.00604731822386384, -0.03043590858578682, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 0.7201, "q": [-0.3136786222457886, -0.013971157371997833, 0.015695301815867424, 0.6312245726585388, -0.3265257775783539, 0.02110590599477291, -0.3226523995399475, 0.029980802908539772, -0.014637341722846031, 0.6231370568275452, -0.336640864610672, -0.02102912962436676, 0.002731946762651205, 0.006115671247243881, -0.03039192594587803, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 0.7368, "q": [-0.3136786222457886, -0.013962633907794952, 0.015681909397244453, 0.6312330961227417, -0.326521635055542, 0.021098682656884193, -0.3226523995399475, 0.029989324510097504, -0.014637341722846031, 0.623145580291748, -0.3366490602493286, -0.021029053255915642, 0.002718554809689522, 0.006115660537034273, -0.030372267588973045, 0.29042571783065796, 0.21594375371932983, -0.005213138181716204, 0.9791830778121948, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 0.7535, "q": [-0.3136700987815857, -0.013962633907794952, 0.015695301815867424, 0.6312501430511475, -0.326521635055542, 0.021084172651171684, -0.3226609230041504, 0.029997846111655235, -0.014637341722846031, 0.6231370568275452, -0.3366449773311615, -0.021021820604801178, 0.002758730435743928, 0.006100476253777742, -0.030391870066523552, 0.29040175676345825, 0.21596772968769073, -0.0051891696639359, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950156629085541, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.7702, "q": [-0.31369566917419434, -0.013979678973555565, 0.015708694234490395, 0.6312330961227417, -0.3265175223350525, 0.021105969324707985, -0.3226609230041504, 0.029989324510097504, -0.014677518047392368, 0.6231370568275452, -0.336640864610672, -0.021043652668595314, 0.002718554809689522, 0.006070069968700409, -0.030362272635102272, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.2950156629085541, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.787, "q": [-0.3136786222457886, -0.013979678973555565, 0.015695301815867424, 0.6312330961227417, -0.326521635055542, 0.021113192662596703, -0.32267796993255615, 0.029997846111655235, -0.01470430102199316, 0.6231541037559509, -0.3366285562515259, -0.021036479622125626, 0.002718554809689522, 0.006100454367697239, -0.030352553352713585, 0.2904376983642578, 0.21594375371932983, -0.0051891696639359, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04087819159030914, 0.2950156629085541, -0.2238173931837082, 0.02310558594763279, 0.9780925512313843, -0.1835743635892868, 0.052442967891693115, 0.008844357915222645]}
|
||||
{"t": 0.8037, "q": [-0.31363600492477417, -0.013979678973555565, 0.015708694234490395, 0.6312330961227417, -0.3265175223350525, 0.021105969324707985, -0.3226609230041504, 0.030006367713212967, -0.014664125628769398, 0.6231541037559509, -0.3366367518901825, -0.021050943061709404, 0.002691771136596799, 0.006115636322647333, -0.03033295087516308, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.8204, "q": [-0.3136700987815857, -0.013979678973555565, 0.015708694234490395, 0.6312330961227417, -0.326513409614563, 0.021098745986819267, -0.32264387607574463, 0.030006367713212967, -0.01470430102199316, 0.6231541037559509, -0.3366285562515259, -0.02105100080370903, 0.0027453387156128883, 0.006100441329181194, -0.03033289685845375, 0.2904376983642578, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 0.8372, "q": [-0.31364452838897705, -0.013971157371997833, 0.015708694234490395, 0.6312245726585388, -0.3265175223350525, 0.021105969324707985, -0.32264387607574463, 0.030014891177415848, -0.01471769344061613, 0.6231626272201538, -0.336640864610672, -0.021043652668595314, 0.002691771136596799, 0.006123231258243322, -0.030328065156936646, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.8539, "q": [-0.31364452838897705, -0.013971157371997833, 0.015708694234490395, 0.6312330961227417, -0.326521635055542, 0.021098682656884193, -0.3226609230041504, 0.030014891177415848, -0.014731084927916527, 0.6231711506843567, -0.3366326689720154, -0.021029187366366386, 0.002718554809689522, 0.00625234842300415, -0.03025481477379799, 0.2904616594314575, 0.2159797102212906, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.8706, "q": [-0.31365305185317993, -0.013962633907794952, 0.015695301815867424, 0.6312330961227417, -0.3265092670917511, 0.02110605128109455, -0.3226523995399475, 0.03002341277897358, -0.014677518047392368, 0.6231881976127625, -0.3366326689720154, -0.021029187366366386, 0.002731946762651205, 0.006168789230287075, -0.03027908317744732, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.0409141443669796, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 0.8873, "q": [-0.31365305185317993, -0.01394559070467949, 0.015722084790468216, 0.6312501430511475, -0.326513409614563, 0.021098745986819267, -0.3226523995399475, 0.03002341277897358, -0.014690909534692764, 0.623222291469574, -0.3366326689720154, -0.021029187366366386, 0.0026783791836351156, 0.0061611998826265335, -0.030293799936771393, 0.2904616594314575, 0.21594375371932983, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.9041, "q": [-0.3136189579963684, -0.013962633907794952, 0.015708694234490395, 0.6312586665153503, -0.326521635055542, 0.021113192662596703, -0.3226609230041504, 0.030014891177415848, -0.014677518047392368, 0.6232308149337769, -0.336640864610672, -0.021043652668595314, 0.002718554809689522, 0.006199179217219353, -0.030279194936156273, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.061658840626478195, -0.040890175849199295, 0.29502764344215393, -0.22378143668174744, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.9209, "q": [-0.31363600492477417, -0.013962633907794952, 0.015695301815867424, 0.6312671899795532, -0.326513409614563, 0.021098745986819267, -0.32264387607574463, 0.030014891177415848, -0.014677518047392368, 0.6232649087905884, -0.3366367518901825, -0.02103642001748085, 0.002718554809689522, 0.006191589869558811, -0.030293911695480347, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15755660831928253, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.9376, "q": [-0.3136189579963684, -0.01395411230623722, 0.015681909397244453, 0.6313012838363647, -0.326513409614563, 0.021098745986819267, -0.32263535261154175, 0.030014891177415848, -0.014690909534692764, 0.6232819557189941, -0.3366285562515259, -0.02105100080370903, 0.0026783791836351156, 0.006168805528432131, -0.030308572575449944, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 0.9543, "q": [-0.3136189579963684, -0.013971157371997833, 0.015708694234490395, 0.6313268542289734, -0.3265175223350525, 0.021091459318995476, -0.3226523995399475, 0.029997846111655235, -0.014690909534692764, 0.6233245730400085, -0.3366285562515259, -0.021036479622125626, 0.0026783791836351156, 0.006244780961424112, -0.03030884824693203, 0.2904736399650574, 0.2159797102212906, -0.005213138181716204, 0.9791830778121948, 0.15762852132320404, 0.06167082488536835, -0.04087819159030914, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.0088803106918931]}
|
||||
{"t": 0.9711, "q": [-0.31360191106796265, -0.013971157371997833, 0.015681909397244453, 0.6313268542289734, -0.326513409614563, 0.021098745986819267, -0.3226523995399475, 0.030014891177415848, -0.014677518047392368, 0.6233330965042114, -0.3366572856903076, -0.020985424518585205, 0.002718554809689522, 0.006161210592836142, -0.030313458293676376, 0.2905096113681793, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06169478967785835, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9781045317649841, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 0.9878, "q": [-0.31359341740608215, -0.01395411230623722, 0.015681909397244453, 0.6313353776931763, -0.3265175223350525, 0.021091459318995476, -0.32264387607574463, 0.029997846111655235, -0.014677518047392368, 0.6233160495758057, -0.3366613984107971, -0.02099265716969967, 0.002718554809689522, 0.006199206691235304, -0.03032834082841873, 0.2904736399650574, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04087819159030914, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.005, "q": [-0.31360191106796265, -0.013962633907794952, 0.015681909397244453, 0.631352424621582, -0.3265175223350525, 0.021091459318995476, -0.32264387607574463, 0.029997846111655235, -0.014677518047392368, 0.6233416199684143, -0.33666548132896423, -0.020999889820814133, 0.0027051628567278385, 0.00619922298938036, -0.030357830226421356, 0.2904736399650574, 0.21593177318572998, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.0409141443669796, 0.29507559537887573, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 1.0217, "q": [-0.3136104345321655, -0.013971157371997833, 0.01564173400402069, 0.631352424621582, -0.326513409614563, 0.021098745986819267, -0.3226523995399475, 0.029989324510097504, -0.014664125628769398, 0.6233245730400085, -0.3366613984107971, -0.02099265716969967, 0.002691771136596799, 0.006191622465848923, -0.030352886766195297, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950875759124756, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 1.0384, "q": [-0.3136274814605713, -0.01394559070467949, 0.015668518841266632, 0.6313439011573792, -0.3265257775783539, 0.02110590599477291, -0.32267796993255615, 0.029989324510097504, -0.014690909534692764, 0.6233330965042114, -0.3366613984107971, -0.02099265716969967, 0.0026649872306734324, 0.006191633641719818, -0.03037254512310028, 0.2905096113681793, 0.21593177318572998, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.0552, "q": [-0.31360191106796265, -0.013962633907794952, 0.015668518841266632, 0.631352424621582, -0.326513409614563, 0.021098745986819267, -0.32268649339675903, 0.029980802908539772, -0.014664125628769398, 0.6233330965042114, -0.33666548132896423, -0.020999889820814133, 0.0027453387156128883, 0.006222012918442488, -0.03035299852490425, 0.29049763083457947, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.0719, "q": [-0.31363600492477417, -0.01395411230623722, 0.01565512642264366, 0.6313609480857849, -0.3265257775783539, 0.021091395989060402, -0.32268649339675903, 0.029980802908539772, -0.014637341722846031, 0.6233330965042114, -0.3366572856903076, -0.020985424518585205, 0.0026649872306734324, 0.006206828635185957, -0.030372601002454758, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.0887, "q": [-0.31363600492477417, -0.013971157371997833, 0.015681909397244453, 0.631352424621582, -0.3265133798122406, 0.02111327461898327, -0.32268649339675903, 0.02996375784277916, -0.014677518047392368, 0.6233330965042114, -0.3366572856903076, -0.021014470607042313, 0.002691771136596799, 0.006222023628652096, -0.030372656881809235, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.1054, "q": [-0.31365305185317993, -0.013971157371997833, 0.015668518841266632, 0.631352424621582, -0.326521635055542, 0.021098682656884193, -0.3226950168609619, 0.029980802908539772, -0.014650734141469002, 0.6233416199684143, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.006153656169772148, -0.0303871501237154, 0.2904616594314575, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 1.1222, "q": [-0.3136615753173828, -0.013962633907794952, 0.015668518841266632, 0.6313439011573792, -0.3265175223350525, 0.021120497956871986, -0.3226950168609619, 0.029980802908539772, -0.014637341722846031, 0.6233330965042114, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.006070108152925968, -0.030431076884269714, 0.2904616594314575, 0.2159557342529297, -0.0051891696639359, 0.9791830778121948, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.2237934172153473, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.1389, "q": [-0.3136700987815857, -0.013962633907794952, 0.015695301815867424, 0.631352424621582, -0.326521635055542, 0.021098682656884193, -0.32272058725357056, 0.029980802908539772, -0.014650734141469002, 0.6233330965042114, -0.3366572856903076, -0.020985424518585205, 0.0026649872306734324, 0.006130866706371307, -0.030391981825232506, 0.2904856503009796, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.15762852132320404, 0.061706773936748505, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 1.1556, "q": [-0.3136615753173828, -0.013971157371997833, 0.015695301815867424, 0.6313694715499878, -0.326521635055542, 0.021098682656884193, -0.32272058725357056, 0.029980802908539772, -0.014637341722846031, 0.6233330965042114, -0.3366490602493286, -0.021029053255915642, 0.0027051628567278385, 0.00610808189958334, -0.030406642705202103, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04092612862586975, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.1723, "q": [-0.3137041926383972, -0.013971157371997833, 0.015695301815867424, 0.631352424621582, -0.3265257775783539, 0.02110590599477291, -0.3227376341819763, 0.029980802908539772, -0.014637341722846031, 0.6233330965042114, -0.3366572856903076, -0.021014470607042313, 0.002691771136596799, 0.00610808189958334, -0.030406642705202103, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.061706773936748505, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.1891, "q": [-0.3137041926383972, -0.014005245640873909, 0.015681909397244453, 0.631352424621582, -0.326521635055542, 0.021113192662596703, -0.32276320457458496, 0.02996375784277916, -0.014677518047392368, 0.6233245730400085, -0.3366613984107971, -0.02099265716969967, 0.002691771136596799, 0.006130866706371307, -0.030391981825232506, 0.29044967889785767, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 1.2058, "q": [-0.3137041926383972, -0.013979678973555565, 0.015681909397244453, 0.631352424621582, -0.3265257775783539, 0.02110590599477291, -0.3227546811103821, 0.029980802908539772, -0.014637341722846031, 0.6233330965042114, -0.33666548132896423, -0.020999889820814133, 0.002651595277711749, 0.006146050523966551, -0.03037237748503685, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.2225, "q": [-0.3137041926383972, -0.013971157371997833, 0.015681909397244453, 0.631352424621582, -0.3265175223350525, 0.021105969324707985, -0.32272058725357056, 0.02997227944433689, -0.014664125628769398, 0.6233245730400085, -0.33666548132896423, -0.020999889820814133, 0.0026649872306734324, 0.006153656169772148, -0.0303871501237154, 0.2904616594314575, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.2392, "q": [-0.31369566917419434, -0.013988200575113297, 0.015681909397244453, 0.6313609480857849, -0.326521635055542, 0.021113192662596703, -0.3227376341819763, 0.02997227944433689, -0.014637341722846031, 0.6233330965042114, -0.3366613984107971, -0.02099265716969967, 0.0027051628567278385, 0.0061232661828398705, -0.030387038365006447, 0.2904616594314575, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.2561, "q": [-0.3137041926383972, -0.013988200575113297, 0.015681909397244453, 0.6313694715499878, -0.3265298902988434, 0.02111312933266163, -0.3227376341819763, 0.029997846111655235, -0.014664125628769398, 0.6233330965042114, -0.3366613984107971, -0.021007180213928223, 0.002731946762651205, 0.006146066822111607, -0.030401866883039474, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023081617429852486, 0.9781045317649841, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.2728, "q": [-0.3137041926383972, -0.013971157371997833, 0.015668518841266632, 0.6313694715499878, -0.3265257775783539, 0.02110590599477291, -0.32272911071777344, 0.029980802908539772, -0.014677518047392368, 0.6233416199684143, -0.33666548132896423, -0.020999889820814133, 0.0027051628567278385, 0.006123277358710766, -0.03040669858455658, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.2895, "q": [-0.3137127161026001, -0.013988200575113297, 0.015681909397244453, 0.6313694715499878, -0.3265175223350525, 0.021091459318995476, -0.32272911071777344, 0.029997846111655235, -0.014690909534692764, 0.623367190361023, -0.3366490602493286, -0.021029053255915642, 0.002691771136596799, 0.006138466764241457, -0.030396923422813416, 0.29049763083457947, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22378143668174744, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.3062, "q": [-0.31369566917419434, -0.013971157371997833, 0.015681909397244453, 0.6313864588737488, -0.326513409614563, 0.021098745986819267, -0.3227546811103821, 0.029980802908539772, -0.014690909534692764, 0.6233927607536316, -0.3366449773311615, -0.021021820604801178, 0.002691771136596799, 0.006047328934073448, -0.030455566942691803, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.323, "q": [-0.3136700987815857, -0.013996722176671028, 0.015681909397244453, 0.6314205527305603, -0.3265175223350525, 0.021091459318995476, -0.3227461576461792, 0.029980802908539772, -0.014664125628769398, 0.6234439015388489, -0.3366449773311615, -0.021021820604801178, 0.002731946762651205, 0.0061005037277936935, -0.03044101782143116, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.3397, "q": [-0.3136700987815857, -0.013971157371997833, 0.015681909397244453, 0.631446123123169, -0.3265175223350525, 0.021091459318995476, -0.3227376341819763, 0.029989324510097504, -0.014664125628769398, 0.6234779357910156, -0.3366449773311615, -0.021021820604801178, 0.0027051628567278385, 0.006100498139858246, -0.030431188642978668, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 1.3564, "q": [-0.3136786222457886, -0.013988200575113297, 0.015681909397244453, 0.6314802169799805, -0.326513409614563, 0.021098745986819267, -0.32272911071777344, 0.029980802908539772, -0.014637341722846031, 0.6235035061836243, -0.3366408944129944, -0.021014587953686714, 0.0026649872306734324, 0.0060549345798790455, -0.030470339581370354, 0.2904856503009796, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 1.3731, "q": [-0.31365305185317993, -0.013971157371997833, 0.015695301815867424, 0.6315057873725891, -0.326513409614563, 0.021098745986819267, -0.3227461576461792, 0.02997227944433689, -0.014637341722846031, 0.6235376000404358, -0.3366449773311615, -0.021021820604801178, 0.0027453387156128883, 0.006062518805265427, -0.030445793643593788, 0.2904376983642578, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.3898, "q": [-0.3136615753173828, -0.013971157371997833, 0.015722084790468216, 0.6315398812294006, -0.326513409614563, 0.021098745986819267, -0.32272058725357056, 0.029980802908539772, -0.014664125628769398, 0.6235716938972473, -0.3366408944129944, -0.021014587953686714, 0.002691771136596799, 0.006024533417075872, -0.030450569465756416, 0.2904736399650574, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.4065, "q": [-0.3136615753173828, -0.013979678973555565, 0.015708694234490395, 0.631582498550415, -0.3265175223350525, 0.021105969324707985, -0.32272911071777344, 0.029980802908539772, -0.014690909534692764, 0.6235802173614502, -0.3366490602493286, -0.021029053255915642, 0.0026783791836351156, 0.006032133940607309, -0.030455512925982475, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04087819159030914, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.4234, "q": [-0.31364452838897705, -0.013979678973555565, 0.015708694234490395, 0.6315995454788208, -0.3265175223350525, 0.021105969324707985, -0.32272058725357056, 0.02997227944433689, -0.014664125628769398, 0.6236057877540588, -0.336640864610672, -0.021043652668595314, 0.002691771136596799, 0.006062518805265427, -0.030445793643593788, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.040890175849199295, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.4402, "q": [-0.31365305185317993, -0.013971157371997833, 0.015735477209091187, 0.6316165924072266, -0.3265092670917511, 0.02110605128109455, -0.3227546811103821, 0.02996375784277916, -0.014650734141469002, 0.623597264289856, -0.3366449773311615, -0.021021820604801178, 0.0026382035575807095, 0.006092898081988096, -0.03042624518275261, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 1.4569, "q": [-0.3136615753173828, -0.013979678973555565, 0.015695301815867424, 0.6316251158714294, -0.326521635055542, 0.021098682656884193, -0.3227376341819763, 0.02997227944433689, -0.014664125628769398, 0.6236057877540588, -0.336649090051651, -0.021014530211687088, 0.002691771136596799, 0.006100492551922798, -0.030421359464526176, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15754462778568268, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.052395034581422806, 0.008856342174112797]}
|
||||
{"t": 1.4736, "q": [-0.3136615753173828, -0.013971157371997833, 0.015695301815867424, 0.6316336393356323, -0.3265298902988434, 0.02109861932694912, -0.3227376341819763, 0.02997227944433689, -0.014650734141469002, 0.6236143112182617, -0.33666548132896423, -0.020999889820814133, 0.002731946762651205, 0.006138472352176905, -0.030406752601265907, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.4903, "q": [-0.3136786222457886, -0.013971157371997833, 0.015695301815867424, 0.6316421627998352, -0.326521635055542, 0.021113192662596703, -0.3227376341819763, 0.02997227944433689, -0.014637341722846031, 0.6236313581466675, -0.3366531729698181, -0.021021762862801552, 0.002691771136596799, 0.006062529515475035, -0.03046545200049877, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 1.5071, "q": [-0.3136786222457886, -0.013979678973555565, 0.015695301815867424, 0.6316421627998352, -0.3265175223350525, 0.021105969324707985, -0.32276320457458496, 0.02996375784277916, -0.014637341722846031, 0.6236398816108704, -0.33666959404945374, -0.021007122471928596, 0.002731946762651205, 0.006092903204262257, -0.03043607622385025, 0.2904856503009796, 0.21596772968769073, -0.0051891696639359, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.5238, "q": [-0.3136786222457886, -0.013979678973555565, 0.015681909397244453, 0.6316506862640381, -0.3265175223350525, 0.021091459318995476, -0.32276320457458496, 0.02996375784277916, -0.014664125628769398, 0.6236398816108704, -0.33666548132896423, -0.020999889820814133, 0.0026649872306734324, 0.0061005037277936935, -0.03044101782143116, 0.29049763083457947, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.5406, "q": [-0.31368714570999146, -0.013988200575113297, 0.015681909397244453, 0.631659209728241, -0.326521635055542, 0.021098682656884193, -0.3227546811103821, 0.02997227944433689, -0.014637341722846031, 0.6236398816108704, -0.3366572856903076, -0.021014470607042313, 0.002691771136596799, 0.006062529515475035, -0.03046545200049877, 0.2905096113681793, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15754462778568268, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9781045317649841, -0.18358634412288666, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.5573, "q": [-0.3136786222457886, -0.013979678973555565, 0.015681909397244453, 0.6316933035850525, -0.3265175223350525, 0.021105969324707985, -0.3227546811103821, 0.02997227944433689, -0.014637341722846031, 0.6236398816108704, -0.3366572856903076, -0.021014470607042313, 0.0026649872306734324, 0.005994165316224098, -0.03048977628350258, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.574, "q": [-0.3136700987815857, -0.013996722176671028, 0.015708694234490395, 0.6316847801208496, -0.3265175223350525, 0.021091459318995476, -0.3227546811103821, 0.02997227944433689, -0.014650734141469002, 0.6236569285392761, -0.3366449773311615, -0.021021820604801178, 0.0027051628567278385, 0.006009360309690237, -0.030489832162857056, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1576405018568039, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 1.5908, "q": [-0.31368714570999146, -0.013962633907794952, 0.015695301815867424, 0.6317188739776611, -0.326521635055542, 0.021098682656884193, -0.3227546811103821, 0.029980802908539772, -0.014650734141469002, 0.6236569285392761, -0.3366367816925049, -0.021021896973252296, 0.002731946762651205, 0.0059258174151182175, -0.03054358996450901, 0.2904616594314575, 0.21594375371932983, -0.005225121974945068, 0.9792070984840393, 0.15752065181732178, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.6075, "q": [-0.31369566917419434, -0.013979678973555565, 0.015708694234490395, 0.631727397441864, -0.3265175223350525, 0.021105969324707985, -0.3227546811103821, 0.02996375784277916, -0.014650734141469002, 0.6236739754676819, -0.3366490602493286, -0.021029053255915642, 0.002691771136596799, 0.005941001698374748, -0.030523985624313354, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.6242, "q": [-0.3136786222457886, -0.013996722176671028, 0.015722084790468216, 0.6317444443702698, -0.3265175223350525, 0.021105969324707985, -0.3227546811103821, 0.02997227944433689, -0.014623950235545635, 0.6236995458602905, -0.3366367518901825, -0.02103642001748085, 0.0027051628567278385, 0.005978975910693407, -0.030499551445245743, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 1.6412, "q": [-0.3136700987815857, -0.013988200575113297, 0.015748869627714157, 0.6317529678344727, -0.3265133798122406, 0.02111327461898327, -0.32276320457458496, 0.02996375784277916, -0.014664125628769398, 0.6237251162528992, -0.3366449773311615, -0.021021820604801178, 0.0026783791836351156, 0.005986565258353949, -0.03048483468592167, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 1.658, "q": [-0.3136700987815857, -0.013979678973555565, 0.015735477209091187, 0.6317529678344727, -0.326513409614563, 0.021098745986819267, -0.32277172803878784, 0.029980802908539772, -0.014650734141469002, 0.6237677335739136, -0.336640864610672, -0.021043652668595314, 0.002731946762651205, 0.00597137538716197, -0.030494607985019684, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.6747, "q": [-0.3136786222457886, -0.013996722176671028, 0.015735477209091187, 0.6317699551582336, -0.3265175223350525, 0.021091459318995476, -0.32277172803878784, 0.02997227944433689, -0.014664125628769398, 0.6237677335739136, -0.3366408944129944, -0.021014587953686714, 0.0027453387156128883, 0.005925806704908609, -0.030523929744958878, 0.2904616594314575, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.6915, "q": [-0.3136786222457886, -0.013971157371997833, 0.015748869627714157, 0.6317699551582336, -0.326521635055542, 0.021098682656884193, -0.32276320457458496, 0.029980802908539772, -0.014623950235545635, 0.6237762570381165, -0.3366449773311615, -0.021021820604801178, 0.0026783791836351156, 0.00597137538716197, -0.030494607985019684, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780685901641846, -0.18353840708732605, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 1.7082, "q": [-0.3136615753173828, -0.013996722176671028, 0.015722084790468216, 0.6318040490150452, -0.3265257775783539, 0.021091395989060402, -0.3227546811103821, 0.029989324510097504, -0.014650734141469002, 0.6238188743591309, -0.3366490602493286, -0.021029053255915642, 0.002731946762651205, 0.00600175466388464, -0.030475059524178505, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.7249, "q": [-0.3136786222457886, -0.013971157371997833, 0.015748869627714157, 0.6318210959434509, -0.3265092670917511, 0.02110605128109455, -0.3227546811103821, 0.029980802908539772, -0.014677518047392368, 0.6238359212875366, -0.3366449773311615, -0.021021820604801178, 0.002691771136596799, 0.005994165316224098, -0.03048977628350258, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.9781045317649841, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.7417, "q": [-0.31365305185317993, -0.01401376724243164, 0.015762262046337128, 0.6318381428718567, -0.3265175223350525, 0.021091459318995476, -0.3227376341819763, 0.029980802908539772, -0.014637341722846031, 0.6239040493965149, -0.3366367816925049, -0.021021896973252296, 0.002731946762651205, 0.006024544592946768, -0.03047022968530655, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.7584, "q": [-0.3136615753173828, -0.013996722176671028, 0.015748869627714157, 0.6318637132644653, -0.3265175223350525, 0.021091459318995476, -0.32276320457458496, 0.029980802908539772, -0.014677518047392368, 0.6239210963249207, -0.3366490602493286, -0.021029053255915642, 0.002718554809689522, 0.006009349599480629, -0.030470173805952072, 0.2904736399650574, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.040890175849199295, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.7751, "q": [-0.31365305185317993, -0.014005245640873909, 0.015748869627714157, 0.631889283657074, -0.326513409614563, 0.021098745986819267, -0.3227546811103821, 0.029980802908539772, -0.014650734141469002, 0.6239551901817322, -0.3366408944129944, -0.021014587953686714, 0.002691771136596799, 0.00602453900501132, -0.030460398644208908, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.792, "q": [-0.31365305185317993, -0.013988200575113297, 0.015748869627714157, 0.6319404244422913, -0.326521635055542, 0.021098682656884193, -0.32276320457458496, 0.029980802908539772, -0.014650734141469002, 0.6240063309669495, -0.3366449773311615, -0.021021820604801178, 0.0027051628567278385, 0.006009349599480629, -0.030470173805952072, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.8087, "q": [-0.3136274814605713, -0.013996722176671028, 0.015748869627714157, 0.6319489479064941, -0.3265175223350525, 0.021091459318995476, -0.3227546811103821, 0.02997227944433689, -0.014637341722846031, 0.6240319013595581, -0.3366449773311615, -0.021021820604801178, 0.0026649872306734324, 0.006032139528542757, -0.030465342104434967, 0.29049763083457947, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835503876209259, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.8254, "q": [-0.31363600492477417, -0.013996722176671028, 0.015748869627714157, 0.6319659948348999, -0.3265175223350525, 0.021091459318995476, -0.3227546811103821, 0.029980802908539772, -0.014664125628769398, 0.6240659952163696, -0.3366449773311615, -0.021021820604801178, 0.0027051628567278385, 0.005978970322757959, -0.03048972226679325, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 1.8422, "q": [-0.3136274814605713, -0.013988200575113297, 0.015735477209091187, 0.6319915652275085, -0.326513409614563, 0.021098745986819267, -0.32276320457458496, 0.029955236241221428, -0.014650734141469002, 0.6240830421447754, -0.3366490602493286, -0.021029053255915642, 0.002718554809689522, 0.006039739586412907, -0.030470283702015877, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.8589, "q": [-0.3136274814605713, -0.013979678973555565, 0.015722084790468216, 0.6320000886917114, -0.3265175223350525, 0.021091459318995476, -0.32277172803878784, 0.02996375784277916, -0.014650734141469002, 0.624108612537384, -0.336649090051651, -0.021000007167458534, 0.002718554809689522, 0.006077708210796118, -0.030436020344495773, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9792190790176392, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.29507559537887573, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.8756, "q": [-0.31363600492477417, -0.013988200575113297, 0.015722084790468216, 0.6320000886917114, -0.326521635055542, 0.021084172651171684, -0.3227887749671936, 0.029955236241221428, -0.014650734141469002, 0.6241256594657898, -0.3366449773311615, -0.021021820604801178, 0.0027051628567278385, 0.006070118863135576, -0.030450737103819847, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 1.8926, "q": [-0.31363600492477417, -0.013996722176671028, 0.015748869627714157, 0.6320171356201172, -0.326513409614563, 0.021098745986819267, -0.32281434535980225, 0.029955236241221428, -0.014637341722846031, 0.624108612537384, -0.33666136860847473, -0.021021703258156776, 0.002718554809689522, 0.006085303146392107, -0.03043113276362419, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9781045317649841, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 1.9093, "q": [-0.31363600492477417, -0.013988200575113297, 0.015735477209091187, 0.6320086121559143, -0.3265175223350525, 0.021091459318995476, -0.3227972984313965, 0.029955236241221428, -0.014637341722846031, 0.6241256594657898, -0.33667367696762085, -0.02101435326039791, 0.0026783791836351156, 0.006070124451071024, -0.03046056628227234, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.9261, "q": [-0.31364452838897705, -0.013996722176671028, 0.015695301815867424, 0.6320171356201172, -0.3265092670917511, 0.02110605128109455, -0.32280582189559937, 0.029946712777018547, -0.014650734141469002, 0.6241256594657898, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.0060245501808822155, -0.03048005886375904, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.052442967891693115, 0.008844357915222645]}
|
||||
{"t": 1.943, "q": [-0.31364452838897705, -0.013988200575113297, 0.015668518841266632, 0.6320171356201172, -0.326521635055542, 0.021098682656884193, -0.32282283902168274, 0.029955236241221428, -0.014623950235545635, 0.624108612537384, -0.33666548132896423, -0.020999889820814133, 0.0026382035575807095, 0.0060245501808822155, -0.03048005886375904, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 1.9597, "q": [-0.31363600492477417, -0.013996722176671028, 0.015708694234490395, 0.6320256590843201, -0.326513409614563, 0.021098745986819267, -0.32280582189559937, 0.029946712777018547, -0.014637341722846031, 0.6241171360015869, -0.33666548132896423, -0.020999889820814133, 0.002718554809689522, 0.005994176026433706, -0.030509434640407562, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.29507559537887573, -0.2237934172153473, 0.023093601688742638, 0.9781045317649841, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 1.9765, "q": [-0.31363600492477417, -0.013988200575113297, 0.015695301815867424, 0.6320171356201172, -0.3265257775783539, 0.021091395989060402, -0.3228313624858856, 0.029946712777018547, -0.014650734141469002, 0.6241256594657898, -0.33667367696762085, -0.02101435326039791, 0.0027051628567278385, 0.006070130039006472, -0.03047039546072483, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.0409141443669796, 0.29507559537887573, -0.22380541265010834, 0.023069633170962334, 0.9781045317649841, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 1.9933, "q": [-0.3136615753173828, -0.013988200575113297, 0.015695301815867424, 0.6320171356201172, -0.3265298902988434, 0.02109861932694912, -0.3228825032711029, 0.029946712777018547, -0.014610557816922665, 0.6241000890731812, -0.33666548132896423, -0.020999889820814133, 0.002718554809689522, 0.006032150238752365, -0.03048500046133995, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04086620733141899, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 2.0101, "q": [-0.31369566917419434, -0.013988200575113297, 0.015708694234490395, 0.6320171356201172, -0.326521635055542, 0.021113192662596703, -0.3228825032711029, 0.029938191175460815, -0.014623950235545635, 0.624108612537384, -0.33666959404945374, -0.021007122471928596, 0.002718554809689522, 0.006024555303156376, -0.030489888042211533, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.29503965377807617, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 2.0268, "q": [-0.3137127161026001, -0.013996722176671028, 0.015695301815867424, 0.6320171356201172, -0.3265257775783539, 0.02110590599477291, -0.32290807366371155, 0.029946712777018547, -0.014623950235545635, 0.624108612537384, -0.33666959404945374, -0.021007122471928596, 0.002731946762651205, 0.005978992208838463, -0.030529038980603218, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.0435, "q": [-0.3137127161026001, -0.013988200575113297, 0.015695301815867424, 0.6320171356201172, -0.3265257775783539, 0.02110590599477291, -0.3229251205921173, 0.029946712777018547, -0.014597166329622269, 0.6241000890731812, -0.33667778968811035, -0.021021604537963867, 0.002651595277711749, 0.005956196691840887, -0.03052404150366783, 0.2905096113681793, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04092612862586975, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 2.0603, "q": [-0.3137553334236145, -0.013988200575113297, 0.015695301815867424, 0.6320171356201172, -0.3265257775783539, 0.02110590599477291, -0.32295069098472595, 0.029938191175460815, -0.014610557816922665, 0.6240830421447754, -0.33668190240859985, -0.02099977247416973, 0.0026783791836351156, 0.005887848790735006, -0.030577853322029114, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.077, "q": [-0.3138149678707123, -0.01401376724243164, 0.015708694234490395, 0.6320171356201172, -0.3265257775783539, 0.02110590599477291, -0.3229847848415375, 0.029938191175460815, -0.014583774842321873, 0.6241000890731812, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.005933412350714207, -0.03053870238363743, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.0409141443669796, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9781045317649841, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.0937, "q": [-0.31383201479911804, -0.01401376724243164, 0.015695301815867424, 0.6320256590843201, -0.3265257775783539, 0.02110590599477291, -0.32299330830574036, 0.029929669573903084, -0.014583774842321873, 0.6240915656089783, -0.33668190240859985, -0.02099977247416973, 0.0027051628567278385, 0.005910633131861687, -0.030563192442059517, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06169478967785835, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.1105, "q": [-0.3138490617275238, -0.014005245640873909, 0.015708694234490395, 0.6320171356201172, -0.3265340030193329, 0.02112036943435669, -0.3230103552341461, 0.029929669573903084, -0.014570382423698902, 0.6240915656089783, -0.33667778968811035, -0.020992539823055267, 0.0026783791836351156, 0.005880243144929409, -0.030563080683350563, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.061658840626478195, -0.04090216010808945, 0.29502764344215393, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.1274, "q": [-0.31386610865592957, -0.014005245640873909, 0.015708694234490395, 0.6320171356201172, -0.3265381455421448, 0.021113082766532898, -0.3230358958244324, 0.029921147972345352, -0.014583774842321873, 0.6240830421447754, -0.33669009804725647, -0.021014254540205002, 0.002718554809689522, 0.005895438138395548, -0.03056313656270504, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04087819159030914, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.1441, "q": [-0.3138916790485382, -0.014005245640873909, 0.015681909397244453, 0.6320256590843201, -0.3265257775783539, 0.021134961396455765, -0.3230188488960266, 0.029921147972345352, -0.014583774842321873, 0.6240915656089783, -0.33668190240859985, -0.02099977247416973, 0.0027453387156128883, 0.005880253855139017, -0.030582740902900696, 0.2904736399650574, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.1608, "q": [-0.3138831555843353, -0.014022288843989372, 0.015708694234490395, 0.6320171356201172, -0.3265175223350525, 0.021120497956871986, -0.3230358958244324, 0.029921147972345352, -0.014610557816922665, 0.6240915656089783, -0.33668598532676697, -0.021007023751735687, 0.002718554809689522, 0.0059334286488592625, -0.030568189918994904, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06169478967785835, -0.0409141443669796, 0.29507559537887573, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 2.1776, "q": [-0.3138916790485382, -0.013996722176671028, 0.015735477209091187, 0.6320171356201172, -0.326521635055542, 0.021098682656884193, -0.3230358958244324, 0.02991262450814247, -0.014610557816922665, 0.6240915656089783, -0.33669009804725647, -0.021014254540205002, 0.002731946762651205, 0.005918233655393124, -0.030568134039640427, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.2238173931837082, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.1943, "q": [-0.31387463212013245, -0.014005245640873909, 0.015695301815867424, 0.632034182548523, -0.3265175223350525, 0.021091459318995476, -0.3230103552341461, 0.02990410290658474, -0.014623950235545635, 0.624108612537384, -0.33668187260627747, -0.02102883718907833, 0.002718554809689522, 0.005903043784201145, -0.03057790920138359, 0.2904736399650574, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 2.2111, "q": [-0.31387463212013245, -0.01401376724243164, 0.015681909397244453, 0.6320256590843201, -0.326513409614563, 0.021098745986819267, -0.3230273723602295, 0.02991262450814247, -0.014583774842321873, 0.6241000890731812, -0.33667367696762085, -0.02101435326039791, 0.002691771136596799, 0.005925823003053665, -0.030553419142961502, 0.2904616594314575, 0.21593177318572998, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.2278, "q": [-0.31387463212013245, -0.01401376724243164, 0.015708694234490395, 0.6320171356201172, -0.3265175223350525, 0.021091459318995476, -0.32304441928863525, 0.02991262450814247, -0.014597166329622269, 0.624108612537384, -0.33666956424713135, -0.02102164551615715, 0.002731946762651205, 0.00592581182718277, -0.03053375892341137, 0.2904616594314575, 0.21596772968769073, -0.0051891696639359, 0.9792070984840393, 0.1575925648212433, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 2.2446, "q": [-0.3138575851917267, -0.013996722176671028, 0.015708694234490395, 0.632034182548523, -0.326521635055542, 0.021113192662596703, -0.3230103552341461, 0.029921147972345352, -0.014637341722846031, 0.624108612537384, -0.33666956424713135, -0.02102164551615715, 0.0027453387156128883, 0.005956196691840887, -0.03052404150366783, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9791830778121948, 0.15756858885288239, 0.06167082488536835, -0.04087819159030914, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835264265537262, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.2614, "q": [-0.3138575851917267, -0.013996722176671028, 0.015722084790468216, 0.632034182548523, -0.3265092670917511, 0.02110605128109455, -0.32299330830574036, 0.029929669573903084, -0.014637341722846031, 0.6241171360015869, -0.3366531729698181, -0.021036284044384956, 0.002718554809689522, 0.0059486073441803455, -0.030538758262991905, 0.29044967889785767, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.2782, "q": [-0.3138490617275238, -0.01401376724243164, 0.015695301815867424, 0.632034182548523, -0.3265092670917511, 0.02110605128109455, -0.3230103552341461, 0.029921147972345352, -0.014623950235545635, 0.6241171360015869, -0.3366531431674957, -0.021050825715065002, 0.002691771136596799, 0.005963802337646484, -0.030538812279701233, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.2949, "q": [-0.3138575851917267, -0.014022288843989372, 0.015708694234490395, 0.6320427060127258, -0.3265175223350525, 0.021091459318995476, -0.32300183176994324, 0.029929669573903084, -0.014650734141469002, 0.6241171360015869, -0.33665725588798523, -0.02104351669549942, 0.002691771136596799, 0.0059865922667086124, -0.030533980578184128, 0.2904856503009796, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.3118, "q": [-0.31383201479911804, -0.014005245640873909, 0.015722084790468216, 0.6320512294769287, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.02991262450814247, -0.014623950235545635, 0.6241341829299927, -0.3366490602493286, -0.021058116108179092, 0.002758730435743928, 0.005956202279776335, -0.030533870682120323, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.0409141443669796, 0.2950636148452759, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.3285, "q": [-0.31383201479911804, -0.014005245640873909, 0.015708694234490395, 0.6320427060127258, -0.3265175223350525, 0.021105969324707985, -0.32299330830574036, 0.029929669573903084, -0.014623950235545635, 0.6241597533226013, -0.33666136860847473, -0.02103622630238533, 0.002718554809689522, 0.006039750762283802, -0.03048994392156601, 0.2905096113681793, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.3453, "q": [-0.3138405382633209, -0.01401376724243164, 0.015708694234490395, 0.6320512294769287, -0.3265092670917511, 0.02110605128109455, -0.32299330830574036, 0.029921147972345352, -0.014623950235545635, 0.6241597533226013, -0.3366490602493286, -0.02104359306395054, 0.0026783791836351156, 0.005978997331112623, -0.03053886815905571, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04092612862586975, 0.29507559537887573, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.1835503876209259, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.3621, "q": [-0.31383201479911804, -0.014022288843989372, 0.015722084790468216, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.32299330830574036, 0.029921147972345352, -0.014650734141469002, 0.6241597533226013, -0.33666548132896423, -0.021014412865042686, 0.002718554809689522, 0.005986575968563557, -0.030504493042826653, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.0409141443669796, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 2.3788, "q": [-0.31383201479911804, -0.014005245640873909, 0.015695301815867424, 0.6320512294769287, -0.326513409614563, 0.021098745986819267, -0.3229847848415375, 0.029921147972345352, -0.014637341722846031, 0.6241512298583984, -0.33666959404945374, -0.021036185324192047, 0.0026783791836351156, 0.005994176026433706, -0.030509434640407562, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15758058428764343, 0.06169478967785835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.3956, "q": [-0.3138405382633209, -0.013996722176671028, 0.015708694234490395, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.32299330830574036, 0.029929669573903084, -0.014623950235545635, 0.6241512298583984, -0.33667367696762085, -0.02104341797530651, 0.002691771136596799, 0.005986581556499004, -0.030514322221279144, 0.2904856503009796, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 2.4123, "q": [-0.3138405382633209, -0.013996722176671028, 0.015722084790468216, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.3229847848415375, 0.029929669573903084, -0.014610557816922665, 0.6241427063941956, -0.33666136860847473, -0.021021703258156776, 0.002758730435743928, 0.005956191103905439, -0.03051421232521534, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.429, "q": [-0.3138575851917267, -0.013996722176671028, 0.015708694234490395, 0.6320512294769287, -0.3265175223350525, 0.021105969324707985, -0.3229762613773346, 0.02991262450814247, -0.014597166329622269, 0.6241597533226013, -0.33666959404945374, -0.021007122471928596, 0.0027453387156128883, 0.006039745174348354, -0.03048011288046837, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 2.4458, "q": [-0.31387463212013245, -0.01401376724243164, 0.015695301815867424, 0.6320512294769287, -0.3265175223350525, 0.021105969324707985, -0.3230103552341461, 0.029921147972345352, -0.014623950235545635, 0.6241427063941956, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006009371485561132, -0.03050949051976204, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 2.4627, "q": [-0.3138575851917267, -0.013996722176671028, 0.015708694234490395, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.029929669573903084, -0.014623950235545635, 0.6241512298583984, -0.33666548132896423, -0.02102893590927124, 0.0026783791836351156, 0.005956196691840887, -0.03052404150366783, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835503876209259, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 2.4794, "q": [-0.31387463212013245, -0.014005245640873909, 0.015748869627714157, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.32299330830574036, 0.029921147972345352, -0.014597166329622269, 0.6241512298583984, -0.33667367696762085, -0.02101435326039791, 0.002758730435743928, 0.005986581556499004, -0.030514322221279144, 0.2904856503009796, 0.21594375371932983, -0.005201153922826052, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835264265537262, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.4962, "q": [-0.31387463212013245, -0.014005245640873909, 0.015722084790468216, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.029921147972345352, -0.014623950235545635, 0.6241512298583984, -0.33667367696762085, -0.02101435326039791, 0.002731946762651205, 0.005986575968563557, -0.030504493042826653, 0.2904616594314575, 0.2159797102212906, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.052395034581422806, 0.008856342174112797]}
|
||||
{"t": 2.5129, "q": [-0.31386610865592957, -0.014005245640873909, 0.015722084790468216, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.32300183176994324, 0.029921147972345352, -0.014610557816922665, 0.6241427063941956, -0.33667367696762085, -0.02101435326039791, 0.0026783791836351156, 0.005994176026433706, -0.030509434640407562, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.5296, "q": [-0.3138490617275238, -0.013996722176671028, 0.015722084790468216, 0.6320512294769287, -0.3265092670917511, 0.02110605128109455, -0.32299330830574036, 0.02990410290658474, -0.014597166329622269, 0.6241427063941956, -0.33667778968811035, -0.021021604537963867, 0.002718554809689522, 0.006032150238752365, -0.03048500046133995, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04087819159030914, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835503876209259, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.5464, "q": [-0.3138490617275238, -0.01401376724243164, 0.015722084790468216, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.3230103552341461, 0.029921147972345352, -0.014597166329622269, 0.6241512298583984, -0.33666959404945374, -0.021007122471928596, 0.0027051628567278385, 0.0060017709620296955, -0.03050454892218113, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.5631, "q": [-0.3138575851917267, -0.01401376724243164, 0.015722084790468216, 0.6320597529411316, -0.3265092968940735, 0.02109152264893055, -0.32300183176994324, 0.029921147972345352, -0.014610557816922665, 0.6241427063941956, -0.33666136860847473, -0.021050767973065376, 0.002718554809689522, 0.006009371485561132, -0.03050949051976204, 0.29044967889785767, 0.21596772968769073, -0.0051891696639359, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 2.5798, "q": [-0.3138490617275238, -0.01401376724243164, 0.015708694234490395, 0.6320597529411316, -0.3265092670917511, 0.02110605128109455, -0.32300183176994324, 0.02990410290658474, -0.014610557816922665, 0.6241427063941956, -0.3366572856903076, -0.021014470607042313, 0.002718554809689522, 0.005986575968563557, -0.030504493042826653, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.295051634311676, -0.2238173931837082, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.5966, "q": [-0.3138575851917267, -0.014005245640873909, 0.015735477209091187, 0.6320597529411316, -0.3265133798122406, 0.02111327461898327, -0.32300183176994324, 0.02991262450814247, -0.014623950235545635, 0.6241512298583984, -0.33666136860847473, -0.02103622630238533, 0.0027051628567278385, 0.0060017709620296955, -0.03050454892218113, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.157616525888443, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.6133, "q": [-0.31382349133491516, -0.014022288843989372, 0.015748869627714157, 0.6320512294769287, -0.326513409614563, 0.021098745986819267, -0.32300183176994324, 0.02991262450814247, -0.014623950235545635, 0.6241427063941956, -0.33665725588798523, -0.02104351669549942, 0.002731946762651205, 0.005978986620903015, -0.030519209802150726, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06169478967785835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.6301, "q": [-0.3138405382633209, -0.014005245640873909, 0.015735477209091187, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.029929669573903084, -0.014610557816922665, 0.6241512298583984, -0.3366490602493286, -0.021058116108179092, 0.0026649872306734324, 0.005971380975097418, -0.030504437163472176, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.061658840626478195, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.647, "q": [-0.31382349133491516, -0.01401376724243164, 0.015695301815867424, 0.6320512294769287, -0.326521635055542, 0.021098682656884193, -0.3229762613773346, 0.029921147972345352, -0.014623950235545635, 0.6241427063941956, -0.33666956424713135, -0.02102164551615715, 0.002691771136596799, 0.0060245501808822155, -0.03048005886375904, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.6637, "q": [-0.3138575851917267, -0.014005245640873909, 0.015708694234490395, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.3229847848415375, 0.029921147972345352, -0.014623950235545635, 0.6241512298583984, -0.33666136860847473, -0.021021703258156776, 0.0026783791836351156, 0.006009365897625685, -0.030499661341309547, 0.2904736399650574, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 2.6805, "q": [-0.31382349133491516, -0.014005245640873909, 0.015722084790468216, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.3229847848415375, 0.029921147972345352, -0.014623950235545635, 0.6241341829299927, -0.33666548132896423, -0.02102893590927124, 0.002731946762651205, 0.006009365897625685, -0.030499661341309547, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 2.6972, "q": [-0.31382349133491516, -0.013996722176671028, 0.015722084790468216, 0.6320512294769287, -0.326521635055542, 0.021084172651171684, -0.32299330830574036, 0.029938191175460815, -0.014623950235545635, 0.6241512298583984, -0.33666959404945374, -0.021036185324192047, 0.002731946762651205, 0.006039750762283802, -0.03048994392156601, 0.2905096113681793, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18353840708732605, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 2.714, "q": [-0.31382349133491516, -0.014022288843989372, 0.015735477209091187, 0.6320597529411316, -0.3265133798122406, 0.02111327461898327, -0.32299330830574036, 0.029938191175460815, -0.014623950235545635, 0.6241512298583984, -0.33666548132896423, -0.02102893590927124, 0.002691771136596799, 0.006115698721259832, -0.030441073700785637, 0.2905096113681793, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.7308, "q": [-0.31383201479911804, -0.013979678973555565, 0.015695301815867424, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.3229847848415375, 0.029946712777018547, -0.014637341722846031, 0.6241427063941956, -0.33668190240859985, -0.02099977247416973, 0.002758730435743928, 0.006100498139858246, -0.030431188642978668, 0.2905096113681793, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.7476, "q": [-0.31383201479911804, -0.013979678973555565, 0.015708694234490395, 0.6320597529411316, -0.3265092670917511, 0.02110605128109455, -0.32300183176994324, 0.029929669573903084, -0.014623950235545635, 0.6241341829299927, -0.33667778968811035, -0.021021604537963867, 0.0026783791836351156, 0.006054929457604885, -0.030460510402917862, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.7643, "q": [-0.3138405382633209, -0.013988200575113297, 0.015695301815867424, 0.6320682764053345, -0.326521635055542, 0.021098682656884193, -0.32300183176994324, 0.029921147972345352, -0.014637341722846031, 0.6241341829299927, -0.33667778968811035, -0.020992539823055267, 0.0027051628567278385, 0.006062529515475035, -0.03046545200049877, 0.2904616594314575, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.1576405018568039, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 2.7812, "q": [-0.3138405382633209, -0.013962633907794952, 0.015708694234490395, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.3230103552341461, 0.029921147972345352, -0.014623950235545635, 0.6241256594657898, -0.33667367696762085, -0.02101435326039791, 0.0027051628567278385, 0.006108098663389683, -0.030436130240559578, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9781045317649841, -0.18356238305568695, 0.052442967891693115, 0.008844357915222645]}
|
||||
{"t": 2.7981, "q": [-0.31386610865592957, -0.013971157371997833, 0.015681909397244453, 0.6320597529411316, -0.3265298902988434, 0.02109861932694912, -0.3230273723602295, 0.02991262450814247, -0.014623950235545635, 0.6241256594657898, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006062523927539587, -0.03045562282204628, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04087819159030914, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.8148, "q": [-0.31387463212013245, -0.013971157371997833, 0.015681909397244453, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.3230273723602295, 0.029929669573903084, -0.014623950235545635, 0.6241256594657898, -0.33667367696762085, -0.02101435326039791, 0.0026649872306734324, 0.006077719386667013, -0.030455678701400757, 0.2904616594314575, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.8316, "q": [-0.31387463212013245, -0.013971157371997833, 0.015695301815867424, 0.6320512294769287, -0.326521635055542, 0.021113192662596703, -0.3230273723602295, 0.029921147972345352, -0.014610557816922665, 0.624108612537384, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006077730096876621, -0.03047533705830574, 0.2904616594314575, 0.2159797102212906, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052395034581422806, 0.008868326433002949]}
|
||||
{"t": 2.8483, "q": [-0.31387463212013245, -0.013971157371997833, 0.015695301815867424, 0.6320597529411316, -0.326521635055542, 0.021098682656884193, -0.323061466217041, 0.029929669573903084, -0.014623950235545635, 0.6241256594657898, -0.3366941809654236, -0.021021487191319466, 0.002691771136596799, 0.006077730096876621, -0.03047533705830574, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.8651, "q": [-0.3139002025127411, -0.013971157371997833, 0.015668518841266632, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.32305294275283813, 0.029921147972345352, -0.014597166329622269, 0.6241341829299927, -0.3367023766040802, -0.02102142944931984, 0.002691771136596799, 0.006039750762283802, -0.03048994392156601, 0.2904856503009796, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.8818, "q": [-0.3138916790485382, -0.013962633907794952, 0.015681909397244453, 0.6320597529411316, -0.3265257775783539, 0.02110590599477291, -0.323061466217041, 0.029929669573903084, -0.014597166329622269, 0.6240915656089783, -0.3367023766040802, -0.02102142944931984, 0.002758730435743928, 0.006032150238752365, -0.03048500046133995, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.8985, "q": [-0.31390872597694397, -0.01395411230623722, 0.015681909397244453, 0.6320512294769287, -0.3265298902988434, 0.02109861932694912, -0.32305294275283813, 0.029921147972345352, -0.014610557816922665, 0.6241000890731812, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.006032155826687813, -0.030494829639792442, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792190790176392, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 2.9152, "q": [-0.31390872597694397, -0.013971157371997833, 0.015681909397244453, 0.6320512294769287, -0.3265257775783539, 0.02112041600048542, -0.3230699896812439, 0.02991262450814247, -0.014583774842321873, 0.6241000890731812, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006032150238752365, -0.03048500046133995, 0.2905096113681793, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.932, "q": [-0.3139342963695526, -0.013962633907794952, 0.015695301815867424, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.3230699896812439, 0.029921147972345352, -0.014570382423698902, 0.6241000890731812, -0.3366941809654236, -0.021021487191319466, 0.0026649872306734324, 0.005941017996519804, -0.03055347315967083, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04092612862586975, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 2.9487, "q": [-0.31391724944114685, -0.013979678973555565, 0.015668518841266632, 0.6320597529411316, -0.3265298902988434, 0.02109861932694912, -0.3230699896812439, 0.02990410290658474, -0.014583774842321873, 0.6241000890731812, -0.3366983234882355, -0.02099965512752533, 0.0026783791836351156, 0.005948612932115793, -0.030548587441444397, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 2.9655, "q": [-0.3139002025127411, -0.013971157371997833, 0.015708694234490395, 0.6320597529411316, -0.3265092670917511, 0.02110605128109455, -0.32304441928863525, 0.02990410290658474, -0.014597166329622269, 0.624108612537384, -0.33669009804725647, -0.021014254540205002, 0.0027051628567278385, 0.005903043784201145, -0.03057790920138359, 0.2905096113681793, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 2.9824, "q": [-0.3138916790485382, -0.013988200575113297, 0.015708694234490395, 0.6320512294769287, -0.3265175223350525, 0.021105969324707985, -0.3230358958244324, 0.02990410290658474, -0.014583774842321873, 0.624108612537384, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.005903043784201145, -0.03057790920138359, 0.2904616594314575, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.052442967891693115, 0.008844357915222645]}
|
||||
{"t": 2.9991, "q": [-0.31390872597694397, -0.013979678973555565, 0.015695301815867424, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.3230273723602295, 0.02991262450814247, -0.014583774842321873, 0.624108612537384, -0.33668598532676697, -0.021036067977547646, 0.002691771136596799, 0.0058954437263309956, -0.030572965741157532, 0.2904856503009796, 0.21594375371932983, -0.005201153922826052, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.2238173931837082, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.0158, "q": [-0.31390872597694397, -0.013988200575113297, 0.015708694234490395, 0.6320597529411316, -0.326521635055542, 0.021084172651171684, -0.3230273723602295, 0.029921147972345352, -0.014597166329622269, 0.624108612537384, -0.33668187260627747, -0.02102883718907833, 0.0027855143416672945, 0.005925828590989113, -0.030563248321413994, 0.29049763083457947, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.29507559537887573, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 3.0327, "q": [-0.3138831555843353, -0.014005245640873909, 0.015695301815867424, 0.6320597529411316, -0.326521635055542, 0.021098682656884193, -0.3230188488960266, 0.029921147972345352, -0.014637341722846031, 0.6241171360015869, -0.33666548132896423, -0.02105799876153469, 0.002691771136596799, 0.006032150238752365, -0.03048500046133995, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.0494, "q": [-0.31387463212013245, -0.014005245640873909, 0.015722084790468216, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.3230103552341461, 0.029921147972345352, -0.014623950235545635, 0.6241341829299927, -0.33666548132896423, -0.02105799876153469, 0.002758730435743928, 0.005918222479522228, -0.030548475682735443, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 3.0662, "q": [-0.31387463212013245, -0.013979678973555565, 0.015708694234490395, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.32300183176994324, 0.02991262450814247, -0.014623950235545635, 0.624108612537384, -0.33666136860847473, -0.021065307781100273, 0.002691771136596799, 0.005956202279776335, -0.030533870682120323, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.2950875759124756, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.0831, "q": [-0.31386610865592957, -0.013988200575113297, 0.015722084790468216, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.3230103552341461, 0.02991262450814247, -0.014623950235545635, 0.624108612537384, -0.33666956424713135, -0.021065231412649155, 0.002731946762651205, 0.006009365897625685, -0.030499661341309547, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.0998, "q": [-0.3138831555843353, -0.013996722176671028, 0.015708694234490395, 0.6320682764053345, -0.3265175223350525, 0.021105969324707985, -0.32300183176994324, 0.02991262450814247, -0.014623950235545635, 0.6241171360015869, -0.33667367696762085, -0.02104341797530651, 0.002731946762651205, 0.006009365897625685, -0.030499661341309547, 0.2904616594314575, 0.2159797102212906, -0.00523710623383522, 0.9791951179504395, 0.15762852132320404, 0.06167082488536835, -0.0409141443669796, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 3.1165, "q": [-0.31387463212013245, -0.013996722176671028, 0.015708694234490395, 0.6320512294769287, -0.326521635055542, 0.021098682656884193, -0.32299330830574036, 0.02991262450814247, -0.014637341722846031, 0.624108612537384, -0.33668187260627747, -0.02102883718907833, 0.002718554809689522, 0.006024555303156376, -0.030489888042211533, 0.2904616594314575, 0.2159557342529297, -0.00523710623383522, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.052395034581422806, 0.008856342174112797]}
|
||||
{"t": 3.1335, "q": [-0.31387463212013245, -0.013996722176671028, 0.015708694234490395, 0.6320512294769287, -0.326513409614563, 0.021098745986819267, -0.3230103552341461, 0.029929669573903084, -0.014623950235545635, 0.624108612537384, -0.33668598532676697, -0.021036067977547646, 0.002718554809689522, 0.005971397273242474, -0.0305339265614748, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.1502, "q": [-0.3138831555843353, -0.014005245640873909, 0.015681909397244453, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.32300183176994324, 0.029921147972345352, -0.014637341722846031, 0.6241171360015869, -0.33669009804725647, -0.021014254540205002, 0.002611419651657343, 0.006009371485561132, -0.03050949051976204, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.1669, "q": [-0.3138831555843353, -0.013971157371997833, 0.015722084790468216, 0.6320512294769287, -0.326521635055542, 0.021084172651171684, -0.3229847848415375, 0.029921147972345352, -0.014610557816922665, 0.6240915656089783, -0.33668598532676697, -0.021036067977547646, 0.002718554809689522, 0.005956196691840887, -0.03052404150366783, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 3.1837, "q": [-0.31386610865592957, -0.013996722176671028, 0.015708694234490395, 0.6320512294769287, -0.3265257775783539, 0.021091395989060402, -0.3230103552341461, 0.029929669573903084, -0.014597166329622269, 0.6241000890731812, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.0060017709620296955, -0.03050454892218113, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950875759124756, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 3.2004, "q": [-0.3138831555843353, -0.013988200575113297, 0.015681909397244453, 0.6320512294769287, -0.326521635055542, 0.021098682656884193, -0.32299330830574036, 0.02991262450814247, -0.014583774842321873, 0.6241000890731812, -0.33669009804725647, -0.021028777584433556, 0.0026649872306734324, 0.005978959146887064, -0.03047006204724312, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1576405018568039, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.2172, "q": [-0.3138831555843353, -0.013971157371997833, 0.015695301815867424, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.32300183176994324, 0.029921147972345352, -0.014597166329622269, 0.6240915656089783, -0.33668598532676697, -0.021021544933319092, 0.002731946762651205, 0.005956180393695831, -0.030494552105665207, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 3.2339, "q": [-0.31387463212013245, -0.013979678973555565, 0.015695301815867424, 0.6320597529411316, -0.3265257775783539, 0.02110590599477291, -0.32300183176994324, 0.02991262450814247, -0.014583774842321873, 0.6240915656089783, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.0059637753292918205, -0.030489666387438774, 0.2904856503009796, 0.21599169075489044, -0.00523710623383522, 0.9791951179504395, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.052395034581422806, 0.008856342174112797]}
|
||||
{"t": 3.2506, "q": [-0.3139002025127411, -0.013979678973555565, 0.015695301815867424, 0.6320597529411316, -0.326521635055542, 0.021098682656884193, -0.3230358958244324, 0.029921147972345352, -0.014597166329622269, 0.6240830421447754, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006047328934073448, -0.030455566942691803, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 3.2675, "q": [-0.31387463212013245, -0.013971157371997833, 0.015681909397244453, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.32300183176994324, 0.02991262450814247, -0.014597166329622269, 0.6240830421447754, -0.33669009804725647, -0.021028777584433556, 0.0026783791836351156, 0.006001760251820087, -0.030484890565276146, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.2950875759124756, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 3.2842, "q": [-0.3138831555843353, -0.013962633907794952, 0.015681909397244453, 0.6320512294769287, -0.326521635055542, 0.021113192662596703, -0.3230103552341461, 0.029921147972345352, -0.014610557816922665, 0.6240745186805725, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.0060245501808822155, -0.03048005886375904, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950875759124756, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.301, "q": [-0.3138916790485382, -0.013962633907794952, 0.015695301815867424, 0.6320427060127258, -0.326521635055542, 0.021098682656884193, -0.3230103552341461, 0.02991262450814247, -0.014597166329622269, 0.6240745186805725, -0.33668598532676697, -0.021007023751735687, 0.002731946762651205, 0.006001760251820087, -0.030484890565276146, 0.2904736399650574, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18353840708732605, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 3.3177, "q": [-0.31387463212013245, -0.013979678973555565, 0.015695301815867424, 0.6320597529411316, -0.3265175223350525, 0.021105969324707985, -0.32300183176994324, 0.02991262450814247, -0.014623950235545635, 0.6240745186805725, -0.33668598532676697, -0.021021544933319092, 0.002718554809689522, 0.006062523927539587, -0.03045562282204628, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.3344, "q": [-0.31387463212013245, -0.013962633907794952, 0.015695301815867424, 0.6320512294769287, -0.3265175223350525, 0.021105969324707985, -0.3230103552341461, 0.02991262450814247, -0.014610557816922665, 0.6240830421447754, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006024544592946768, -0.03047022968530655, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.3512, "q": [-0.31387463212013245, -0.013971157371997833, 0.015695301815867424, 0.6320597529411316, -0.3265092670917511, 0.02110605128109455, -0.3230103552341461, 0.029921147972345352, -0.014610557816922665, 0.6240830421447754, -0.33668598532676697, -0.021021544933319092, 0.0027453387156128883, 0.006016949657350779, -0.030475115403532982, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.0409141443669796, 0.2950636148452759, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 3.3679, "q": [-0.31386610865592957, -0.013979678973555565, 0.015708694234490395, 0.6320512294769287, -0.326521635055542, 0.021098682656884193, -0.32299330830574036, 0.029929669573903084, -0.014610557816922665, 0.6240915656089783, -0.33666956424713135, -0.0210507083684206, 0.002691771136596799, 0.0060245501808822155, -0.03048005886375904, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.3846, "q": [-0.31387463212013245, -0.013979678973555565, 0.015695301815867424, 0.6320512294769287, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.029921147972345352, -0.014623950235545635, 0.6240745186805725, -0.33667367696762085, -0.02104341797530651, 0.0027051628567278385, 0.00605491828173399, -0.03044085204601288, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.06167082488536835, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008832373656332493]}
|
||||
{"t": 3.4014, "q": [-0.31387463212013245, -0.013971157371997833, 0.015681909397244453, 0.6320682764053345, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.029921147972345352, -0.014623950235545635, 0.6240830421447754, -0.33668187260627747, -0.02102883718907833, 0.002651595277711749, 0.0060473233461380005, -0.03044573776423931, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04092612862586975, 0.29507559537887573, -0.22378143668174744, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 3.4181, "q": [-0.31387463212013245, -0.013979678973555565, 0.015708694234490395, 0.6320682764053345, -0.3265175223350525, 0.021105969324707985, -0.32300183176994324, 0.029921147972345352, -0.014623950235545635, 0.6240830421447754, -0.33668598532676697, -0.021036067977547646, 0.0027453387156128883, 0.006100492551922798, -0.030421359464526176, 0.2904616594314575, 0.2159797102212906, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.4348, "q": [-0.31387463212013245, -0.013971157371997833, 0.015695301815867424, 0.6320512294769287, -0.3265175223350525, 0.021091459318995476, -0.32299330830574036, 0.029929669573903084, -0.014623950235545635, 0.6240830421447754, -0.33668187260627747, -0.02102883718907833, 0.0027051628567278385, 0.0060473233461380005, -0.03044573776423931, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.4515, "q": [-0.31386610865592957, -0.013971157371997833, 0.015695301815867424, 0.6320597529411316, -0.3265175223350525, 0.021091459318995476, -0.3229847848415375, 0.029921147972345352, -0.014597166329622269, 0.6240745186805725, -0.33668598532676697, -0.021036067977547646, 0.002758730435743928, 0.006070124451071024, -0.03046056628227234, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.978116512298584, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.4683, "q": [-0.31387463212013245, -0.01395411230623722, 0.015708694234490395, 0.6320682764053345, -0.326513409614563, 0.021084235981106758, -0.3229847848415375, 0.029921147972345352, -0.014597166329622269, 0.6240915656089783, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.00605491828173399, -0.03044085204601288, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792190790176392, 0.1575925648212433, 0.06169478967785835, -0.04092612862586975, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 3.485, "q": [-0.3138575851917267, -0.01395411230623722, 0.015681909397244453, 0.6320512294769287, -0.3265175223350525, 0.021105969324707985, -0.32299330830574036, 0.029921147972345352, -0.014623950235545635, 0.6240745186805725, -0.33668598532676697, -0.021036067977547646, 0.0027051628567278385, 0.006161262281239033, -0.030401920899748802, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9791830778121948, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 3.5017, "q": [-0.3138490617275238, -0.01395411230623722, 0.015695301815867424, 0.6320597529411316, -0.326513409614563, 0.021098745986819267, -0.32299330830574036, 0.029929669573903084, -0.014637341722846031, 0.6240830421447754, -0.33668187260627747, -0.02102883718907833, 0.0026783791836351156, 0.006199228577315807, -0.030367659404873848, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950875759124756, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835983246564865, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 3.5184, "q": [-0.3138490617275238, -0.013962633907794952, 0.015681909397244453, 0.6320512294769287, -0.326521635055542, 0.021098682656884193, -0.3229762613773346, 0.029929669573903084, -0.014623950235545635, 0.6240489482879639, -0.3366941809654236, -0.021021487191319466, 0.0026783791836351156, 0.006184038706123829, -0.030377432703971863, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9791951179504395, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.29507559537887573, -0.2237934172153473, 0.023093601688742638, 0.9781045317649841, -0.1835503876209259, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.5352, "q": [-0.31387463212013245, -0.013971157371997833, 0.015708694234490395, 0.6320512294769287, -0.326521635055542, 0.021098682656884193, -0.3229847848415375, 0.029921147972345352, -0.014597166329622269, 0.624040424823761, -0.33668598532676697, -0.021021544933319092, 0.002691771136596799, 0.006085303146392107, -0.03043113276362419, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008832373656332493]}
|
||||
{"t": 3.5519, "q": [-0.31386610865592957, -0.013971157371997833, 0.015695301815867424, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.32299330830574036, 0.029921147972345352, -0.014623950235545635, 0.6240148544311523, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.006146066822111607, -0.030401866883039474, 0.2904736399650574, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 3.5686, "q": [-0.31387463212013245, -0.013962633907794952, 0.015668518841266632, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.3229847848415375, 0.029921147972345352, -0.014597166329622269, 0.6240063309669495, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.00616884371265769, -0.030377376824617386, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.0409141443669796, 0.2950636148452759, -0.22378143668174744, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 3.5854, "q": [-0.31387463212013245, -0.01394559070467949, 0.01565512642264366, 0.6320512294769287, -0.3265298902988434, 0.02111312933266163, -0.3229847848415375, 0.029921147972345352, -0.014623950235545635, 0.6240063309669495, -0.3366941809654236, -0.021021487191319466, 0.002691771136596799, 0.006161251105368137, -0.03038226254284382, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950875759124756, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.6021, "q": [-0.3138916790485382, -0.01395411230623722, 0.015681909397244453, 0.6320512294769287, -0.3265257775783539, 0.02110590599477291, -0.3229762613773346, 0.029921147972345352, -0.014597166329622269, 0.6239892840385437, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.006100492551922798, -0.030421359464526176, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 3.619, "q": [-0.3139002025127411, -0.01395411230623722, 0.015668518841266632, 0.6320512294769287, -0.3265298902988434, 0.02109861932694912, -0.32299330830574036, 0.029921147972345352, -0.014583774842321873, 0.6239892840385437, -0.3366941809654236, -0.021021487191319466, 0.0027051628567278385, 0.006108093075454235, -0.030426301062107086, 0.29049763083457947, 0.2159557342529297, -0.005201153922826052, 0.9791951179504395, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.2237934172153473, 0.023081617429852486, 0.9780685901641846, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 3.6359, "q": [-0.3138916790485382, -0.01394559070467949, 0.015681909397244453, 0.6320427060127258, -0.3265257775783539, 0.02110590599477291, -0.3229847848415375, 0.029929669573903084, -0.014610557816922665, 0.6239892840385437, -0.33669009804725647, -0.021014254540205002, 0.0027051628567278385, 0.006100492551922798, -0.030421359464526176, 0.2904616594314575, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.2950875759124756, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 3.6527, "q": [-0.3139002025127411, -0.013962633907794952, 0.015668518841266632, 0.6320427060127258, -0.326521635055542, 0.021113192662596703, -0.32299330830574036, 0.029921147972345352, -0.014610557816922665, 0.6239551901817322, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.0062144179828464985, -0.030357884243130684, 0.2904616594314575, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.6694, "q": [-0.3138916790485382, -0.01394559070467949, 0.015681909397244453, 0.632034182548523, -0.3265257775783539, 0.02110590599477291, -0.3229847848415375, 0.029929669573903084, -0.014623950235545635, 0.6239637136459351, -0.33668598532676697, -0.021036067977547646, 0.002758730435743928, 0.006138456054031849, -0.030377265065908432, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.6862, "q": [-0.31390872597694397, -0.013962633907794952, 0.015668518841266632, 0.6320427060127258, -0.3265175223350525, 0.021105969324707985, -0.3229847848415375, 0.029921147972345352, -0.014623950235545635, 0.6239722371101379, -0.33669009804725647, -0.021014254540205002, 0.002718554809689522, 0.006108087487518787, -0.030416471883654594, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.703, "q": [-0.3139002025127411, -0.01394559070467949, 0.015681909397244453, 0.6320427060127258, -0.3265257775783539, 0.02110590599477291, -0.3229762613773346, 0.02991262450814247, -0.014637341722846031, 0.6239637136459351, -0.33668598532676697, -0.021021544933319092, 0.002731946762651205, 0.006130883004516363, -0.03042146936058998, 0.2904736399650574, 0.21594375371932983, -0.005225121974945068, 0.9791830778121948, 0.1576405018568039, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835983246564865, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 3.7197, "q": [-0.3138916790485382, -0.01394559070467949, 0.015681909397244453, 0.6320427060127258, -0.3265257775783539, 0.02110590599477291, -0.3229847848415375, 0.029921147972345352, -0.014623950235545635, 0.6239551901817322, -0.3366941809654236, -0.021021487191319466, 0.002718554809689522, 0.006115676835179329, -0.03040175512433052, 0.29044967889785767, 0.21596772968769073, -0.005201153922826052, 0.9791951179504395, 0.15765248239040375, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.7366, "q": [-0.3138916790485382, -0.01394559070467949, 0.015668518841266632, 0.632034182548523, -0.326521635055542, 0.021098682656884193, -0.32299330830574036, 0.029921147972345352, -0.014597166329622269, 0.6239722371101379, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.006168851628899574, -0.030387206003069878, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.7534, "q": [-0.3138831555843353, -0.01394559070467949, 0.015668518841266632, 0.632034182548523, -0.326521635055542, 0.021098682656884193, -0.3229762613773346, 0.029929669573903084, -0.014623950235545635, 0.6239637136459351, -0.3366941809654236, -0.021006964147090912, 0.002718554809689522, 0.0060928924940526485, -0.030416416004300117, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.061658840626478195, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.7701, "q": [-0.31391724944114685, -0.01395411230623722, 0.015681909397244453, 0.632034182548523, -0.3265257775783539, 0.02110590599477291, -0.3229762613773346, 0.029929669573903084, -0.014610557816922665, 0.6239551901817322, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.006184038706123829, -0.030377432703971863, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792190790176392, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.7871, "q": [-0.31387463212013245, -0.01394559070467949, 0.01564173400402069, 0.6320512294769287, -0.326521635055542, 0.021113192662596703, -0.3229762613773346, 0.02991262450814247, -0.014610557816922665, 0.6239722371101379, -0.33669009804725647, -0.021028777584433556, 0.002691771136596799, 0.00622960738837719, -0.03034811094403267, 0.2904736399650574, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.0409141443669796, 0.2950875759124756, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.8038, "q": [-0.31387463212013245, -0.01395411230623722, 0.01565512642264366, 0.6320427060127258, -0.326521635055542, 0.021098682656884193, -0.3229762613773346, 0.029921147972345352, -0.014623950235545635, 0.6239551901817322, -0.33669009804725647, -0.021014254540205002, 0.002651595277711749, 0.006206817924976349, -0.030352942645549774, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.06169478967785835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.8205, "q": [-0.31387463212013245, -0.01395411230623722, 0.01565512642264366, 0.632034182548523, -0.3265257775783539, 0.02110590599477291, -0.32295069098472595, 0.029929669573903084, -0.014637341722846031, 0.6239466667175293, -0.33668598532676697, -0.021036067977547646, 0.0026649872306734324, 0.006138456054031849, -0.030377265065908432, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.2950875759124756, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 3.8376, "q": [-0.3138831555843353, -0.01394559070467949, 0.015668518841266632, 0.632034182548523, -0.326521635055542, 0.021098682656884193, -0.32295921444892883, 0.029921147972345352, -0.014610557816922665, 0.6239466667175293, -0.33669009804725647, -0.021014254540205002, 0.0027051628567278385, 0.006191617343574762, -0.030343057587742805, 0.29049763083457947, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.1576405018568039, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.8545, "q": [-0.31387463212013245, -0.01394559070467949, 0.015681909397244453, 0.632034182548523, -0.326521635055542, 0.021098682656884193, -0.3229677379131317, 0.029929669573903084, -0.014623950235545635, 0.6239466667175293, -0.33668187260627747, -0.02102883718907833, 0.0027051628567278385, 0.006237202323973179, -0.030343223363161087, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 3.8712, "q": [-0.31387463212013245, -0.01394559070467949, 0.01565512642264366, 0.6320256590843201, -0.326521635055542, 0.021098682656884193, -0.3229677379131317, 0.029921147972345352, -0.014637341722846031, 0.6239381432533264, -0.3366941809654236, -0.021021487191319466, 0.0027051628567278385, 0.006275165360420942, -0.030299130827188492, 0.2905215919017792, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 3.888, "q": [-0.3138575851917267, -0.01394559070467949, 0.01564173400402069, 0.6320256590843201, -0.3265257775783539, 0.02110590599477291, -0.32295921444892883, 0.029929669573903084, -0.014610557816922665, 0.6239040493965149, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006282765883952379, -0.0303040724247694, 0.2905096113681793, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.905, "q": [-0.3138916790485382, -0.013937067240476608, 0.01565512642264366, 0.6320256590843201, -0.3265257775783539, 0.021091395989060402, -0.32295069098472595, 0.02991262450814247, -0.014637341722846031, 0.623895525932312, -0.33668187260627747, -0.02102883718907833, 0.0027051628567278385, 0.006282765883952379, -0.0303040724247694, 0.2905096113681793, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.9217, "q": [-0.3138575851917267, -0.01395411230623722, 0.01565512642264366, 0.6320171356201172, -0.3265298902988434, 0.02109861932694912, -0.32294216752052307, 0.029929669573903084, -0.014650734141469002, 0.6238784790039062, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.006267587188631296, -0.03033350594341755, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.9384, "q": [-0.31387463212013245, -0.013937067240476608, 0.01564173400402069, 0.6320086121559143, -0.326521635055542, 0.021098682656884193, -0.3229336440563202, 0.02991262450814247, -0.014623950235545635, 0.6238529086112976, -0.3366941809654236, -0.021021487191319466, 0.0026649872306734324, 0.0062903608195483685, -0.03029918670654297, 0.2904616594314575, 0.21594375371932983, -0.005225121974945068, 0.9792070984840393, 0.15758058428764343, 0.06169478967785835, -0.040890175849199295, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 3.9552, "q": [-0.31387463212013245, -0.013937067240476608, 0.01565512642264366, 0.6319915652275085, -0.3265298902988434, 0.02109861932694912, -0.32295921444892883, 0.029938191175460815, -0.014623950235545635, 0.6238273978233337, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006259981542825699, -0.030318733304739, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.0409141443669796, 0.2950636148452759, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 3.9719, "q": [-0.31387463212013245, -0.013911502435803413, 0.01562834158539772, 0.6319830417633057, -0.3265381157398224, 0.021084045991301537, -0.32294216752052307, 0.029921147972345352, -0.014623950235545635, 0.6238018274307251, -0.3366941809654236, -0.021006964147090912, 0.002731946762651205, 0.006267576012760401, -0.030313847586512566, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04087819159030914, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 3.9886, "q": [-0.31387463212013245, -0.013928545638918877, 0.01562834158539772, 0.6319745182991028, -0.3265298902988434, 0.02109861932694912, -0.32294216752052307, 0.029929669573903084, -0.014610557816922665, 0.6237847805023193, -0.3366941809654236, -0.021021487191319466, 0.0026382035575807095, 0.006259986665099859, -0.03032856248319149, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.0055, "q": [-0.3138916790485382, -0.013920024037361145, 0.01565512642264366, 0.6319659948348999, -0.3265298902988434, 0.02111312933266163, -0.32294216752052307, 0.029921147972345352, -0.014650734141469002, 0.6237592101097107, -0.33668187260627747, -0.02102883718907833, 0.002691771136596799, 0.00622200733050704, -0.03034316934645176, 0.2904616594314575, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.0223, "q": [-0.3138916790485382, -0.013902978971600533, 0.01562834158539772, 0.631957471370697, -0.3265298902988434, 0.02111312933266163, -0.32295069098472595, 0.029929669573903084, -0.014623950235545635, 0.6237251162528992, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.006237186025828123, -0.030313735827803612, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.29507559537887573, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.039, "q": [-0.31390872597694397, -0.013911502435803413, 0.01562834158539772, 0.6319404244422913, -0.3265175223350525, 0.021105969324707985, -0.32294216752052307, 0.029938191175460815, -0.014623950235545635, 0.6237165927886963, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006199228577315807, -0.030367659404873848, 0.2904616594314575, 0.2159797102212906, -0.0051891696639359, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.0409141443669796, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008832373656332493]}
|
||||
{"t": 4.0558, "q": [-0.3138831555843353, -0.013894457370042801, 0.01562834158539772, 0.6319404244422913, -0.3265298902988434, 0.02109861932694912, -0.3229251205921173, 0.02991262450814247, -0.014623950235545635, 0.6236910223960876, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006184016820043325, -0.030338115990161896, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.0725, "q": [-0.31392577290534973, -0.013920024037361145, 0.015601558610796928, 0.6319233775138855, -0.3265298902988434, 0.02111312933266163, -0.32294216752052307, 0.029929669573903084, -0.014637341722846031, 0.6236484050750732, -0.3366983234882355, -0.02099965512752533, 0.0026649872306734324, 0.006252364721149206, -0.030284302309155464, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 4.0893, "q": [-0.31390872597694397, -0.01388593576848507, 0.01564173400402069, 0.6319063305854797, -0.3265381455421448, 0.021113082766532898, -0.3229336440563202, 0.029929669573903084, -0.014623950235545635, 0.6236057877540588, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.006221969146281481, -0.030274363234639168, 0.2904856503009796, 0.21596772968769073, -0.00523710623383522, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 4.106, "q": [-0.31391724944114685, -0.013902978971600533, 0.015601558610796928, 0.6319063305854797, -0.3265340030193329, 0.02112036943435669, -0.3229336440563202, 0.029921147972345352, -0.014637341722846031, 0.6235716938972473, -0.3366941809654236, -0.021021487191319466, 0.002691771136596799, 0.006221979856491089, -0.03029402159154415, 0.2905096113681793, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.157616525888443, 0.06169478967785835, -0.040890175849199295, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.1227, "q": [-0.3139342963695526, -0.013920024037361145, 0.015601558610796928, 0.631889283657074, -0.3265340030193329, 0.02112036943435669, -0.32294216752052307, 0.029921147972345352, -0.014597166329622269, 0.6235631704330444, -0.33669009804725647, -0.021014254540205002, 0.002718554809689522, 0.006252370309084654, -0.030294133350253105, 0.2905096113681793, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 4.1396, "q": [-0.3139342963695526, -0.01388593576848507, 0.01562834158539772, 0.6318807601928711, -0.3265381455421448, 0.021113082766532898, -0.32289955019950867, 0.029929669573903084, -0.014623950235545635, 0.6235546469688416, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.0062827495858073235, -0.030274584889411926, 0.2904856503009796, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.1564, "q": [-0.3139428198337555, -0.01388593576848507, 0.015601558610796928, 0.6318722367286682, -0.3265340030193329, 0.021105842664837837, -0.32291659712791443, 0.029929669573903084, -0.014610557816922665, 0.6235376000404358, -0.33668598532676697, -0.021007023751735687, 0.0027453387156128883, 0.006297944579273462, -0.030274640768766403, 0.29044967889785767, 0.2159797102212906, -0.005225121974945068, 0.9792190790176392, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 4.1731, "q": [-0.3139342963695526, -0.013894457370042801, 0.01562834158539772, 0.6318637132644653, -0.3265381455421448, 0.021113082766532898, -0.32294216752052307, 0.029929669573903084, -0.014664125628769398, 0.62352055311203, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006252370309084654, -0.030294133350253105, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22378143668174744, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 4.1898, "q": [-0.3139513432979584, -0.013894457370042801, 0.01562834158539772, 0.6318551898002625, -0.3265381455421448, 0.021113082766532898, -0.32291659712791443, 0.029938191175460815, -0.014623950235545635, 0.62352055311203, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.006275160238146782, -0.030289301648736, 0.29044967889785767, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.2066, "q": [-0.3139428198337555, -0.013894457370042801, 0.015601558610796928, 0.6318466663360596, -0.3265381455421448, 0.021113082766532898, -0.32291659712791443, 0.029938191175460815, -0.014597166329622269, 0.6235120296478271, -0.33669009804725647, -0.021014254540205002, 0.002718554809689522, 0.006267559714615345, -0.03028435818850994, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.29502764344215393, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.2233, "q": [-0.3139513432979584, -0.01388593576848507, 0.01562834158539772, 0.6318551898002625, -0.3265381455421448, 0.021113082766532898, -0.3229336440563202, 0.029938191175460815, -0.014650734141469002, 0.6234779357910156, -0.33669009804725647, -0.021014254540205002, 0.0026649872306734324, 0.0062523758970201015, -0.030303962528705597, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 4.24, "q": [-0.3139342963695526, -0.013877412304282188, 0.015614950098097324, 0.6318381428718567, -0.3265257775783539, 0.02110590599477291, -0.32291659712791443, 0.029938191175460815, -0.014623950235545635, 0.6234779357910156, -0.33668187260627747, -0.02102883718907833, 0.002758730435743928, 0.006252370309084654, -0.030294133350253105, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.0409141443669796, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.2568, "q": [-0.31392577290534973, -0.01388593576848507, 0.015614950098097324, 0.6318381428718567, -0.3265298902988434, 0.02111312933266163, -0.32289955019950867, 0.029921147972345352, -0.014664125628769398, 0.6234694719314575, -0.33669009804725647, -0.021014254540205002, 0.0027051628567278385, 0.0063055395148694515, -0.03026975318789482, 0.2904736399650574, 0.21594375371932983, -0.0051891696639359, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.0088803106918931]}
|
||||
{"t": 4.2736, "q": [-0.31391724944114685, -0.01388593576848507, 0.015614950098097324, 0.6318381428718567, -0.3265381455421448, 0.021113082766532898, -0.32290807366371155, 0.029946712777018547, -0.014664125628769398, 0.6234779357910156, -0.33669009804725647, -0.021014254540205002, 0.002718554809689522, 0.006267554592341185, -0.03027452901005745, 0.2904736399650574, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.061658840626478195, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18353840708732605, 0.05240701511502266, 0.008892294950783253]}
|
||||
{"t": 4.2904, "q": [-0.31392577290534973, -0.013902978971600533, 0.015601558610796928, 0.6318210959434509, -0.3265298902988434, 0.02111312933266163, -0.3228825032711029, 0.029938191175460815, -0.014637341722846031, 0.6234694719314575, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.0062751490622758865, -0.030269641429185867, 0.2904736399650574, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835983246564865, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 4.3071, "q": [-0.3139342963695526, -0.013877412304282188, 0.015601558610796928, 0.6318296194076538, -0.3265175223350525, 0.021120497956871986, -0.3228825032711029, 0.029938191175460815, -0.014650734141469002, 0.6234694719314575, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006290349643677473, -0.030279526486992836, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.29507559537887573, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 4.3239, "q": [-0.3139513432979584, -0.013894457370042801, 0.015588166192173958, 0.6318210959434509, -0.3265298902988434, 0.02109861932694912, -0.3228825032711029, 0.029938191175460815, -0.014664125628769398, 0.6234524250030518, -0.33668190240859985, -0.02099977247416973, 0.002691771136596799, 0.006335907615721226, -0.03023054637014866, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 4.3407, "q": [-0.3139342963695526, -0.013894457370042801, 0.015588166192173958, 0.6318296194076538, -0.3265381157398224, 0.021098555997014046, -0.3228739798069, 0.029938191175460815, -0.014677518047392368, 0.6234524250030518, -0.33669009804725647, -0.021014254540205002, 0.002718554809689522, 0.00629032775759697, -0.03024020977318287, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 4.3574, "q": [-0.3139342963695526, -0.013877412304282188, 0.015601558610796928, 0.6318296194076538, -0.3265298902988434, 0.02111312933266163, -0.32285693287849426, 0.029938191175460815, -0.014677518047392368, 0.623435378074646, -0.33669009804725647, -0.021014254540205002, 0.002731946762651205, 0.006320723332464695, -0.030250148847699165, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.3742, "q": [-0.31392577290534973, -0.01388593576848507, 0.015601558610796928, 0.6318210959434509, -0.3265340030193329, 0.021105842664837837, -0.3228910267353058, 0.029946712777018547, -0.014637341722846031, 0.6234524250030518, -0.33669009804725647, -0.021014254540205002, 0.002758730435743928, 0.006305523216724396, -0.030240265652537346, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792190790176392, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.3909, "q": [-0.31390872597694397, -0.01388593576848507, 0.015574774704873562, 0.6318210959434509, -0.3265175223350525, 0.021120497956871986, -0.3228484094142914, 0.029938191175460815, -0.014650734141469002, 0.623435378074646, -0.33668598532676697, -0.021007023751735687, 0.0027051628567278385, 0.0063283126801252365, -0.03023543395102024, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 4.4077, "q": [-0.31390872597694397, -0.013868890702724457, 0.015574774704873562, 0.6318210959434509, -0.3265298902988434, 0.02109861932694912, -0.3228398859500885, 0.029946712777018547, -0.014650734141469002, 0.623435378074646, -0.33668187260627747, -0.02102883718907833, 0.002758730435743928, 0.006313128862529993, -0.030255036428570747, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 4.4244, "q": [-0.31390872597694397, -0.013868890702724457, 0.015601558610796928, 0.6318040490150452, -0.3265340030193329, 0.021105842664837837, -0.32285693287849426, 0.029946712777018547, -0.014677518047392368, 0.6234268546104431, -0.33668598532676697, -0.021021544933319092, 0.0027453387156128883, 0.006389076821506023, -0.030206166207790375, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1576405018568039, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 4.4411, "q": [-0.3138916790485382, -0.013868890702724457, 0.015588166192173958, 0.6318040490150452, -0.3265340030193329, 0.021105842664837837, -0.3228398859500885, 0.029946712777018547, -0.014637341722846031, 0.6234183311462402, -0.33668598532676697, -0.021021544933319092, 0.002718554809689522, 0.006320712622255087, -0.030230490490794182, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 4.4578, "q": [-0.3138916790485382, -0.013877412304282188, 0.015601558610796928, 0.6317955255508423, -0.3265257775783539, 0.02110590599477291, -0.3228313624858856, 0.029938191175460815, -0.014664125628769398, 0.6234183311462402, -0.33667367696762085, -0.02101435326039791, 0.002718554809689522, 0.006434645503759384, -0.03017684444785118, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 4.4746, "q": [-0.31390872597694397, -0.013877412304282188, 0.015574774704873562, 0.6317870020866394, -0.3265257775783539, 0.02110590599477291, -0.3228398859500885, 0.029946712777018547, -0.014650734141469002, 0.6233842372894287, -0.33668187260627747, -0.02102883718907833, 0.002731946762651205, 0.006396660581231117, -0.03018162027001381, 0.2904616594314575, 0.21593177318572998, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.4913, "q": [-0.3138831555843353, -0.013877412304282188, 0.015588166192173958, 0.6317784786224365, -0.3265257775783539, 0.02110590599477291, -0.3228313624858856, 0.029946712777018547, -0.014690909534692764, 0.6233757138252258, -0.33669009804725647, -0.021014254540205002, 0.002651595277711749, 0.006389066111296415, -0.03018650785088539, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.0409141443669796, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 4.5082, "q": [-0.31387463212013245, -0.013868890702724457, 0.015601558610796928, 0.6317784786224365, -0.3265257775783539, 0.02112041600048542, -0.32282283902168274, 0.029955236241221428, -0.014677518047392368, 0.6233757138252258, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.006404266692698002, -0.03019639290869236, 0.2904616594314575, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.5249, "q": [-0.31390872597694397, -0.013868890702724457, 0.015574774704873562, 0.6317529678344727, -0.3265298902988434, 0.02109861932694912, -0.3228313624858856, 0.029955236241221428, -0.014677518047392368, 0.623367190361023, -0.33668598532676697, -0.021007023751735687, 0.002718554809689522, 0.006449829787015915, -0.030157241970300674, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.5417, "q": [-0.31387463212013245, -0.013868890702724457, 0.015574774704873562, 0.6317444443702698, -0.3265298902988434, 0.02109861932694912, -0.32281434535980225, 0.029955236241221428, -0.014650734141469002, 0.623367190361023, -0.33667367696762085, -0.02101435326039791, 0.002624811604619026, 0.006366276182234287, -0.030191339552402496, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06169478967785835, -0.04087819159030914, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.5584, "q": [-0.31387463212013245, -0.013877412304282188, 0.015588166192173958, 0.6317359209060669, -0.3265298902988434, 0.02109861932694912, -0.32281434535980225, 0.02996375784277916, -0.014664125628769398, 0.6233586668968201, -0.33668598532676697, -0.021021544933319092, 0.0027453387156128883, 0.006449829787015915, -0.030157241970300674, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 4.5752, "q": [-0.3138490617275238, -0.013868890702724457, 0.015601558610796928, 0.631727397441864, -0.3265257775783539, 0.021091395989060402, -0.32282283902168274, 0.02996375784277916, -0.014677518047392368, 0.6233586668968201, -0.33668187260627747, -0.02102883718907833, 0.0027453387156128883, 0.006434640381485224, -0.03016701526939869, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.06169478967785835, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.5919, "q": [-0.3138405382633209, -0.013868890702724457, 0.015574774704873562, 0.631727397441864, -0.3265257775783539, 0.021091395989060402, -0.32282283902168274, 0.02996375784277916, -0.014664125628769398, 0.6233501434326172, -0.33667778968811035, -0.021021604537963867, 0.0027453387156128883, 0.006434629205614328, -0.030147356912493706, 0.2904736399650574, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.6087, "q": [-0.31383201479911804, -0.013877412304282188, 0.015588166192173958, 0.6317188739776611, -0.326521635055542, 0.021098682656884193, -0.3227972984313965, 0.029955236241221428, -0.014664125628769398, 0.6233330965042114, -0.33667778968811035, -0.021021604537963867, 0.0026649872306734324, 0.0064118392765522, -0.03015218861401081, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.6254, "q": [-0.3138490617275238, -0.013868890702724457, 0.015588166192173958, 0.6316762566566467, -0.3265133798122406, 0.02111327461898327, -0.3227887749671936, 0.02996375784277916, -0.014677518047392368, 0.6233160495758057, -0.33668187260627747, -0.02102883718907833, 0.002691771136596799, 0.006533356383442879, -0.030073996633291245, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 4.6422, "q": [-0.3138405382633209, -0.013843324035406113, 0.015574774704873562, 0.631659209728241, -0.326521635055542, 0.021098682656884193, -0.3227972984313965, 0.029955236241221428, -0.014677518047392368, 0.6233075261116028, -0.33668190240859985, -0.021014314144849777, 0.0026783791836351156, 0.006540956906974316, -0.030078938230872154, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.023081617429852486, 0.9780685901641846, -0.1835743635892868, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 4.6591, "q": [-0.31382349133491516, -0.013851847499608994, 0.015588166192173958, 0.6316421627998352, -0.3265257775783539, 0.021091395989060402, -0.32276320457458496, 0.02996375784277916, -0.014677518047392368, 0.6232734322547913, -0.33668187260627747, -0.02102883718907833, 0.002651595277711749, 0.00654094573110342, -0.03005927987396717, 0.29049763083457947, 0.2159797102212906, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 4.6758, "q": [-0.3138064444065094, -0.013868890702724457, 0.015588166192173958, 0.6316251158714294, -0.326521635055542, 0.021098682656884193, -0.3227546811103821, 0.02996375784277916, -0.014650734141469002, 0.6232649087905884, -0.33668187260627747, -0.02102883718907833, 0.0027051628567278385, 0.006601709872484207, -0.030030013993382454, 0.2904616594314575, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.061658840626478195, -0.04086620733141899, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008892294950783253]}
|
||||
{"t": 4.6925, "q": [-0.3138064444065094, -0.013868890702724457, 0.015574774704873562, 0.6315995454788208, -0.326521635055542, 0.021098682656884193, -0.3227376341819763, 0.02996375784277916, -0.014690909534692764, 0.6232308149337769, -0.33666548132896423, -0.020999889820814133, 0.002691771136596799, 0.0066548679023981094, -0.029985975474119186, 0.2905096113681793, 0.2159797102212906, -0.005213138181716204, 0.9791830778121948, 0.15754462778568268, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 4.7093, "q": [-0.3138064444065094, -0.013868890702724457, 0.015601558610796928, 0.6315654516220093, -0.3265257775783539, 0.02110590599477291, -0.3227546811103821, 0.02996375784277916, -0.014731084927916527, 0.6231796741485596, -0.33668187260627747, -0.02102883718907833, 0.0026649872306734324, 0.0066548679023981094, -0.029985975474119186, 0.2904856503009796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.06169478967785835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.726, "q": [-0.31378939747810364, -0.013860369101166725, 0.015574774704873562, 0.6315313577651978, -0.3265298902988434, 0.02109861932694912, -0.3227376341819763, 0.02996375784277916, -0.014664125628769398, 0.6231200098991394, -0.33669009804725647, -0.021014254540205002, 0.002731946762651205, 0.0066548679023981094, -0.029985975474119186, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.7427, "q": [-0.31378090381622314, -0.013860369101166725, 0.015601558610796928, 0.6314802169799805, -0.3265257775783539, 0.02110590599477291, -0.32272058725357056, 0.02996375784277916, -0.014650734141469002, 0.6230944395065308, -0.33669009804725647, -0.021014254540205002, 0.002691771136596799, 0.006609299220144749, -0.03001529723405838, 0.29049763083457947, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06169478967785835, -0.0409141443669796, 0.29507559537887573, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.052395034581422806, 0.008844357915222645]}
|
||||
{"t": 4.7595, "q": [-0.3138064444065094, -0.013834802433848381, 0.015588166192173958, 0.6314802169799805, -0.3265257775783539, 0.02110590599477291, -0.32272058725357056, 0.029980802908539772, -0.014664125628769398, 0.6230348348617554, -0.33667778968811035, -0.021021604537963867, 0.002691771136596799, 0.006586514879018068, -0.030029958114027977, 0.2904736399650574, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 4.7762, "q": [-0.31378939747810364, -0.013834802433848381, 0.015588166192173958, 0.6314375996589661, -0.326521635055542, 0.021113192662596703, -0.3227120637893677, 0.029980802908539772, -0.014664125628769398, 0.6229751706123352, -0.33668187260627747, -0.02102883718907833, 0.0027051628567278385, 0.006632083561271429, -0.030000636354088783, 0.2904616594314575, 0.21594375371932983, -0.005201153922826052, 0.9792190790176392, 0.15760454535484314, 0.061658840626478195, -0.040890175849199295, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 4.793, "q": [-0.31377238035202026, -0.01382628083229065, 0.015588166192173958, 0.6313949823379517, -0.3265381157398224, 0.021084045991301537, -0.32272058725357056, 0.02997227944433689, -0.014690909534692764, 0.622915506362915, -0.33667367696762085, -0.02101435326039791, 0.002718554809689522, 0.006616894155740738, -0.030010409653186798, 0.29049763083457947, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950875759124756, -0.22378143668174744, 0.023093601688742638, 0.9781045317649841, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.8097, "q": [-0.31382349133491516, -0.01382628083229065, 0.015561383217573166, 0.6313694715499878, -0.3265257775783539, 0.02110590599477291, -0.3227035403251648, 0.02997227944433689, -0.014690909534692764, 0.6228728890419006, -0.33669009804725647, -0.021014254540205002, 0.0026783791836351156, 0.006586514879018068, -0.030029958114027977, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.29507559537887573, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.8265, "q": [-0.3137979209423065, -0.013834802433848381, 0.015588166192173958, 0.6313439011573792, -0.3265257775783539, 0.02110590599477291, -0.3227035403251648, 0.029989324510097504, -0.014677518047392368, 0.6228217482566833, -0.33667778968811035, -0.021021604537963867, 0.0027051628567278385, 0.0066017042845487595, -0.030020184814929962, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.29507559537887573, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.8433, "q": [-0.3138149678707123, -0.013809235766530037, 0.015588166192173958, 0.6313353776931763, -0.3265340030193329, 0.021105842664837837, -0.32264387607574463, 0.029997846111655235, -0.01470430102199316, 0.6227876543998718, -0.33666959404945374, -0.021007122471928596, 0.0026649872306734324, 0.006586509291082621, -0.030020128935575485, 0.29049763083457947, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.86, "q": [-0.31378090381622314, -0.013817759230732918, 0.015561383217573166, 0.6312757134437561, -0.3265340030193329, 0.02112036943435669, -0.32262685894966125, 0.029989324510097504, -0.014677518047392368, 0.6227194666862488, -0.33667367696762085, -0.02101435326039791, 0.0027051628567278385, 0.006632077973335981, -0.02999080717563629, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 4.8767, "q": [-0.31377238035202026, -0.013834802433848381, 0.015561383217573166, 0.6312160491943359, -0.3265257775783539, 0.02110590599477291, -0.32262685894966125, 0.029989324510097504, -0.01470430102199316, 0.6226769089698792, -0.33667367696762085, -0.02101435326039791, 0.0026649872306734324, 0.006662462837994099, -0.029981087893247604, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 4.8935, "q": [-0.3137979209423065, -0.013843324035406113, 0.015588166192173958, 0.6311563849449158, -0.3265298902988434, 0.02109861932694912, -0.32259276509284973, 0.029989324510097504, -0.014677518047392368, 0.6226428151130676, -0.33667367696762085, -0.02101435326039791, 0.0027051628567278385, 0.0066700465977191925, -0.02995654195547104, 0.2904616594314575, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 4.9116, "q": [-0.31378090381622314, -0.013817759230732918, 0.015574774704873562, 0.63113933801651, -0.3265298902988434, 0.02109861932694912, -0.3226012885570526, 0.029997846111655235, -0.01470430102199316, 0.6225831508636475, -0.33669009804725647, -0.021014254540205002, 0.0027453387156128883, 0.006639656610786915, -0.029956432059407234, 0.29044967889785767, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023069633170962334, 0.9780925512313843, -0.1835503876209259, 0.05243098363280296, 0.0088803106918931]}
|
||||
{"t": 4.9283, "q": [-0.31378939747810364, -0.01382628083229065, 0.015561383217573166, 0.6311052441596985, -0.3265298902988434, 0.02111312933266163, -0.3225671947002411, 0.029997846111655235, -0.014731084927916527, 0.6225490570068359, -0.33668190240859985, -0.02099977247416973, 0.002718554809689522, 0.006624466739594936, -0.02996620535850525, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 4.9451, "q": [-0.3137979209423065, -0.013817759230732918, 0.015561383217573166, 0.6310455799102783, -0.3265298902988434, 0.02109861932694912, -0.32258424162864685, 0.029997846111655235, -0.01470430102199316, 0.6225234866142273, -0.33666959404945374, -0.021007122471928596, 0.002731946762651205, 0.006723205093294382, -0.02991250343620777, 0.29044967889785767, 0.2159797102212906, -0.005225121974945068, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 4.9618, "q": [-0.31377238035202026, -0.013817759230732918, 0.015561383217573166, 0.6310114860534668, -0.3265298902988434, 0.02109861932694912, -0.32253310084342957, 0.029997846111655235, -0.014731084927916527, 0.62247234582901, -0.33667367696762085, -0.02101435326039791, 0.002731946762651205, 0.0067080045118927956, -0.029902620241045952, 0.2904856503009796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 4.9786, "q": [-0.31377238035202026, -0.013817759230732918, 0.015547990798950195, 0.6309689283370972, -0.3265298902988434, 0.02109861932694912, -0.3225245773792267, 0.029989324510097504, -0.014690909534692764, 0.622404158115387, -0.33667367696762085, -0.02101435326039791, 0.0026783791836351156, 0.006707998923957348, -0.02989278919994831, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 4.9953, "q": [-0.3137553334236145, -0.013809235766530037, 0.015561383217573166, 0.6309348344802856, -0.3265381157398224, 0.021098555997014046, -0.32249900698661804, 0.029989324510097504, -0.014731084927916527, 0.6223785877227783, -0.33666959404945374, -0.021007122471928596, 0.002718554809689522, 0.006700403988361359, -0.029897676780819893, 0.2904736399650574, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.29507559537887573, -0.2238173931837082, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 5.012, "q": [-0.3137553334236145, -0.013800714164972305, 0.015561383217573166, 0.6309263110160828, -0.3265257775783539, 0.02110590599477291, -0.3224819600582123, 0.029989324510097504, -0.01471769344061613, 0.6223530173301697, -0.33666548132896423, -0.020999889820814133, 0.002691771136596799, 0.00665482971817255, -0.029917169362306595, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.04086620733141899, 0.29503965377807617, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 5.0288, "q": [-0.31372976303100586, -0.013800714164972305, 0.015561383217573166, 0.6309007406234741, -0.326521635055542, 0.021113192662596703, -0.3224649131298065, 0.030006367713212967, -0.01470430102199316, 0.6223104596138, -0.33667778968811035, -0.020992539823055267, 0.0027453387156128883, 0.006662430241703987, -0.029922112822532654, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 5.0455, "q": [-0.3137127161026001, -0.013800714164972305, 0.015547990798950195, 0.6308240294456482, -0.3265257775783539, 0.02110590599477291, -0.3224819600582123, 0.029997846111655235, -0.01471769344061613, 0.622242271900177, -0.33667370676994324, -0.020985309034585953, 0.002718554809689522, 0.006806714925915003, -0.029829397797584534, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.0623, "q": [-0.3136786222457886, -0.013809235766530037, 0.015561383217573166, 0.6307814121246338, -0.3265298902988434, 0.02109861932694912, -0.32245638966560364, 0.029997846111655235, -0.014731084927916527, 0.6222081780433655, -0.33667778968811035, -0.020992539823055267, 0.002691771136596799, 0.0068067223764956, -0.029839208349585533, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.0791, "q": [-0.31368714570999146, -0.013792192563414574, 0.015547990798950195, 0.6307558417320251, -0.3265298902988434, 0.02109861932694912, -0.32243937253952026, 0.029997846111655235, -0.014744477346539497, 0.6221996545791626, -0.33667370676994324, -0.020985309034585953, 0.0027051628567278385, 0.006829492282122374, -0.029814792796969414, 0.2904616594314575, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.1575925648212433, 0.06169478967785835, -0.04090216010808945, 0.2950636148452759, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 5.0958, "q": [-0.31368714570999146, -0.013792192563414574, 0.0155345993116498, 0.6307217478752136, -0.326521635055542, 0.021098682656884193, -0.3224308490753174, 0.030006367713212967, -0.014731084927916527, 0.6221314668655396, -0.33666548132896423, -0.020999889820814133, 0.002691771136596799, 0.0068067223764956, -0.029839208349585533, 0.2904736399650574, 0.21594375371932983, -0.0051891696639359, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9781045317649841, -0.1835503876209259, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.1126, "q": [-0.31363600492477417, -0.01376662589609623, 0.015521206893026829, 0.6307047009468079, -0.3265257775783539, 0.02110590599477291, -0.32239675521850586, 0.030006367713212967, -0.014731084927916527, 0.6221058964729309, -0.33667367696762085, -0.02101435326039791, 0.0027051628567278385, 0.006776344496756792, -0.029848871752619743, 0.2904736399650574, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06169478967785835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.1293, "q": [-0.3136274814605713, -0.01376662589609623, 0.0155345993116498, 0.6306791305541992, -0.3265298902988434, 0.02109861932694912, -0.32235413789749146, 0.030014891177415848, -0.014731084927916527, 0.6220718026161194, -0.33666959404945374, -0.021007122471928596, 0.0027051628567278385, 0.006821899674832821, -0.029819661751389503, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 5.146, "q": [-0.31363600492477417, -0.01376662589609623, 0.015521206893026829, 0.6306279897689819, -0.3265298902988434, 0.02109861932694912, -0.3223711848258972, 0.030014891177415848, -0.014731084927916527, 0.6220206618309021, -0.33667370676994324, -0.020985309034585953, 0.0027453387156128883, 0.006859861314296722, -0.029795320704579353, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.1628, "q": [-0.31363600492477417, -0.013775147497653961, 0.015521206893026829, 0.6305939555168152, -0.3265257775783539, 0.02110590599477291, -0.3223711848258972, 0.030006367713212967, -0.014731084927916527, 0.6219525337219238, -0.33667367696762085, -0.02101435326039791, 0.0026783791836351156, 0.006867461837828159, -0.029800262302160263, 0.2904856503009796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 5.1795, "q": [-0.31363600492477417, -0.013749580830335617, 0.015521206893026829, 0.6305513381958008, -0.3265298902988434, 0.02109861932694912, -0.3223711848258972, 0.030014891177415848, -0.014731084927916527, 0.6218843460083008, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.006837077438831329, -0.029800113290548325, 0.29044967889785767, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.1962, "q": [-0.31363600492477417, -0.013749580830335617, 0.015507815405726433, 0.630534291267395, -0.326521635055542, 0.021098682656884193, -0.32236266136169434, 0.03002341277897358, -0.014690909534692764, 0.621867299079895, -0.33668190240859985, -0.02099977247416973, 0.002731946762651205, 0.006859861314296722, -0.029795320704579353, 0.2904376983642578, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 5.213, "q": [-0.31364452838897705, -0.013758104294538498, 0.015507815405726433, 0.6305001974105835, -0.3265298902988434, 0.02109861932694912, -0.3223456144332886, 0.030014891177415848, -0.014731084927916527, 0.6218332052230835, -0.33666548132896423, -0.020999889820814133, 0.002718554809689522, 0.006844677496701479, -0.029805056750774384, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.2297, "q": [-0.3136189579963684, -0.013749580830335617, 0.015507815405726433, 0.6304575800895691, -0.3265298902988434, 0.02109861932694912, -0.32235413789749146, 0.03002341277897358, -0.014731084927916527, 0.6217650175094604, -0.33666959404945374, -0.020992599427700043, 0.002718554809689522, 0.006859861314296722, -0.029795320704579353, 0.2904856503009796, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.29507559537887573, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 5.2465, "q": [-0.31360191106796265, -0.013749580830335617, 0.015507815405726433, 0.6303723454475403, -0.3265340030193329, 0.021091332659125328, -0.32236266136169434, 0.03002341277897358, -0.014731084927916527, 0.6216627359390259, -0.33666548132896423, -0.020999889820814133, 0.002718554809689522, 0.006897824816405773, -0.029770951718091965, 0.2904856503009796, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.2635, "q": [-0.31363600492477417, -0.013749580830335617, 0.015494422987103462, 0.630321204662323, -0.3265298902988434, 0.02109861932694912, -0.3223370909690857, 0.03003193438053131, -0.01471769344061613, 0.6215945482254028, -0.33666959404945374, -0.021007122471928596, 0.0027453387156128883, 0.006875039078295231, -0.029775751754641533, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.061658840626478195, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.2802, "q": [-0.31363600492477417, -0.013749580830335617, 0.015507815405726433, 0.6303041577339172, -0.3265340030193329, 0.021105842664837837, -0.32231152057647705, 0.03003193438053131, -0.014731084927916527, 0.6215605139732361, -0.33666959404945374, -0.020992599427700043, 0.002731946762651205, 0.006905409973114729, -0.02975625731050968, 0.2904616594314575, 0.21596772968769073, -0.0051891696639359, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.2969, "q": [-0.31364452838897705, -0.013741059228777885, 0.015507815405726433, 0.6302530169487, -0.3265340030193329, 0.021105842664837837, -0.3222944736480713, 0.030040455982089043, -0.01471769344061613, 0.6215093731880188, -0.33666959404945374, -0.021007122471928596, 0.0027453387156128883, 0.00692818034440279, -0.029731813818216324, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.061706773936748505, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.3138, "q": [-0.31359341740608215, -0.013741059228777885, 0.015507815405726433, 0.630236029624939, -0.3265298902988434, 0.02109861932694912, -0.32226890325546265, 0.030048979446291924, -0.014744477346539497, 0.6214582324028015, -0.33667367696762085, -0.02101435326039791, 0.0026783791836351156, 0.006928187794983387, -0.02974163554608822, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18358634412288666, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 5.3305, "q": [-0.31360191106796265, -0.013749580830335617, 0.015494422987103462, 0.6302104592323303, -0.3265340030193329, 0.021105842664837837, -0.32226890325546265, 0.030040455982089043, -0.014744477346539497, 0.62142413854599, -0.33667370676994324, -0.020985309034585953, 0.002731946762651205, 0.006897802464663982, -0.02974148653447628, 0.2904376983642578, 0.21593177318572998, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.061706773936748505, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 5.3473, "q": [-0.3136189579963684, -0.013749580830335617, 0.015507815405726433, 0.6301678419113159, -0.3265298902988434, 0.02109861932694912, -0.3222433626651764, 0.030040455982089043, -0.014744477346539497, 0.6213474273681641, -0.33666136860847473, -0.021021703258156776, 0.0027051628567278385, 0.006966136395931244, -0.02969762124121189, 0.29042571783065796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.3641, "q": [-0.3136104345321655, -0.013749580830335617, 0.015507815405726433, 0.6301252245903015, -0.3265257775783539, 0.02110590599477291, -0.3222348392009735, 0.030040455982089043, -0.014757868833839893, 0.6213048100471497, -0.33666959404945374, -0.020992599427700043, 0.0026783791836351156, 0.006996514275670052, -0.029687948524951935, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.3808, "q": [-0.3136104345321655, -0.013749580830335617, 0.015507815405726433, 0.6301252245903015, -0.3265298902988434, 0.02109861932694912, -0.32221779227256775, 0.030048979446291924, -0.014771261252462864, 0.6212877631187439, -0.3366572856903076, -0.021014470607042313, 0.002718554809689522, 0.0070041147992014885, -0.029692895710468292, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950156629085541, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 5.3976, "q": [-0.31360191106796265, -0.013749580830335617, 0.015481031499803066, 0.6300996541976929, -0.3265298902988434, 0.02111312933266163, -0.322200745344162, 0.030057501047849655, -0.014771261252462864, 0.6212536692619324, -0.3366572856903076, -0.02099994756281376, 0.002731946762651205, 0.006981306709349155, -0.029668230563402176, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.4143, "q": [-0.31360191106796265, -0.013749580830335617, 0.015521206893026829, 0.6300826072692871, -0.326521635055542, 0.021098682656884193, -0.3221836984157562, 0.030048979446291924, -0.01479804515838623, 0.6212451457977295, -0.33666136860847473, -0.021021703258156776, 0.0027051628567278385, 0.006981306709349155, -0.029668230563402176, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.431, "q": [-0.31359341740608215, -0.013732537627220154, 0.015507815405726433, 0.6300570368766785, -0.3265298902988434, 0.02109861932694912, -0.3221836984157562, 0.030048979446291924, -0.01479804515838623, 0.6211855411529541, -0.33666959404945374, -0.021007122471928596, 0.002731946762651205, 0.0070344251580536366, -0.029594825580716133, 0.2904376983642578, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 5.4478, "q": [-0.3135763704776764, -0.013749580830335617, 0.015507815405726433, 0.6300314664840698, -0.3265257775783539, 0.02110590599477291, -0.32216665148735046, 0.030048979446291924, -0.01478465273976326, 0.6211514472961426, -0.33666548132896423, -0.020999889820814133, 0.002731946762651205, 0.007057209499180317, -0.029590027406811714, 0.29042571783065796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.4646, "q": [-0.31360191106796265, -0.013732537627220154, 0.015481031499803066, 0.6300144195556641, -0.3265298902988434, 0.02109861932694912, -0.32217517495155334, 0.030048979446291924, -0.01478465273976326, 0.6211258769035339, -0.33667778968811035, -0.020992539823055267, 0.002758730435743928, 0.007042017765343189, -0.029589951038360596, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04087819159030914, 0.29502764344215393, -0.22378143668174744, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 5.4813, "q": [-0.31359341740608215, -0.013732537627220154, 0.015481031499803066, 0.6299803256988525, -0.3265298902988434, 0.02109861932694912, -0.3221581280231476, 0.030048979446291924, -0.014757868833839893, 0.6211003065109253, -0.33666959404945374, -0.02097807638347149, 0.0027453387156128883, 0.007057209499180317, -0.029590027406811714, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.0409141443669796, 0.29503965377807617, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.4981, "q": [-0.31354227662086487, -0.01370697095990181, 0.015481031499803066, 0.629946231842041, -0.3265298902988434, 0.02109861932694912, -0.3221581280231476, 0.030057501047849655, -0.014744477346539497, 0.6210576891899109, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.0070344251580536366, -0.029594825580716133, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 5.5148, "q": [-0.31355932354927063, -0.01370697095990181, 0.015481031499803066, 0.629946231842041, -0.3265340030193329, 0.021091332659125328, -0.32212403416633606, 0.030057501047849655, -0.014731084927916527, 0.621049165725708, -0.33667370676994324, -0.020985309034585953, 0.002718554809689522, 0.006996462121605873, -0.02961919456720352, 0.2904736399650574, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 5.5315, "q": [-0.31354227662086487, -0.01370697095990181, 0.0154542475938797, 0.6299377083778381, -0.3265298902988434, 0.02109861932694912, -0.32212403416633606, 0.030048979446291924, -0.01479804515838623, 0.6210065484046936, -0.33666959404945374, -0.021007122471928596, 0.002731946762651205, 0.0070648095570504665, -0.02959497459232807, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.1576405018568039, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.5485, "q": [-0.31355080008506775, -0.013698449358344078, 0.015481031499803066, 0.6299036145210266, -0.3265381455421448, 0.021113082766532898, -0.3221069872379303, 0.030048979446291924, -0.014757868833839893, 0.6210065484046936, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.007049609441310167, -0.029585078358650208, 0.2904376983642578, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.5654, "q": [-0.31354227662086487, -0.013672882691025734, 0.015481031499803066, 0.6299036145210266, -0.3265340030193329, 0.021091332659125328, -0.3221155107021332, 0.030074546113610268, -0.014771261252462864, 0.6209980249404907, -0.3366572856903076, -0.02099994756281376, 0.002718554809689522, 0.00705720204859972, -0.02958020567893982, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 5.5821, "q": [-0.313533753156662, -0.013681404292583466, 0.015467639081180096, 0.6298950910568237, -0.3265298902988434, 0.02109861932694912, -0.3221155107021332, 0.030066022649407387, -0.01478465273976326, 0.620980978012085, -0.33666548132896423, -0.020999889820814133, 0.002731946762651205, 0.00706480210646987, -0.029585152864456177, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.052442967891693115, 0.008856342174112797]}
|
||||
{"t": 5.5988, "q": [-0.3135252296924591, -0.013655837625265121, 0.015481031499803066, 0.6298695802688599, -0.3265298902988434, 0.02109861932694912, -0.3221069872379303, 0.030066022649407387, -0.014771261252462864, 0.6209639310836792, -0.33667370676994324, -0.020985309034585953, 0.002758730435743928, 0.007057209499180317, -0.029590027406811714, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.6156, "q": [-0.313533753156662, -0.013672882691025734, 0.015481031499803066, 0.629878044128418, -0.3265298902988434, 0.02109861932694912, -0.3220984637737274, 0.030074546113610268, -0.01478465273976326, 0.6209468841552734, -0.33666548132896423, -0.020999889820814133, 0.0026783791836351156, 0.007049609441310167, -0.029585078358650208, 0.29042571783065796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.0088803106918931]}
|
||||
{"t": 5.6324, "q": [-0.313533753156662, -0.013672882691025734, 0.015467639081180096, 0.6298269629478455, -0.3265298902988434, 0.02109861932694912, -0.32212403416633606, 0.030066022649407387, -0.014811436645686626, 0.6209298372268677, -0.33666548132896423, -0.020999889820814133, 0.0027051628567278385, 0.007079987786710262, -0.02957540564239025, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.6491, "q": [-0.31354227662086487, -0.013664361089468002, 0.015467639081180096, 0.6298184394836426, -0.3265298902988434, 0.02109861932694912, -0.3220643997192383, 0.030083067715168, -0.01479804515838623, 0.6209127902984619, -0.3366613984107971, -0.02099265716969967, 0.002718554809689522, 0.007064794655889273, -0.029575331136584282, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.6658, "q": [-0.3135252296924591, -0.013655837625265121, 0.015481031499803066, 0.6298184394836426, -0.3265257775783539, 0.02110590599477291, -0.3220473527908325, 0.030083067715168, -0.01478465273976326, 0.6208616495132446, -0.3366572856903076, -0.020985424518585205, 0.0026649872306734324, 0.00704960199072957, -0.029575256630778313, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 5.6826, "q": [-0.3135167062282562, -0.013655837625265121, 0.015481031499803066, 0.6298099160194397, -0.3265298902988434, 0.02109861932694912, -0.32198768854141235, 0.030083067715168, -0.01479804515838623, 0.620836079120636, -0.3366613984107971, -0.02099265716969967, 0.0027051628567278385, 0.007064787205308676, -0.029565509408712387, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.6993, "q": [-0.3134911358356476, -0.013672882691025734, 0.0154542475938797, 0.6298099160194397, -0.3265340030193329, 0.021105842664837837, -0.32193654775619507, 0.03009158931672573, -0.01479804515838623, 0.6208105683326721, -0.3366613984107971, -0.02099265716969967, 0.0027051628567278385, 0.007064787205308676, -0.029565509408712387, 0.29042571783065796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 5.716, "q": [-0.31350818276405334, -0.013638794422149658, 0.0154542475938797, 0.629784345626831, -0.3265298902988434, 0.02109861932694912, -0.32194507122039795, 0.030083067715168, -0.014838220551609993, 0.6207168102264404, -0.33666959404945374, -0.021007122471928596, 0.0027051628567278385, 0.00704960199072957, -0.029575256630778313, 0.29042571783065796, 0.21594375371932983, -0.005201153922826052, 0.9791951179504395, 0.15755660831928253, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008832373656332493]}
|
||||
{"t": 5.7328, "q": [-0.3134826123714447, -0.013664361089468002, 0.0154542475938797, 0.6297502517700195, -0.3265257775783539, 0.021091395989060402, -0.3219109773635864, 0.030083067715168, -0.014838220551609993, 0.6207082867622375, -0.33666548132896423, -0.020999889820814133, 0.002691771136596799, 0.007133121136575937, -0.029521644115447998, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 5.7498, "q": [-0.3134826123714447, -0.01364731602370739, 0.015440856106579304, 0.6297417283058167, -0.3265298902988434, 0.02109861932694912, -0.3218854069709778, 0.03009158931672573, -0.014811436645686626, 0.6206912398338318, -0.33666548132896423, -0.020999889820814133, 0.002731946762651205, 0.007110335864126682, -0.029526444151997566, 0.29042571783065796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.7665, "q": [-0.3134826123714447, -0.01364731602370739, 0.015467639081180096, 0.6297332048416138, -0.3265298902988434, 0.02111312933266163, -0.3218683898448944, 0.03009158931672573, -0.014811436645686626, 0.6206486225128174, -0.33667370676994324, -0.020985309034585953, 0.002718554809689522, 0.007102735806256533, -0.02952149510383606, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.7833, "q": [-0.3134826123714447, -0.013655837625265121, 0.015467639081180096, 0.629716157913208, -0.3265257775783539, 0.02110590599477291, -0.3218342959880829, 0.03009158931672573, -0.014824828132987022, 0.6206145286560059, -0.3366531729698181, -0.021007239818572998, 0.002731946762651205, 0.007095127832144499, -0.029506726190447807, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 5.8, "q": [-0.31346556544303894, -0.01364731602370739, 0.0154542475938797, 0.6297076344490051, -0.3265257775783539, 0.02110590599477291, -0.32182577252388, 0.030083067715168, -0.014811436645686626, 0.6205889582633972, -0.3366572856903076, -0.02099994756281376, 0.002691771136596799, 0.0071027278900146484, -0.029511673375964165, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15765248239040375, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.8168, "q": [-0.3134485185146332, -0.013638794422149658, 0.015467639081180096, 0.6296905875205994, -0.3265298902988434, 0.02109861932694912, -0.32182577252388, 0.030100110918283463, -0.014838220551609993, 0.6205548644065857, -0.336649090051651, -0.021014530211687088, 0.002731946762651205, 0.0071027204394340515, -0.02950185164809227, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.29503965377807617, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.8336, "q": [-0.3134399950504303, -0.013638794422149658, 0.0154542475938797, 0.6296905875205994, -0.3265257775783539, 0.02110590599477291, -0.3217746317386627, 0.030100110918283463, -0.014824828132987022, 0.6205037236213684, -0.3366572856903076, -0.020985424518585205, 0.002758730435743928, 0.007110306061804295, -0.029487160965800285, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 5.8503, "q": [-0.31342294812202454, -0.013638794422149658, 0.015427463687956333, 0.6296394467353821, -0.3265298902988434, 0.02109861932694912, -0.3217746317386627, 0.030100110918283463, -0.014838220551609993, 0.6204696297645569, -0.336649090051651, -0.02098548412322998, 0.0027051628567278385, 0.0071254912763834, -0.02947741374373436, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 5.8671, "q": [-0.3134314715862274, -0.013621749356389046, 0.015427463687956333, 0.6296138763427734, -0.3265422582626343, 0.021105796098709106, -0.3217490613460541, 0.030100110918283463, -0.014838220551609993, 0.6203929781913757, -0.3366572856903076, -0.020985424518585205, 0.0027051628567278385, 0.0071254912763834, -0.02947741374373436, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 5.8838, "q": [-0.31341442465782166, -0.013630270957946777, 0.015400679782032967, 0.6295627355575562, -0.3265298902988434, 0.02109861932694912, -0.3217320144176483, 0.030108634382486343, -0.014851612038910389, 0.6203588843345642, -0.336649090051651, -0.02098548412322998, 0.002731946762651205, 0.007140676956623793, -0.029467666521668434, 0.29044967889785767, 0.2159797102212906, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 5.9006, "q": [-0.31340593099594116, -0.013630270957946777, 0.015427463687956333, 0.6295201182365417, -0.3265298902988434, 0.02109861932694912, -0.32171496748924255, 0.03009158931672573, -0.014851612038910389, 0.6203333139419556, -0.3366572856903076, -0.020985424518585205, 0.002691771136596799, 0.007140670903027058, -0.029457861557602882, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04087819159030914, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.9173, "q": [-0.31340593099594116, -0.013621749356389046, 0.015414072200655937, 0.6295286417007446, -0.3265257775783539, 0.02110590599477291, -0.3216553330421448, 0.030100110918283463, -0.014851612038910389, 0.6202566027641296, -0.3366572856903076, -0.020985424518585205, 0.0026649872306734324, 0.007125479634851217, -0.029457805678248405, 0.2904736399650574, 0.21596772968769073, -0.005225121974945068, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.9343, "q": [-0.31340593099594116, -0.013613227754831314, 0.01538728829473257, 0.6294775605201721, -0.3265340030193329, 0.021105842664837837, -0.32166385650634766, 0.030100110918283463, -0.014905179850757122, 0.620162844657898, -0.3366572856903076, -0.020985424518585205, 0.002718554809689522, 0.007171047385782003, -0.029448170214891434, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.951, "q": [-0.3133974075317383, -0.013604706153273582, 0.015347111970186234, 0.629417896270752, -0.3265340030193329, 0.021105842664837837, -0.32166385650634766, 0.03009158931672573, -0.014918571338057518, 0.6200435757637024, -0.3366572856903076, -0.020985424518585205, 0.0027051628567278385, 0.00714826351031661, -0.029452988877892494, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9791951179504395, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.29507559537887573, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008832373656332493]}
|
||||
{"t": 5.9677, "q": [-0.3133888840675354, -0.013604706153273582, 0.015347111970186234, 0.6293582320213318, -0.3265340030193329, 0.021105842664837837, -0.32167237997055054, 0.03009158931672573, -0.014905179850757122, 0.6200180053710938, -0.336649090051651, -0.020970961079001427, 0.002691771136596799, 0.00714826351031661, -0.029452988877892494, 0.2904376983642578, 0.2159797102212906, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 5.9846, "q": [-0.3133974075317383, -0.013596182689070702, 0.015347111970186234, 0.6292900443077087, -0.3265298902988434, 0.02111312933266163, -0.3216809034347534, 0.030100110918283463, -0.014905179850757122, 0.6199157238006592, -0.3366572856903076, -0.020985424518585205, 0.0027453387156128883, 0.007186232600361109, -0.029438422992825508, 0.2904616594314575, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 6.0013, "q": [-0.3133974075317383, -0.013613227754831314, 0.015347111970186234, 0.6292048096656799, -0.3265381455421448, 0.021113082766532898, -0.3216809034347534, 0.030108634382486343, -0.014891788363456726, 0.6198475360870361, -0.3366572856903076, -0.020985424518585205, 0.002691771136596799, 0.007148257456719875, -0.029443183913826942, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.018, "q": [-0.31340593099594116, -0.013621749356389046, 0.015333720482885838, 0.6291195750236511, -0.3265298902988434, 0.02109861932694912, -0.3216894268989563, 0.030117155984044075, -0.01486500445753336, 0.6197367310523987, -0.3366532027721405, -0.02097819373011589, 0.002758730435743928, 0.007186220958828926, -0.029418814927339554, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.0351, "q": [-0.31341442465782166, -0.013613227754831314, 0.015320328995585442, 0.6290770173072815, -0.3265340030193329, 0.021105842664837837, -0.3216809034347534, 0.030108634382486343, -0.014878395944833755, 0.6196515560150146, -0.336649090051651, -0.020970961079001427, 0.002691771136596799, 0.007155856117606163, -0.029448114335536957, 0.2904376983642578, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15765248239040375, 0.06167082488536835, -0.04090216010808945, 0.29502764344215393, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18358634412288666, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 6.0519, "q": [-0.3133974075317383, -0.013596182689070702, 0.015320328995585442, 0.6290684938430786, -0.3265298902988434, 0.02109861932694912, -0.3216468095779419, 0.030108634382486343, -0.014931963756680489, 0.6196174621582031, -0.3366532027721405, -0.02097819373011589, 0.002691771136596799, 0.007171041332185268, -0.02943836711347103, 0.29044967889785767, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.0409141443669796, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 6.0686, "q": [-0.3134314715862274, -0.013596182689070702, 0.015306936576962471, 0.6290343999862671, -0.3265381455421448, 0.021113082766532898, -0.3216468095779419, 0.030125677585601807, -0.014878395944833755, 0.6195748448371887, -0.3366532027721405, -0.02097819373011589, 0.0026783791836351156, 0.007171035744249821, -0.02942856401205063, 0.2904616594314575, 0.2159797102212906, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.06169478967785835, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.0854, "q": [-0.31341442465782166, -0.01358766108751297, 0.015320328995585442, 0.6289917826652527, -0.3265340030193329, 0.021105842664837837, -0.3216553330421448, 0.030125677585601807, -0.014891788363456726, 0.6194725632667542, -0.336649090051651, -0.020970961079001427, 0.0026649872306734324, 0.007193813566118479, -0.029413942247629166, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 6.1023, "q": [-0.31342294812202454, -0.013613227754831314, 0.015320328995585442, 0.6289406418800354, -0.3265340030193329, 0.021105842664837837, -0.3216468095779419, 0.030134201049804688, -0.014878395944833755, 0.6193873286247253, -0.3366450071334839, -0.020978251472115517, 0.002691771136596799, 0.007178616244345903, -0.029404081404209137, 0.2904616594314575, 0.21594375371932983, -0.0051891696639359, 0.9791830778121948, 0.15758058428764343, 0.0616828091442585, -0.0409141443669796, 0.2950156629085541, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835264265537262, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.119, "q": [-0.31341442465782166, -0.01358766108751297, 0.015320328995585442, 0.6289406418800354, -0.3265298902988434, 0.02111312933266163, -0.3215530514717102, 0.03014272265136242, -0.014905179850757122, 0.6193873286247253, -0.3366408944129944, -0.02100006490945816, 0.002691771136596799, 0.007148239761590958, -0.029413774609565735, 0.29040175676345825, 0.2159557342529297, -0.005201153922826052, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.1358, "q": [-0.31342294812202454, -0.01358766108751297, 0.015347111970186234, 0.6289491653442383, -0.3265381455421448, 0.021113082766532898, -0.32153600454330444, 0.03015124425292015, -0.014891788363456726, 0.6193192005157471, -0.3366532027721405, -0.02097819373011589, 0.002691771136596799, 0.007140625733882189, -0.029379436746239662, 0.29040175676345825, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.1526, "q": [-0.3133974075317383, -0.013579139485955238, 0.015360504388809204, 0.6289406418800354, -0.3265257775783539, 0.02110590599477291, -0.32153600454330444, 0.03015124425292015, -0.014931963756680489, 0.6193192005157471, -0.33663269877433777, -0.021000124514102936, 0.002718554809689522, 0.007178594823926687, -0.029364870861172676, 0.2904137372970581, 0.21596772968769073, -0.0051891696639359, 0.9791830778121948, 0.15756858885288239, 0.0616828091442585, -0.0409141443669796, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 6.1693, "q": [-0.3133974075317383, -0.013570617884397507, 0.015360504388809204, 0.6289406418800354, -0.3265298902988434, 0.02109861932694912, -0.3215104341506958, 0.03015124425292015, -0.014918571338057518, 0.6192936301231384, -0.3366367816925049, -0.02100735530257225, 0.002731946762651205, 0.007193774450570345, -0.0293453186750412, 0.2903897762298584, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 6.186, "q": [-0.3133888840675354, -0.013596182689070702, 0.0153738958761096, 0.6289406418800354, -0.3265340030193329, 0.021105842664837837, -0.32147637009620667, 0.030159765854477882, -0.014905179850757122, 0.6192936301231384, -0.33663269877433777, -0.021000124514102936, 0.002691771136596799, 0.007186163682490587, -0.02932078205049038, 0.29040175676345825, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.052383050322532654, 0.008832373656332493]}
|
||||
{"t": 6.2029, "q": [-0.31337183713912964, -0.01358766108751297, 0.01538728829473257, 0.6289406418800354, -0.326521635055542, 0.021113192662596703, -0.3214252293109894, 0.030159765854477882, -0.014918571338057518, 0.6192765831947327, -0.33663269877433777, -0.021000124514102936, 0.002691771136596799, 0.0071861459873616695, -0.029291372746229172, 0.29037776589393616, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.06167082488536835, -0.040890175849199295, 0.2950156629085541, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 6.2196, "q": [-0.31327807903289795, -0.013579139485955238, 0.015360504388809204, 0.6289321184158325, -0.3265298902988434, 0.02109861932694912, -0.3213314712047577, 0.03015124425292015, -0.014905179850757122, 0.6192680597305298, -0.33663269877433777, -0.021000124514102936, 0.0026649872306734324, 0.007239282596856356, -0.029237648472189903, 0.29037776589393616, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.1576405018568039, 0.0616828091442585, -0.0409141443669796, 0.2950036823749542, -0.2238173931837082, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 6.2365, "q": [-0.31319287419319153, -0.013570617884397507, 0.015400679782032967, 0.6289321184158325, -0.3265298902988434, 0.02109861932694912, -0.3212292194366455, 0.030168289318680763, -0.014918571338057518, 0.6192765831947327, -0.33663269877433777, -0.021000124514102936, 0.0026783791836351156, 0.007239239756017923, -0.029169024899601936, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.0409141443669796, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.2533, "q": [-0.31313320994377136, -0.013596182689070702, 0.0153738958761096, 0.6289321184158325, -0.3265257775783539, 0.02110590599477291, -0.32116955518722534, 0.030176810920238495, -0.014931963756680489, 0.6192595362663269, -0.33662858605384827, -0.021007433533668518, 0.002691771136596799, 0.007246814668178558, -0.029134739190340042, 0.2904137372970581, 0.2159797102212906, -0.005201153922826052, 0.9792190790176392, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 6.27, "q": [-0.3130309283733368, -0.013579139485955238, 0.01538728829473257, 0.6289321184158325, -0.3265257775783539, 0.02110590599477291, -0.3211354613304138, 0.030176810920238495, -0.014918571338057518, 0.6192595362663269, -0.33662447333335876, -0.021000200882554054, 0.002718554809689522, 0.007360704708844423, -0.029061632230877876, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.2867, "q": [-0.3129883408546448, -0.013570617884397507, 0.0153738958761096, 0.6289065480232239, -0.3265257775783539, 0.02110590599477291, -0.3210587799549103, 0.030185332521796227, -0.014931963756680489, 0.619251012802124, -0.33662858605384827, -0.020992891862988472, 0.002691771136596799, 0.007368279621005058, -0.029027346521615982, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.0409141443669796, 0.2950036823749542, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.3036, "q": [-0.3129883408546448, -0.01358766108751297, 0.0153738958761096, 0.6288809776306152, -0.3265257775783539, 0.02110590599477291, -0.3210502564907074, 0.030185332521796227, -0.014931963756680489, 0.6192595362663269, -0.33663269877433777, -0.021000124514102936, 0.002691771136596799, 0.007383470889180899, -0.02902740240097046, 0.29042571783065796, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.3204, "q": [-0.3129883408546448, -0.013570617884397507, 0.015347111970186234, 0.6288639307022095, -0.3265340030193329, 0.021105842664837837, -0.32103320956230164, 0.030193854123353958, -0.014945355243980885, 0.6192424893379211, -0.33662858605384827, -0.020992891862988472, 0.002691771136596799, 0.007421433925628662, -0.02900303341448307, 0.29042571783065796, 0.2159797102212906, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.3371, "q": [-0.3129883408546448, -0.013562094420194626, 0.015347111970186234, 0.6288809776306152, -0.3265298902988434, 0.02109861932694912, -0.32103320956230164, 0.030185332521796227, -0.014931963756680489, 0.6192169189453125, -0.33662858605384827, -0.020992891862988472, 0.002731946762651205, 0.007375883869826794, -0.0290420800447464, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.2237934172153473, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.354, "q": [-0.31294572353363037, -0.013553572818636894, 0.015347111970186234, 0.6288639307022095, -0.3265257775783539, 0.02110590599477291, -0.3210417330265045, 0.030193854123353958, -0.014918571338057518, 0.6192339658737183, -0.33663269877433777, -0.020985601469874382, 0.002731946762651205, 0.007391063496470451, -0.02902252972126007, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.0409141443669796, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.3707, "q": [-0.3129372000694275, -0.013553572818636894, 0.015320328995585442, 0.6288383603096008, -0.3265298902988434, 0.02109861932694912, -0.3210161626338959, 0.030193854123353958, -0.014918571338057518, 0.6192169189453125, -0.33663269877433777, -0.021000124514102936, 0.002691771136596799, 0.007413847371935844, -0.02901771105825901, 0.2904376983642578, 0.21594375371932983, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.3874, "q": [-0.31292015314102173, -0.013553572818636894, 0.015306936576962471, 0.6288383603096008, -0.3265298902988434, 0.02109861932694912, -0.32102468609809875, 0.030185332521796227, -0.014931963756680489, 0.6192083954811096, -0.3366367816925049, -0.020992834120988846, 0.002718554809689522, 0.007368285208940506, -0.029037151485681534, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22378143668174744, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.4042, "q": [-0.31292015314102173, -0.013553572818636894, 0.015293545089662075, 0.6288213133811951, -0.3265257775783539, 0.02110590599477291, -0.32103320956230164, 0.030193854123353958, -0.014958747662603855, 0.6191913485527039, -0.33663681149482727, -0.020978311076760292, 0.002718554809689522, 0.007375883869826794, -0.0290420800447464, 0.2904616594314575, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.4209, "q": [-0.31290310621261597, -0.01352800615131855, 0.015293545089662075, 0.6287616491317749, -0.3265298902988434, 0.02108410932123661, -0.3210417330265045, 0.03020237758755684, -0.014905179850757122, 0.619182825088501, -0.3366408944129944, -0.020985541865229607, 0.002718554809689522, 0.007398668210953474, -0.02903726138174534, 0.2904736399650574, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.4376, "q": [-0.31291162967681885, -0.01352800615131855, 0.015293545089662075, 0.6287105679512024, -0.3265257775783539, 0.021091395989060402, -0.3210587799549103, 0.030193854123353958, -0.014905179850757122, 0.6191146373748779, -0.33663269877433777, -0.020985601469874382, 0.002731946762651205, 0.007383482530713081, -0.029047010466456413, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.4543, "q": [-0.31292015314102173, -0.01352800615131855, 0.015280152671039104, 0.6286935210227966, -0.3265381157398224, 0.021084045991301537, -0.3210587799549103, 0.030193854123353958, -0.014918571338057518, 0.6190890669822693, -0.3366408944129944, -0.020985541865229607, 0.002758730435743928, 0.007383494637906551, -0.02906661666929722, 0.29044967889785767, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.4711, "q": [-0.3129286766052246, -0.013536527752876282, 0.015306936576962471, 0.6286764740943909, -0.3265298902988434, 0.02109861932694912, -0.32106730341911316, 0.030193854123353958, -0.014931963756680489, 0.6190634965896606, -0.3366408944129944, -0.020985541865229607, 0.002691771136596799, 0.007375895977020264, -0.029061686247587204, 0.2904616594314575, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.4878, "q": [-0.3129372000694275, -0.013519484549760818, 0.015266761183738708, 0.6286509037017822, -0.3265257775783539, 0.02110590599477291, -0.3210587799549103, 0.03020237758755684, -0.014945355243980885, 0.619037926197052, -0.336649090051651, -0.020970961079001427, 0.0027453387156128883, 0.007368297316133976, -0.02905675768852234, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15754462778568268, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 6.5045, "q": [-0.3129286766052246, -0.013545051217079163, 0.015280152671039104, 0.6286168098449707, -0.3265257775783539, 0.02110590599477291, -0.32106730341911316, 0.03020237758755684, -0.014945355243980885, 0.6189953088760376, -0.3366408944129944, -0.020971018821001053, 0.002718554809689522, 0.007360698655247688, -0.029051827266812325, 0.29042571783065796, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.5214, "q": [-0.31296277046203613, -0.013545051217079163, 0.015280152671039104, 0.6285741925239563, -0.3265298902988434, 0.02109861932694912, -0.32106730341911316, 0.03020237758755684, -0.014891788363456726, 0.6189101338386536, -0.3366449773311615, -0.02099277451634407, 0.002731946762651205, 0.007375883869826794, -0.0290420800447464, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.5383, "q": [-0.31294572353363037, -0.013553572818636894, 0.015280152671039104, 0.6285400986671448, -0.3265257775783539, 0.021091395989060402, -0.32103320956230164, 0.03020237758755684, -0.014918571338057518, 0.618876039981842, -0.3366367816925049, -0.020963769406080246, 0.0027051628567278385, 0.007368297316133976, -0.02905675768852234, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.555, "q": [-0.31291162967681885, -0.01352800615131855, 0.015306936576962471, 0.628523051738739, -0.3265257775783539, 0.02110590599477291, -0.32103320956230164, 0.03020237758755684, -0.014918571338057518, 0.6188248991966248, -0.3366367816925049, -0.020992834120988846, 0.002691771136596799, 0.007345507387071848, -0.029051773250102997, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.5718, "q": [-0.31294572353363037, -0.013545051217079163, 0.015320328995585442, 0.6284889578819275, -0.3265340030193329, 0.021105842664837837, -0.3210161626338959, 0.03020237758755684, -0.014918571338057518, 0.6187737584114075, -0.33663269877433777, -0.021000124514102936, 0.002731946762651205, 0.007368291262537241, -0.029046954587101936, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 6.5885, "q": [-0.3129372000694275, -0.013536527752876282, 0.015333720482885838, 0.6284719109535217, -0.3265381157398224, 0.021084045991301537, -0.321007639169693, 0.03020237758755684, -0.014918571338057518, 0.6187481880187988, -0.33662858605384827, -0.020992891862988472, 0.002691771136596799, 0.007353088352829218, -0.029027290642261505, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.6053, "q": [-0.31292015314102173, -0.013553572818636894, 0.015333720482885838, 0.6284463405609131, -0.3265257775783539, 0.02110590599477291, -0.3209564983844757, 0.03020237758755684, -0.014918571338057518, 0.6186970472335815, -0.33662447333335876, -0.020985642448067665, 0.002691771136596799, 0.007330292370170355, -0.02901250310242176, 0.29037776589393616, 0.21594375371932983, -0.005201153922826052, 0.9791830778121948, 0.1575925648212433, 0.06167082488536835, -0.040890175849199295, 0.29499170184135437, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.622, "q": [-0.3129372000694275, -0.013553572818636894, 0.015360504388809204, 0.6284037232398987, -0.3265381157398224, 0.021084045991301537, -0.3209564983844757, 0.030193854123353958, -0.014918571338057518, 0.61866295337677, -0.33662447333335876, -0.020985642448067665, 0.002731946762651205, 0.007330280262976885, -0.028992895036935806, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.1576405018568039, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 6.6389, "q": [-0.31290310621261597, -0.013545051217079163, 0.015347111970186234, 0.6283951997756958, -0.3265298902988434, 0.02109861932694912, -0.32087981700897217, 0.03020237758755684, -0.014918571338057518, 0.6186288595199585, -0.33662858605384827, -0.020992891862988472, 0.002691771136596799, 0.007322681602090597, -0.02898796647787094, 0.29040175676345825, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.1835743635892868, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 6.6556, "q": [-0.31290310621261597, -0.013553572818636894, 0.015333720482885838, 0.62837815284729, -0.3265298902988434, 0.02109861932694912, -0.32088834047317505, 0.03021089918911457, -0.014958747662603855, 0.6186118125915527, -0.33663269877433777, -0.020971059799194336, 0.002691771136596799, 0.007383422926068306, -0.02894897572696209, 0.29042571783065796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.0088803106918931]}
|
||||
{"t": 6.6724, "q": [-0.3128775358200073, -0.013545051217079163, 0.015333720482885838, 0.6283696293830872, -0.3265381455421448, 0.021113082766532898, -0.32083719968795776, 0.03020237758755684, -0.014958747662603855, 0.6185862421989441, -0.33663269877433777, -0.020971059799194336, 0.002718554809689522, 0.007391003891825676, -0.028924494981765747, 0.29040175676345825, 0.2159557342529297, -0.005225121974945068, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 6.6893, "q": [-0.31286048889160156, -0.013545051217079163, 0.015306936576962471, 0.6283526420593262, -0.3265340030193329, 0.021105842664837837, -0.3208286762237549, 0.03020237758755684, -0.014945355243980885, 0.6186032891273499, -0.33663269877433777, -0.020985601469874382, 0.002758730435743928, 0.007391003891825676, -0.028924494981765747, 0.2904137372970581, 0.2159557342529297, -0.005201153922826052, 0.9791951179504395, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 6.706, "q": [-0.3128434419631958, -0.013553572818636894, 0.015320328995585442, 0.6283526420593262, -0.3265340030193329, 0.021105842664837837, -0.32080310583114624, 0.030193854123353958, -0.014931963756680489, 0.6186032891273499, -0.3366408944129944, -0.020985541865229607, 0.002718554809689522, 0.007398590445518494, -0.028909817337989807, 0.29040175676345825, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.7227, "q": [-0.31281790137290955, -0.013536527752876282, 0.015320328995585442, 0.6283100247383118, -0.3265257775783539, 0.02110590599477291, -0.32080310583114624, 0.03020237758755684, -0.014958747662603855, 0.618594765663147, -0.3366408944129944, -0.020985541865229607, 0.002731946762651205, 0.007444152608513832, -0.028890376910567284, 0.29042571783065796, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.7395, "q": [-0.31280937790870667, -0.013553572818636894, 0.015293545089662075, 0.6282674074172974, -0.3265257775783539, 0.02110590599477291, -0.320820152759552, 0.030193854123353958, -0.014945355243980885, 0.6185692548751831, -0.3366450071334839, -0.020963728427886963, 0.002718554809689522, 0.007436553947627544, -0.02888544835150242, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.7562, "q": [-0.31281790137290955, -0.013519484549760818, 0.015280152671039104, 0.628224790096283, -0.3265298902988434, 0.02109861932694912, -0.32080310583114624, 0.03020237758755684, -0.014931963756680489, 0.6185266375541687, -0.336649090051651, -0.020970961079001427, 0.002691771136596799, 0.00745173916220665, -0.028875699266791344, 0.2904376983642578, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.7731, "q": [-0.3128008544445038, -0.013510962948203087, 0.015253368765115738, 0.628224790096283, -0.3265340030193329, 0.021091332659125328, -0.320820152759552, 0.03020237758755684, -0.014945355243980885, 0.6184925436973572, -0.33663681149482727, -0.020978311076760292, 0.0027453387156128883, 0.007413770072162151, -0.02889026515185833, 0.2903897762298584, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04086620733141899, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.7898, "q": [-0.3128264248371124, -0.013502439484000206, 0.015266761183738708, 0.6281906962394714, -0.3265463709831238, 0.021083982661366463, -0.3208542466163635, 0.030193854123353958, -0.014931963756680489, 0.6184499263763428, -0.33665731549263, -0.020941857248544693, 0.002758730435743928, 0.007390991784632206, -0.028904886916279793, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.8066, "q": [-0.3128264248371124, -0.01346835121512413, 0.015239977277815342, 0.6281310319900513, -0.3265422582626343, 0.021091269329190254, -0.3209053874015808, 0.03020237758755684, -0.014958747662603855, 0.6183732151985168, -0.3366655111312866, -0.020941779017448425, 0.002691771136596799, 0.007421380374580622, -0.02891480177640915, 0.2904616594314575, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.2237934172153473, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.8233, "q": [-0.3128434419631958, -0.013476874679327011, 0.015239977277815342, 0.6280969381332397, -0.3265340030193329, 0.021091332659125328, -0.3209139108657837, 0.030193854123353958, -0.014958747662603855, 0.6183391213417053, -0.3366655111312866, -0.020941779017448425, 0.002691771136596799, 0.007406201213598251, -0.028934353962540627, 0.2904616594314575, 0.21594375371932983, -0.00523710623383522, 0.9792070984840393, 0.15758058428764343, 0.06169478967785835, -0.04090216010808945, 0.29502764344215393, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.84, "q": [-0.31286901235580444, -0.01346835121512413, 0.015253368765115738, 0.628079891204834, -0.3265340030193329, 0.021091332659125328, -0.3209139108657837, 0.030193854123353958, -0.014931963756680489, 0.6183220744132996, -0.336665540933609, -0.02092725783586502, 0.002731946762651205, 0.007406201213598251, -0.028934353962540627, 0.2904616594314575, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008832373656332493]}
|
||||
{"t": 6.8568, "q": [-0.3128434419631958, -0.013485396280884743, 0.015226585790514946, 0.6280202269554138, -0.3265381157398224, 0.021098555997014046, -0.3209053874015808, 0.030193854123353958, -0.014918571338057518, 0.6182794570922852, -0.3366655111312866, -0.020941779017448425, 0.002758730435743928, 0.007406207267194986, -0.02894415706396103, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.8736, "q": [-0.3128434419631958, -0.01346835121512413, 0.015239977277815342, 0.6279776692390442, -0.3265381157398224, 0.021098555997014046, -0.3209224343299866, 0.03020237758755684, -0.014918571338057518, 0.618219792842865, -0.33665731549263, -0.020941857248544693, 0.0027051628567278385, 0.007398608606308699, -0.028939226642251015, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15752065181732178, 0.0616828091442585, -0.04087819159030914, 0.295051634311676, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 6.8903, "q": [-0.3128434419631958, -0.013459829613566399, 0.015239977277815342, 0.6279350519180298, -0.3265463709831238, 0.021098509430885315, -0.3209224343299866, 0.030185332521796227, -0.014945355243980885, 0.6181260943412781, -0.3366532027721405, -0.020949147641658783, 0.002718554809689522, 0.007383422926068306, -0.02894897572696209, 0.2904376983642578, 0.21596772968769073, -0.005201153922826052, 0.9791951179504395, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 6.9071, "q": [-0.3128434419631958, -0.013459829613566399, 0.015239977277815342, 0.6279009580612183, -0.3265381157398224, 0.021084045991301537, -0.3209139108657837, 0.030193854123353958, -0.014931963756680489, 0.6181175708770752, -0.3366532027721405, -0.020949147641658783, 0.002718554809689522, 0.007383422926068306, -0.02894897572696209, 0.29042571783065796, 0.21594375371932983, -0.0051891696639359, 0.9791951179504395, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.924, "q": [-0.3128519654273987, -0.013485396280884743, 0.015253368765115738, 0.6278839111328125, -0.3265422582626343, 0.021091269329190254, -0.3209139108657837, 0.030193854123353958, -0.014945355243980885, 0.6180238127708435, -0.336649090051651, -0.020941896364092827, 0.002758730435743928, 0.007391015999019146, -0.028944101184606552, 0.2904376983642578, 0.21593177318572998, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04086620733141899, 0.29503965377807617, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 6.9407, "q": [-0.31286048889160156, -0.013502439484000206, 0.015226585790514946, 0.6278157234191895, -0.3265422582626343, 0.021105796098709106, -0.3209053874015808, 0.03020237758755684, -0.014918571338057518, 0.6179726719856262, -0.3366532027721405, -0.020949147641658783, 0.0027721223887056112, 0.007368231657892466, -0.028948919847607613, 0.2904376983642578, 0.21596772968769073, -0.005201153922826052, 0.9791830778121948, 0.15762852132320404, 0.06169478967785835, -0.040890175849199295, 0.29502764344215393, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 6.9575, "q": [-0.31286901235580444, -0.013493917882442474, 0.015253368765115738, 0.6277986764907837, -0.3265340030193329, 0.021105842664837837, -0.32087981700897217, 0.03020237758755684, -0.014918571338057518, 0.6179471015930176, -0.33665731549263, -0.020941857248544693, 0.002718554809689522, 0.007360639050602913, -0.028953792527318, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.06169478967785835, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 6.9744, "q": [-0.31286901235580444, -0.013493917882442474, 0.015280152671039104, 0.6278157234191895, -0.3265381455421448, 0.021113082766532898, -0.32089686393737793, 0.03020237758755684, -0.014918571338057518, 0.6179300546646118, -0.3366655111312866, -0.020941779017448425, 0.002731946762651205, 0.007368226069957018, -0.02893911674618721, 0.29042571783065796, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 6.9911, "q": [-0.3128775358200073, -0.013510962948203087, 0.015266761183738708, 0.6277986764907837, -0.3265422582626343, 0.021076759323477745, -0.32083719968795776, 0.03021089918911457, -0.014931963756680489, 0.617913007736206, -0.33663269877433777, -0.021000124514102936, 0.0026382035575807095, 0.007368226069957018, -0.02893911674618721, 0.29040175676345825, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.1576644629240036, 0.0616828091442585, -0.0409141443669796, 0.29499170184135437, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18358634412288666, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.0078, "q": [-0.3128775358200073, -0.013519484549760818, 0.015280152671039104, 0.6277901530265808, -0.3265381455421448, 0.021113082766532898, -0.32079458236694336, 0.03020237758755684, -0.014958747662603855, 0.6178874373435974, -0.3366367816925049, -0.020992834120988846, 0.002691771136596799, 0.007368226069957018, -0.02893911674618721, 0.29040175676345825, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 7.0247, "q": [-0.3128519654273987, -0.013510962948203087, 0.015293545089662075, 0.6277986764907837, -0.3265381455421448, 0.021113082766532898, -0.32079458236694336, 0.03020237758755684, -0.014931963756680489, 0.6178789138793945, -0.3366367816925049, -0.020992834120988846, 0.002718554809689522, 0.007383393589407206, -0.028899958357214928, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780685901641846, -0.18356238305568695, 0.05241899937391281, 0.0088803106918931]}
|
||||
{"t": 7.0414, "q": [-0.31286048889160156, -0.01352800615131855, 0.015280152671039104, 0.6277986764907837, -0.3265340030193329, 0.021105842664837837, -0.32075196504592896, 0.03020237758755684, -0.014958747662603855, 0.6178874373435974, -0.3366367816925049, -0.020992834120988846, 0.002691771136596799, 0.007375794928520918, -0.028895027935504913, 0.29040175676345825, 0.2159557342529297, -0.0051891696639359, 0.9791830778121948, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.29499170184135437, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.0582, "q": [-0.3128519654273987, -0.01352800615131855, 0.015293545089662075, 0.6277986764907837, -0.3265298902988434, 0.02109861932694912, -0.32070085406303406, 0.03020237758755684, -0.014931963756680489, 0.6178874373435974, -0.3366367816925049, -0.020992834120988846, 0.002691771136596799, 0.007368178106844425, -0.02886068820953369, 0.2903897762298584, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.29499170184135437, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 7.0749, "q": [-0.31276676058769226, -0.013510962948203087, 0.015293545089662075, 0.627773106098175, -0.3265381455421448, 0.021113082766532898, -0.32066676020622253, 0.03020237758755684, -0.014918571338057518, 0.6178789138793945, -0.3366367816925049, -0.020992834120988846, 0.002718554809689522, 0.007421315182000399, -0.028806963935494423, 0.2903897762298584, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04087819159030914, 0.2949797213077545, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.0916, "q": [-0.3127582371234894, -0.013519484549760818, 0.015293545089662075, 0.6277901530265808, -0.3265257775783539, 0.02110590599477291, -0.32065823674201965, 0.030193854123353958, -0.014945355243980885, 0.6179044842720032, -0.3366408944129944, -0.020956479012966156, 0.002718554809689522, 0.007451679557561874, -0.02877766452729702, 0.2903897762298584, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 7.1086, "q": [-0.3127411901950836, -0.013519484549760818, 0.015293545089662075, 0.6277901530265808, -0.3265298902988434, 0.02111312933266163, -0.32060709595680237, 0.03020237758755684, -0.014985531568527222, 0.6178959608078003, -0.33663269877433777, -0.020985601469874382, 0.002691771136596799, 0.007436482701450586, -0.02876780554652214, 0.29040175676345825, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.1253, "q": [-0.3127070963382721, -0.013510962948203087, 0.015280152671039104, 0.6277645826339722, -0.3265340030193329, 0.021091332659125328, -0.3205985724925995, 0.03021089918911457, -0.014985531568527222, 0.6179044842720032, -0.33663269877433777, -0.020985601469874382, 0.0027855143416672945, 0.007512426003813744, -0.02874847874045372, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 7.142, "q": [-0.31259632110595703, -0.013510962948203087, 0.015266761183738708, 0.627773106098175, -0.3265340030193329, 0.021105842664837837, -0.3204622268676758, 0.03021089918911457, -0.014998923055827618, 0.617913007736206, -0.33663681149482727, -0.020978311076760292, 0.002691771136596799, 0.007482043467462063, -0.028748366981744766, 0.2904137372970581, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15758058428764343, 0.061706773936748505, -0.04090216010808945, 0.2950036823749542, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 7.1588, "q": [-0.3124769926071167, -0.013519484549760818, 0.015226585790514946, 0.6277645826339722, -0.3265340030193329, 0.021091332659125328, -0.32034292817115784, 0.030219420790672302, -0.015025706961750984, 0.617913007736206, -0.3366367816925049, -0.020963769406080246, 0.002691771136596799, 0.007520012557506561, -0.02873380109667778, 0.2904137372970581, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.1756, "q": [-0.31235769391059875, -0.013519484549760818, 0.015239977277815342, 0.6277560591697693, -0.3265381157398224, 0.021084045991301537, -0.32020655274391174, 0.03021089918911457, -0.014998923055827618, 0.617913007736206, -0.33663269877433777, -0.020971059799194336, 0.002691771136596799, 0.007504827342927456, -0.028743548318743706, 0.29042571783065796, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.1923, "q": [-0.31217020750045776, -0.013485396280884743, 0.015226585790514946, 0.6277645826339722, -0.3265340030193329, 0.021091332659125328, -0.320002019405365, 0.030227944254875183, -0.015025706961750984, 0.6179044842720032, -0.3366408944129944, -0.020956479012966156, 0.002691771136596799, 0.0074896421283483505, -0.02875329554080963, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.0409141443669796, 0.2950036823749542, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.209, "q": [-0.31203386187553406, -0.013459829613566399, 0.015226585790514946, 0.6277645826339722, -0.3265257775783539, 0.02110590599477291, -0.3198060393333435, 0.030236465856432915, -0.01505249086767435, 0.6179215312004089, -0.3366408944129944, -0.020956479012966156, 0.0027989062946289778, 0.00747445086017251, -0.028753241524100304, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.2258, "q": [-0.3118293285369873, -0.013459829613566399, 0.015173017978668213, 0.6277645826339722, -0.3265298902988434, 0.02108410932123661, -0.31959298253059387, 0.030244987457990646, -0.01503909844905138, 0.6179044842720032, -0.336649090051651, -0.020941896364092827, 0.002758730435743928, 0.007504815235733986, -0.0287239421159029, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.2425, "q": [-0.3116588890552521, -0.013451308012008667, 0.01519980188459158, 0.6277475357055664, -0.3265340030193329, 0.02107682265341282, -0.3194566071033478, 0.030236465856432915, -0.015079274773597717, 0.6178789138793945, -0.3366450071334839, -0.020963728427886963, 0.002758730435743928, 0.007512419950217009, -0.028738675639033318, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.2592, "q": [-0.31159070134162903, -0.013459829613566399, 0.015173017978668213, 0.6277475357055664, -0.3265381157398224, 0.021084045991301537, -0.3193202614784241, 0.030244987457990646, -0.015092666260898113, 0.6178703904151917, -0.3366450071334839, -0.020963728427886963, 0.0027989062946289778, 0.007520012557506561, -0.02873380109667778, 0.2904376983642578, 0.21594375371932983, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.276, "q": [-0.31153956055641174, -0.013451308012008667, 0.015132841654121876, 0.6277304887771606, -0.3265340030193329, 0.021091332659125328, -0.31927764415740967, 0.030244987457990646, -0.015079274773597717, 0.617844820022583, -0.336649090051651, -0.020970961079001427, 0.0027453387156128883, 0.007497228682041168, -0.02873861975967884, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.2927, "q": [-0.31153956055641174, -0.013451308012008667, 0.015132841654121876, 0.6277560591697693, -0.3265422582626343, 0.021091269329190254, -0.31924358010292053, 0.030244987457990646, -0.01505249086767435, 0.617844820022583, -0.3366532027721405, -0.020949147641658783, 0.0027453387156128883, 0.0074896421283483505, -0.02875329554080963, 0.29040175676345825, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29499170184135437, -0.22378143668174744, 0.023093601688742638, 0.9780685901641846, -0.18353840708732605, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 7.3094, "q": [-0.3115480840206146, -0.013451308012008667, 0.015146234072744846, 0.6277560591697693, -0.3265340030193329, 0.021105842664837837, -0.31923505663871765, 0.030244987457990646, -0.015079274773597717, 0.6178277730941772, -0.33665731549263, -0.020956380292773247, 0.002731946762651205, 0.0074896300211548805, -0.028733689337968826, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023081617429852486, 0.9780685901641846, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.3261, "q": [-0.3114969730377197, -0.013451308012008667, 0.015132841654121876, 0.6277560591697693, -0.3265381157398224, 0.021084045991301537, -0.3192180097103119, 0.030236465856432915, -0.015079274773597717, 0.6178277730941772, -0.3366450071334839, -0.020963728427886963, 0.0027453387156128883, 0.007512426003813744, -0.02874847874045372, 0.2904736399650574, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04087819159030914, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835264265537262, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 7.3428, "q": [-0.3114969730377197, -0.013459829613566399, 0.01511945016682148, 0.6277560591697693, -0.3265381157398224, 0.021084045991301537, -0.31920096278190613, 0.030236465856432915, -0.01505249086767435, 0.6178107857704163, -0.3366450071334839, -0.020963728427886963, 0.002624811604619026, 0.007466863840818405, -0.028767917305231094, 0.2904856503009796, 0.21594375371932983, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.0616828091442585, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 7.3595, "q": [-0.3114628791809082, -0.013442784547805786, 0.015146234072744846, 0.6277560591697693, -0.3265381157398224, 0.021098555997014046, -0.31920096278190613, 0.030236465856432915, -0.015065882354974747, 0.6178022623062134, -0.3366408944129944, -0.020956479012966156, 0.002731946762651205, 0.007451679557561874, -0.02877766452729702, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.06169478967785835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.1835503876209259, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.3763, "q": [-0.3115054965019226, -0.01346835121512413, 0.015146234072744846, 0.6277475357055664, -0.3265381157398224, 0.021098555997014046, -0.319209486246109, 0.030219420790672302, -0.01503909844905138, 0.6177511215209961, -0.3366450071334839, -0.020963728427886963, 0.002758730435743928, 0.0074592712335288525, -0.028772791847586632, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 7.393, "q": [-0.3115054965019226, -0.01346835121512413, 0.015146234072744846, 0.6277475357055664, -0.3265381455421448, 0.021113082766532898, -0.31920096278190613, 0.030219420790672302, -0.015079274773597717, 0.6177170276641846, -0.3366532027721405, -0.020949147641658783, 0.0027855143416672945, 0.007474462501704693, -0.02877284772694111, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04092612862586975, 0.29502764344215393, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 7.4097, "q": [-0.31153103709220886, -0.013476874679327011, 0.015132841654121876, 0.6277475357055664, -0.3265422582626343, 0.021105796098709106, -0.31919243931770325, 0.030219420790672302, -0.015092666260898113, 0.6176658868789673, -0.33665731549263, -0.020956380292773247, 0.002718554809689522, 0.007451679557561874, -0.02877766452729702, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008844357915222645]}
|
||||
{"t": 7.4264, "q": [-0.31153103709220886, -0.013459829613566399, 0.01511945016682148, 0.6277390122413635, -0.3265463709831238, 0.021113019436597824, -0.31920096278190613, 0.030219420790672302, -0.015092666260898113, 0.6176317930221558, -0.3366450071334839, -0.020949188619852066, 0.002718554809689522, 0.007428901735693216, -0.028792286291718483, 0.29042571783065796, 0.2159557342529297, -0.005201153922826052, 0.9791951179504395, 0.15760454535484314, 0.06167082488536835, -0.04090216010808945, 0.29503965377807617, -0.2237934172153473, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.4432, "q": [-0.3115651309490204, -0.013451308012008667, 0.015106058679521084, 0.6277304887771606, -0.3265463709831238, 0.021098509430885315, -0.319209486246109, 0.030227944254875183, -0.015092666260898113, 0.6175891757011414, -0.3366532027721405, -0.020949147641658783, 0.0026783791836351156, 0.007451691664755344, -0.028797272592782974, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.040890175849199295, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.4599, "q": [-0.31157365441322327, -0.013459829613566399, 0.015092666260898113, 0.6277304887771606, -0.3265422582626343, 0.021105796098709106, -0.31920096278190613, 0.030219420790672302, -0.015079274773597717, 0.6175550818443298, -0.3366532027721405, -0.020949147641658783, 0.002718554809689522, 0.007451679557561874, -0.02877766452729702, 0.2904616594314575, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.4768, "q": [-0.3115566074848175, -0.01346835121512413, 0.015092666260898113, 0.6277134418487549, -0.3265463709831238, 0.021098509430885315, -0.31920096278190613, 0.030227944254875183, -0.015106058679521084, 0.6174954175949097, -0.33665731549263, -0.020956380292773247, 0.002691771136596799, 0.007436494342982769, -0.028787413612008095, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.4935, "q": [-0.3115651309490204, -0.013485396280884743, 0.015092666260898113, 0.6276793479919434, -0.3265504837036133, 0.021105732768774033, -0.31920096278190613, 0.030219420790672302, -0.015079274773597717, 0.6174954175949097, -0.3366532027721405, -0.020949147641658783, 0.002691771136596799, 0.007436494342982769, -0.028787413612008095, 0.2904376983642578, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.5103, "q": [-0.3115992248058319, -0.01346835121512413, 0.015106058679521084, 0.6276793479919434, -0.3265422582626343, 0.021105796098709106, -0.31920096278190613, 0.030227944254875183, -0.015079274773597717, 0.6174954175949097, -0.336649090051651, -0.020941896364092827, 0.002758730435743928, 0.007444086950272322, -0.028782539069652557, 0.29042571783065796, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 7.527, "q": [-0.31159070134162903, -0.013476874679327011, 0.015092666260898113, 0.6276878714561462, -0.3265422582626343, 0.021120306104421616, -0.31920096278190613, 0.030227944254875183, -0.015079274773597717, 0.6174613237380981, -0.3366532027721405, -0.020949147641658783, 0.0026783791836351156, 0.007444086950272322, -0.028782539069652557, 0.2903897762298584, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.5437, "q": [-0.31159070134162903, -0.013451308012008667, 0.015106058679521084, 0.6276793479919434, -0.3265422582626343, 0.021120306104421616, -0.319209486246109, 0.030236465856432915, -0.015106058679521084, 0.6174442768096924, -0.336649090051651, -0.020941896364092827, 0.0027453387156128883, 0.007436494342982769, -0.028787413612008095, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29499170184135437, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.052442967891693115, 0.008868326433002949]}
|
||||
{"t": 7.5606, "q": [-0.31159070134162903, -0.01346835121512413, 0.015106058679521084, 0.6276793479919434, -0.3265381455421448, 0.021113082766532898, -0.3191668689250946, 0.030227944254875183, -0.01511945016682148, 0.6174358129501343, -0.3366532027721405, -0.020949147641658783, 0.002691771136596799, 0.007413704413920641, -0.028782427310943604, 0.2903897762298584, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15760454535484314, 0.06167082488536835, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 7.5773, "q": [-0.31159070134162903, -0.01346835121512413, 0.015106058679521084, 0.6276708245277405, -0.3265463709831238, 0.021098509430885315, -0.31914129853248596, 0.030227944254875183, -0.01511945016682148, 0.6174358129501343, -0.33665731549263, -0.020941857248544693, 0.0026783791836351156, 0.007421297021210194, -0.028777554631233215, 0.2904137372970581, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 7.594, "q": [-0.31157365441322327, -0.013451308012008667, 0.01511945016682148, 0.6276708245277405, -0.3265381455421448, 0.021113082766532898, -0.31914129853248596, 0.030236465856432915, -0.01511945016682148, 0.6174358129501343, -0.3366532027721405, -0.020949147641658783, 0.002691771136596799, 0.007444086950272322, -0.028782539069652557, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835503876209259, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 7.6109, "q": [-0.3115651309490204, -0.013485396280884743, 0.01511945016682148, 0.6276623010635376, -0.3265422582626343, 0.021105796098709106, -0.31914129853248596, 0.030236465856432915, -0.01511945016682148, 0.6174358129501343, -0.3366532027721405, -0.020949147641658783, 0.0026649872306734324, 0.007428890094161034, -0.028772680088877678, 0.29040175676345825, 0.21596772968769073, -0.005225121974945068, 0.9791830778121948, 0.15760454535484314, 0.06167082488536835, -0.040890175849199295, 0.2950036823749542, -0.22378143668174744, 0.023081617429852486, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 7.6277, "q": [-0.3115651309490204, -0.013459829613566399, 0.01511945016682148, 0.6276623010635376, -0.3265340030193329, 0.02112036943435669, -0.3191327750682831, 0.030219420790672302, -0.015132841654121876, 0.6174528002738953, -0.336649090051651, -0.020941896364092827, 0.0027453387156128883, 0.0074592651799321175, -0.02876298874616623, 0.2904137372970581, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 7.6444, "q": [-0.3115651309490204, -0.013485396280884743, 0.015106058679521084, 0.6276623010635376, -0.3265381455421448, 0.021113082766532898, -0.3190816342830658, 0.030244987457990646, -0.015092666260898113, 0.6174358129501343, -0.3366532027721405, -0.020949147641658783, 0.002691771136596799, 0.007474456448107958, -0.028763044625520706, 0.29042571783065796, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 7.6611, "q": [-0.31153103709220886, -0.013476874679327011, 0.015092666260898113, 0.6276878714561462, -0.3265340030193329, 0.021105842664837837, -0.31901347637176514, 0.03026203252375126, -0.015186409465968609, 0.6174613237380981, -0.3366408944129944, -0.020956479012966156, 0.002691771136596799, 0.0074592651799321175, -0.02876298874616623, 0.2904137372970581, 0.2159797102212906, -0.005213138181716204, 0.9792070984840393, 0.15758058428764343, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 7.6778, "q": [-0.3114714026451111, -0.013493917882442474, 0.015092666260898113, 0.6276878714561462, -0.3265381455421448, 0.021113082766532898, -0.31891971826553345, 0.030253509059548378, -0.015186409465968609, 0.6174783706665039, -0.3366450071334839, -0.020963728427886963, 0.002731946762651205, 0.007436482701450586, -0.02876780554652214, 0.29042571783065796, 0.2159557342529297, -0.0051891696639359, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.0409141443669796, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.6946, "q": [-0.31140321493148804, -0.01346835121512413, 0.015079274773597717, 0.6276963949203491, -0.3265340030193329, 0.021091332659125328, -0.3188430368900299, 0.030244987457990646, -0.01519980188459158, 0.6174442768096924, -0.336649090051651, -0.020941896364092827, 0.002691771136596799, 0.00747445086017251, -0.028753241524100304, 0.2904376983642578, 0.2159797102212906, -0.005225121974945068, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008832373656332493]}
|
||||
{"t": 7.7113, "q": [-0.31135207414627075, -0.013459829613566399, 0.01503909844905138, 0.6276963949203491, -0.3265422582626343, 0.021105796098709106, -0.31878337264060974, 0.030244987457990646, -0.01519980188459158, 0.6174868941307068, -0.33663681149482727, -0.020949246361851692, 0.002691771136596799, 0.0074668521992862225, -0.02874831110239029, 0.2904137372970581, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.061658840626478195, -0.04087819159030914, 0.2950036823749542, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.728, "q": [-0.31134355068206787, -0.01346835121512413, 0.01503909844905138, 0.627704918384552, -0.3265381455421448, 0.021113082766532898, -0.31873223185539246, 0.030244987457990646, -0.01519980188459158, 0.6174783706665039, -0.33663681149482727, -0.020949246361851692, 0.002718554809689522, 0.00745166651904583, -0.028758058324456215, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15760454535484314, 0.0616828091442585, -0.0409141443669796, 0.2950036823749542, -0.22380541265010834, 0.023069633170962334, 0.9780805706977844, -0.1835743635892868, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.745, "q": [-0.31126686930656433, -0.013451308012008667, 0.01505249086767435, 0.6277134418487549, -0.3265340030193329, 0.021091332659125328, -0.3186555504798889, 0.030253509059548378, -0.015213193371891975, 0.6174783706665039, -0.33663681149482727, -0.020978311076760292, 0.002691771136596799, 0.0074668521992862225, -0.02874831110239029, 0.2904137372970581, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.157616525888443, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.7617, "q": [-0.3112412989139557, -0.013459829613566399, 0.01505249086767435, 0.627704918384552, -0.3265381455421448, 0.021113082766532898, -0.3186555504798889, 0.030244987457990646, -0.015226585790514946, 0.6174783706665039, -0.3366450071334839, -0.020963728427886963, 0.0026649872306734324, 0.0074896421283483505, -0.02875329554080963, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.1575925648212433, 0.06167082488536835, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.7784, "q": [-0.3112327754497528, -0.013459829613566399, 0.015025706961750984, 0.627704918384552, -0.3265422582626343, 0.021105796098709106, -0.3186555504798889, 0.030244987457990646, -0.015226585790514946, 0.617469847202301, -0.336649090051651, -0.020970961079001427, 0.002691771136596799, 0.00747445086017251, -0.028753241524100304, 0.29044967889785767, 0.21596772968769073, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.06169478967785835, -0.04087819159030914, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18353840708732605, 0.05241899937391281, 0.008844357915222645]}
|
||||
{"t": 7.7952, "q": [-0.3112412989139557, -0.013451308012008667, 0.015025706961750984, 0.6276963949203491, -0.3265381157398224, 0.021098555997014046, -0.3186555504798889, 0.030244987457990646, -0.015226585790514946, 0.617469847202301, -0.3366408944129944, -0.020956479012966156, 0.002718554809689522, 0.0074668521992862225, -0.02874831110239029, 0.29042571783065796, 0.2159557342529297, -0.005213138181716204, 0.9791830778121948, 0.15758058428764343, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.8119, "q": [-0.31126686930656433, -0.013451308012008667, 0.015025706961750984, 0.627704918384552, -0.3265504837036133, 0.02107669599354267, -0.31868109107017517, 0.030244987457990646, -0.015226585790514946, 0.617469847202301, -0.3366408944129944, -0.020971018821001053, 0.0027453387156128883, 0.007504821289330721, -0.028733745217323303, 0.2904616594314575, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.295051634311676, -0.22380541265010834, 0.023093601688742638, 0.9780685901641846, -0.1835503876209259, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.8288, "q": [-0.3112839162349701, -0.013451308012008667, 0.015025706961750984, 0.6277134418487549, -0.3265381157398224, 0.021098555997014046, -0.31868109107017517, 0.030244987457990646, -0.015226585790514946, 0.6174613237380981, -0.3366450071334839, -0.020963728427886963, 0.002731946762651205, 0.007444067858159542, -0.02875312976539135, 0.2904616594314575, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.040890175849199295, 0.2950636148452759, -0.22380541265010834, 0.023081617429852486, 0.9780685901641846, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.8456, "q": [-0.31125834584236145, -0.013451308012008667, 0.015012315474450588, 0.627704918384552, -0.3265381157398224, 0.021098555997014046, -0.3187066614627838, 0.030244987457990646, -0.015213193371891975, 0.6174528002738953, -0.33663681149482727, -0.020949246361851692, 0.002731946762651205, 0.007451679557561874, -0.02877766452729702, 0.2904616594314575, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.22380541265010834, 0.02310558594763279, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.8623, "q": [-0.31126686930656433, -0.01346835121512413, 0.015012315474450588, 0.627704918384552, -0.3265463709831238, 0.021098509430885315, -0.31868109107017517, 0.030244987457990646, -0.015213193371891975, 0.617469847202301, -0.3366408944129944, -0.020956479012966156, 0.002731946762651205, 0.007444086950272322, -0.028782539069652557, 0.29044967889785767, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15756858885288239, 0.06167082488536835, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780925512313843, -0.18356238305568695, 0.05240701511502266, 0.008868326433002949]}
|
||||
{"t": 7.879, "q": [-0.31126686930656433, -0.013442784547805786, 0.015012315474450588, 0.627704918384552, -0.3265422582626343, 0.021105796098709106, -0.31868961453437805, 0.030244987457990646, -0.01519980188459158, 0.6174613237380981, -0.3366408944129944, -0.020956479012966156, 0.002731946762651205, 0.007451679557561874, -0.02877766452729702, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 7.8958, "q": [-0.31126686930656433, -0.01346835121512413, 0.015012315474450588, 0.6277219653129578, -0.3265298902988434, 0.02109861932694912, -0.31868961453437805, 0.030253509059548378, -0.015226585790514946, 0.6174954175949097, -0.3366450071334839, -0.020963728427886963, 0.002691771136596799, 0.007428895682096481, -0.02878248319029808, 0.29044967889785767, 0.21594375371932983, -0.005213138181716204, 0.9792070984840393, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.29502764344215393, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008856342174112797]}
|
||||
{"t": 7.9126, "q": [-0.31125834584236145, -0.013451308012008667, 0.015025706961750984, 0.627704918384552, -0.3265298902988434, 0.02111312933266163, -0.3186640739440918, 0.030253509059548378, -0.01519980188459158, 0.617469847202301, -0.3366367816925049, -0.020963769406080246, 0.002691771136596799, 0.007421309128403664, -0.02879716083407402, 0.2904376983642578, 0.21596772968769073, -0.005201153922826052, 0.9792070984840393, 0.15762852132320404, 0.06167082488536835, -0.04087819159030914, 0.2950036823749542, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 7.9293, "q": [-0.31126686930656433, -0.013459829613566399, 0.01503909844905138, 0.6277304887771606, -0.3265340030193329, 0.021105842664837837, -0.31864702701568604, 0.03027055412530899, -0.01519980188459158, 0.6174954175949097, -0.33662447333335876, -0.020985642448067665, 0.002691771136596799, 0.007413704413920641, -0.028782427310943604, 0.2904137372970581, 0.21596772968769073, -0.005213138181716204, 0.9791830778121948, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05240701511502266, 0.008856342174112797]}
|
||||
{"t": 7.946, "q": [-0.31126686930656433, -0.01346835121512413, 0.015065882354974747, 0.6277219653129578, -0.3265381455421448, 0.021113082766532898, -0.3186299800872803, 0.03027055412530899, -0.01519980188459158, 0.6174868941307068, -0.33662036061286926, -0.020992949604988098, 0.002731946762651205, 0.007406105753034353, -0.02877749875187874, 0.2904137372970581, 0.2159797102212906, -0.005201153922826052, 0.9791951179504395, 0.15762852132320404, 0.0616828091442585, -0.040890175849199295, 0.2950036823749542, -0.22380541265010834, 0.023069633170962334, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 7.9627, "q": [-0.31124982237815857, -0.01346835121512413, 0.015065882354974747, 0.6277304887771606, -0.3265463709831238, 0.021098509430885315, -0.3186299800872803, 0.03026203252375126, -0.01519980188459158, 0.6174868941307068, -0.33662858605384827, -0.020992891862988472, 0.0027453387156128883, 0.007413692772388458, -0.0287628211081028, 0.2904376983642578, 0.2159557342529297, -0.005201153922826052, 0.9792070984840393, 0.1576405018568039, 0.0616828091442585, -0.04090216010808945, 0.2950036823749542, -0.22380541265010834, 0.023081617429852486, 0.9780925512313843, -0.18356238305568695, 0.05241899937391281, 0.008868326433002949]}
|
||||
{"t": 7.9795, "q": [-0.31125834584236145, -0.01346835121512413, 0.015079274773597717, 0.6277560591697693, -0.3265340030193329, 0.021105842664837837, -0.3186299800872803, 0.03026203252375126, -0.01519980188459158, 0.617469847202301, -0.33661627769470215, -0.020971177145838737, 0.002758730435743928, 0.007390908896923065, -0.02876763977110386, 0.29040175676345825, 0.2159557342529297, -0.005213138181716204, 0.9792070984840393, 0.1575925648212433, 0.0616828091442585, -0.04090216010808945, 0.295051634311676, -0.2237934172153473, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05243098363280296, 0.008868326433002949]}
|
||||
{"t": 7.9962, "q": [-0.31124982237815857, -0.013476874679327011, 0.015079274773597717, 0.6277645826339722, -0.3265422582626343, 0.021105796098709106, -0.31858736276626587, 0.030253509059548378, -0.015213193371891975, 0.6174954175949097, -0.33662447333335876, -0.020985642448067665, 0.002718554809689522, 0.007398495450615883, -0.02875296212732792, 0.29040175676345825, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15765248239040375, 0.06167082488536835, -0.04090216010808945, 0.29502764344215393, -0.22378143668174744, 0.023093601688742638, 0.9780805706977844, -0.1835743635892868, 0.05240701511502266, 0.008844357915222645]}
|
||||
{"t": 8.0129, "q": [-0.3112327754497528, -0.01346835121512413, 0.015079274773597717, 0.627773106098175, -0.3265340030193329, 0.021105842664837837, -0.3185703158378601, 0.030279075726866722, -0.015226585790514946, 0.6174868941307068, -0.33662039041519165, -0.0209784097969532, 0.002691771136596799, 0.007398495450615883, -0.02875296212732792, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.1576405018568039, 0.0616828091442585, -0.0409381128847599, 0.2950036823749542, -0.22378143668174744, 0.02310558594763279, 0.9780805706977844, -0.18353840708732605, 0.05243098363280296, 0.008856342174112797]}
|
||||
{"t": 8.0299, "q": [-0.3112327754497528, -0.01346835121512413, 0.015106058679521084, 0.6277645826339722, -0.3265340030193329, 0.021105842664837837, -0.318578839302063, 0.03027055412530899, -0.01519980188459158, 0.6174868941307068, -0.33661627769470215, -0.020971177145838737, 0.0026783791836351156, 0.00746682845056057, -0.02870909683406353, 0.2904376983642578, 0.2159557342529297, -0.005213138181716204, 0.9791951179504395, 0.15760454535484314, 0.0616828091442585, -0.04090216010808945, 0.2950156629085541, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.052395034581422806, 0.008844357915222645]}
|
||||
{"t": 8.0469, "q": [-0.3112412989139557, -0.01346835121512413, 0.015079274773597717, 0.6277645826339722, -0.3265381157398224, 0.021098555997014046, -0.31854474544525146, 0.03026203252375126, -0.015253368765115738, 0.617469847202301, -0.33662039041519165, -0.0209784097969532, 0.002691771136596799, 0.00745923537760973, -0.028713971376419067, 0.2903897762298584, 0.21596772968769073, -0.005213138181716204, 0.9791951179504395, 0.15756858885288239, 0.0616828091442585, -0.04090216010808945, 0.29503965377807617, -0.22380541265010834, 0.023093601688742638, 0.9780805706977844, -0.18356238305568695, 0.05241899937391281, 0.008844357915222645]}
|
||||
1103
recorder/g1_record_replay.py
Normal file
1103
recorder/g1_record_replay.py
Normal file
File diff suppressed because it is too large
Load Diff
46
robot.sh
Executable file
46
robot.sh
Executable file
@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# robot.sh — WORKSTATION-side helper: run manage.sh on the G1 robot (PC2) over SSH.
|
||||
# manage.sh itself must run on the robot (that's where the hands live); this just
|
||||
# forwards your command there.
|
||||
#
|
||||
# ./robot.sh # robot status
|
||||
# ./robot.sh status|restart|... # any manage.sh command (see: ./robot.sh help)
|
||||
# ./robot.sh like|handshake # gestures (ARM MOVES on the robot)
|
||||
# ./robot.sh arm "shake hand" # quotes/spaces preserved
|
||||
# ./robot.sh deploy # rsync this repo -> robot, then build.sh
|
||||
#
|
||||
# ./robot.sh -ip 10.255.254.88 status # target a specific address (e.g. the
|
||||
# # wifi IP, which changes via DHCP)
|
||||
#
|
||||
# Env: ROBOT (default unitree@192.168.123.164 — ethernet). -ip overrides it.
|
||||
# Give -ip either "10.255.254.88" (user defaults to unitree) or "user@host".
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
ROBOT="${ROBOT:-unitree@192.168.123.164}"
|
||||
|
||||
# -ip <addr> : target a specific host (e.g. the changing wifi IP) instead of eth0.
|
||||
if [ "${1:-}" = "-ip" ] || [ "${1:-}" = "--ip" ]; then
|
||||
shift
|
||||
[ $# -ge 1 ] || { echo "usage: ./robot.sh -ip <addr> <command...>" >&2; exit 1; }
|
||||
case "$1" in *@*) ROBOT="$1" ;; *) ROBOT="unitree@$1" ;; esac
|
||||
shift
|
||||
fi
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
REMOTE='~/DFX_inspire_service'
|
||||
TT=""; [ -t 0 ] && TT="-t" # allocate a TTY only when we have one (menu/pose/logs)
|
||||
SSH_OPTS="-o ConnectTimeout=8" # fail fast if eth0 is down (use -ip <wifi> instead)
|
||||
|
||||
echo ">> target: $ROBOT" >&2
|
||||
|
||||
if [ "${1:-}" = "deploy" ]; then
|
||||
echo ">> rsync $HERE -> $ROBOT:$REMOTE"
|
||||
rsync -az --exclude='build/' -e "ssh $SSH_OPTS" "$HERE/" "$ROBOT:$REMOTE/"
|
||||
# shellcheck disable=SC2086
|
||||
ssh $SSH_OPTS $TT "$ROBOT" "cd $REMOTE && ./build.sh"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
ssh $SSH_OPTS $TT "$ROBOT" "cd $REMOTE && ./manage.sh $(printf '%q ' "$@")"
|
||||
143
start.sh
Executable file
143
start.sh
Executable file
@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# start.sh — ONE command to bring up the whole hand stack.
|
||||
#
|
||||
# Starts the Docker container that runs all three pieces together — the RS-485
|
||||
# service (inspire_g1), the TCP->DDS bridge (hand_bridge) and the web dashboard
|
||||
# on :8088 — then waits until the dashboard actually answers before telling you
|
||||
# it is up.
|
||||
#
|
||||
# ./start.sh start it (builds the image the first time)
|
||||
# ./start.sh stop stop the container
|
||||
# ./start.sh restart stop + start
|
||||
# ./start.sh status is it up, what is it serving, are the hands alive
|
||||
# ./start.sh logs follow the container log
|
||||
# ./start.sh rebuild force an image rebuild, then start
|
||||
#
|
||||
# RUN IT ON THE ROBOT. Run it on the workstation and it rsyncs this folder to
|
||||
# the robot and runs itself there — the hands, the DDS interface and Docker are
|
||||
# all on the robot, so there is nothing for it to do locally.
|
||||
#
|
||||
# Env: ROBOT=unitree@192.168.123.164 (override for the wifi IP)
|
||||
# PORT=8088
|
||||
# =============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
ROBOT="${ROBOT:-unitree@192.168.123.164}"
|
||||
REMOTE_DIR='~/DFX_inspire_service'
|
||||
PORT="${PORT:-8088}"
|
||||
IMG="${IMG:-inspire-hand:latest}"
|
||||
CMD="${1:-start}"
|
||||
|
||||
say() { printf '\033[36m>>\033[0m %s\n' "$*"; }
|
||||
ok() { printf '\033[32m>>\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[31m>>\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# The robot is the only place this can run: it owns the hands (/dev/ttyUSB*), the
|
||||
# DDS interface to the arm, and Docker. aarch64 is the reliable tell — the
|
||||
# workstation is x86_64 and the image is built for arm64.
|
||||
is_robot() { [ "$(uname -m)" = "aarch64" ] && command -v docker >/dev/null 2>&1; }
|
||||
|
||||
remote() {
|
||||
say "not the robot — deploying to $ROBOT and running there"
|
||||
command -v rsync >/dev/null || die "rsync not installed"
|
||||
# build/ is excluded: the image compiles its own binaries, and the host copy is
|
||||
# 55MB of artifacts that only the (optional) native path uses.
|
||||
rsync -az --delete --exclude='build/' --exclude='docker/.ctx/' \
|
||||
-e "ssh -o ConnectTimeout=8" "$HERE/" "$ROBOT:$REMOTE_DIR/"
|
||||
# shellcheck disable=SC2029
|
||||
ssh -o ConnectTimeout=8 -t "$ROBOT" "cd $REMOTE_DIR && ./start.sh $CMD"
|
||||
exit $?
|
||||
}
|
||||
|
||||
have_image() { docker image inspect "$IMG" >/dev/null 2>&1; }
|
||||
|
||||
# run.sh tails the container log, which spills the dashboard's HTTP lines over this
|
||||
# script's own output. Keep it unless something actually fails.
|
||||
run_quiet() {
|
||||
local log="/tmp/hand_start.$$.log"
|
||||
if ! "$HERE/docker/run.sh" >"$log" 2>&1; then
|
||||
cat "$log"; rm -f "$log"; die "docker run failed"
|
||||
fi
|
||||
rm -f "$log"
|
||||
}
|
||||
|
||||
build() {
|
||||
say "building $IMG (compiles the binaries + python DDS in-image; a few minutes)"
|
||||
"$HERE/docker/build_image.sh"
|
||||
}
|
||||
|
||||
wait_up() {
|
||||
# Poll the dashboard rather than trusting `docker run` — the container can be up
|
||||
# while the service inside is still opening the serial ports, and reporting a URL
|
||||
# that 404s is worse than waiting three more seconds for it.
|
||||
say "waiting for the dashboard..."
|
||||
for _ in $(seq 1 40); do
|
||||
if curl -fsS "http://127.0.0.1:$PORT/api/status" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
report() {
|
||||
local s
|
||||
s="$(curl -fsS "http://127.0.0.1:$PORT/api/status" 2>/dev/null || true)"
|
||||
[ -n "$s" ] || { echo " dashboard not answering on :$PORT"; return 1; }
|
||||
python3 - "$s" <<'PY' 2>/dev/null || echo " $s"
|
||||
import json, sys
|
||||
d = json.loads(sys.argv[1])
|
||||
print(" service=%s bridge=%s iface=%s ports=%s"
|
||||
% (d.get("service"), d.get("bridge"), d.get("iface"), ", ".join(d.get("ports") or []) or "none"))
|
||||
if d.get("mismatch"):
|
||||
print(" WARNING: port drift — the service opened different ttys than are live now")
|
||||
PY
|
||||
local r
|
||||
r="$(curl -fsS "http://127.0.0.1:$PORT/api/rec/status" 2>/dev/null || true)"
|
||||
case "$r" in
|
||||
*'"ready":true'*) echo " recorder: ready (record/replay panel enabled)" ;;
|
||||
*'"ready":false'*) echo " recorder: NOT found — rebuild with ./start.sh rebuild" ;;
|
||||
esac
|
||||
# Skip docker's own bridge addresses (172.17-19.x) — nothing outside the robot can
|
||||
# reach those, and printing them as if they were the dashboard URL wastes a click.
|
||||
for ip in $(hostname -I 2>/dev/null); do
|
||||
case "$ip" in 172.1[789].*|127.*) continue ;; esac
|
||||
echo " http://$ip:$PORT"
|
||||
done
|
||||
}
|
||||
|
||||
is_robot || remote
|
||||
|
||||
case "$CMD" in
|
||||
start|restart)
|
||||
have_image || build
|
||||
run_quiet
|
||||
wait_up || die "dashboard did not come up — ./start.sh logs"
|
||||
ok "up"
|
||||
report
|
||||
;;
|
||||
rebuild)
|
||||
build
|
||||
run_quiet
|
||||
wait_up || die "dashboard did not come up — ./start.sh logs"
|
||||
ok "rebuilt and up"
|
||||
report
|
||||
;;
|
||||
stop)
|
||||
"$HERE/docker/stop.sh"
|
||||
;;
|
||||
status)
|
||||
docker ps --filter name=inspire-hand --format ' {{.Names}} · {{.Status}} · {{.Image}}' | grep . \
|
||||
|| echo " inspire-hand is not running"
|
||||
report || true
|
||||
;;
|
||||
logs)
|
||||
docker logs -f --tail 60 inspire-hand
|
||||
;;
|
||||
*)
|
||||
sed -n '2,26p' "$0" | sed 's/^# \{0,1\}//'
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
12
udev/99-inspire-hands.rules
Normal file
12
udev/99-inspire-hands.rules
Normal file
@ -0,0 +1,12 @@
|
||||
# Grant non-root (0666) access to the Inspire hand USB-RS485 adapters.
|
||||
#
|
||||
# Both adapters are QinHeng CH340 (1a86:7523) and report the SAME USB serial, so
|
||||
# they can't be told apart by ID. We no longer pin per-port symlinks (they broke
|
||||
# whenever the adapters moved to a hub / different USB ports). Instead we grant
|
||||
# 0666 to ANY CH340 tty and let inspire_g1 open /dev/ttyUSB0 + /dev/ttyUSB1
|
||||
# directly (the only ttyUSB on this box are the two hands). Port-independent —
|
||||
# works no matter which USB/hub port they land on.
|
||||
#
|
||||
# If right/left come out swapped, swap serial1/serial2 in inspire_g1.cpp.
|
||||
|
||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE="0666"
|
||||
39
vendor/unitree_sdk2_python/.gitignore
vendored
Normal file
39
vendor/unitree_sdk2_python/.gitignore
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# Generated by MacOS
|
||||
.DS_Store
|
||||
|
||||
# Generated by Windows
|
||||
Thumbs.db
|
||||
|
||||
# Applications
|
||||
*.app
|
||||
*.exe
|
||||
*.war
|
||||
|
||||
# Large media files
|
||||
*.mp4
|
||||
*.tiff
|
||||
*.avi
|
||||
*.flv
|
||||
*.mov
|
||||
*.wmv
|
||||
*.jpg
|
||||
*.png
|
||||
|
||||
# VS Code
|
||||
.vscode
|
||||
|
||||
# other
|
||||
*.egg-info
|
||||
__pycache__
|
||||
|
||||
# IDEs
|
||||
.idea
|
||||
|
||||
# cache
|
||||
.pytest_cache
|
||||
|
||||
# JetBrains IDE
|
||||
.idea/
|
||||
|
||||
# python
|
||||
dist/
|
||||
29
vendor/unitree_sdk2_python/LICENSE
vendored
Normal file
29
vendor/unitree_sdk2_python/LICENSE
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2016-2024 HangZhou YuShu TECHNOLOGY CO.,LTD. ("Unitree Robotics")
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
121
vendor/unitree_sdk2_python/README zh.md
vendored
Normal file
121
vendor/unitree_sdk2_python/README zh.md
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
# unitree_sdk2_python
|
||||
unitree_sdk2 python 接口
|
||||
|
||||
# 安装
|
||||
## 依赖
|
||||
- python>=3.8
|
||||
- cyclonedds==0.10.2
|
||||
- numpy
|
||||
- opencv-python
|
||||
|
||||
## 安装 unitree_sdk2_python
|
||||
在终端中执行:
|
||||
```bash
|
||||
cd ~
|
||||
sudo apt install python3-pip
|
||||
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
|
||||
cd unitree_sdk2_python
|
||||
pip3 install -e .
|
||||
```
|
||||
## FAQ
|
||||
##### 1. `pip3 install -e .` 遇到报错
|
||||
```bash
|
||||
Could not locate cyclonedds. Try to set CYCLONEDDS_HOME or CMAKE_PREFIX_PATH
|
||||
```
|
||||
该错误提示找不到 cyclonedds 路径。首先编译安装cyclonedds:
|
||||
```bash
|
||||
cd ~
|
||||
git clone https://github.com/eclipse-cyclonedds/cyclonedds -b releases/0.10.x
|
||||
cd cyclonedds && mkdir build install && cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=../install
|
||||
cmake --build . --target install
|
||||
```
|
||||
进入 unitree_sdk2_python 目录,设置 `CYCLONEDDS_HOME` 为刚刚编译好的 cyclonedds 所在路径,再安装 unitree_sdk2_python
|
||||
```bash
|
||||
cd ~/unitree_sdk2_python
|
||||
export CYCLONEDDS_HOME="~/cyclonedds/install"
|
||||
pip3 install -e .
|
||||
```
|
||||
|
||||
详细见:
|
||||
https://pypi.org/project/cyclonedds/#installing-with-pre-built-binaries
|
||||
|
||||
# 使用
|
||||
python sdk2 接口与 unitree_skd2的接口保持一致,通过请求响应或订阅发布topic实现机器人的状态获取和控制。相应的例程位于`/example`目录下。在运行例程前,需要根据文档 https://support.unitree.com/home/zh/developer/Quick_start 配置好机器人的网络连接。
|
||||
## DDS通讯
|
||||
在终端中执行:
|
||||
```bash
|
||||
python3 ./example/helloworld/publisher.py
|
||||
```
|
||||
打开新的终端,执行:
|
||||
```bash
|
||||
python3 ./example/helloworld/subscriber.py
|
||||
```
|
||||
可以看到终端输出的数据信息。`publisher.py` 和 `subscriber.py` 传输的数据定义在 `user_data.py` 中,用户可以根据需要自行定义需要传输的数据结构。
|
||||
|
||||
## 高层状态和控制
|
||||
高层接口的数据结构和控制方式与unitree_sdk2一致。具体可见:https://support.unitree.com/home/zh/developer/sports_services
|
||||
### 高层状态
|
||||
终端中执行:
|
||||
```bash
|
||||
python3 ./example/high_level/read_highstate.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。
|
||||
### 高层控制
|
||||
终端中执行:
|
||||
```bash
|
||||
python3 ./example/high_level/sportmode_test.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。
|
||||
该例程提供了几种测试方法,可根据测试需要选择:
|
||||
```python
|
||||
test.StandUpDown() # 站立趴下
|
||||
# test.VelocityMove() # 速度控制
|
||||
# test.BalanceAttitude() # 姿态控制
|
||||
# test.TrajectoryFollow() # 轨迹跟踪
|
||||
# test.SpecialMotions() # 特殊动作
|
||||
|
||||
```
|
||||
## 底层状态和控制
|
||||
底层接口的数据结构和控制方式与unitree_sdk2一致。具体可见:https://support.unitree.com/home/zh/developer/Basic_services
|
||||
### 底层状态
|
||||
终端中执行:
|
||||
```bash
|
||||
python3 ./example/low_level/lowlevel_control.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。程序会输出右前腿hip关节的状态、IMU和电池电压信息。
|
||||
|
||||
### 底层电机控制
|
||||
首先使用 app 关闭高层运动服务(sport_mode),否则会导致指令冲突。
|
||||
终端中执行:
|
||||
```bash
|
||||
python3 ./example/low_level/lowlevel_control.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。左后腿 hip 关节会保持在0角度 (安全起见,这里设置 kp=10, kd=1),左后腿 calf 关节将持续输出 1Nm 的转矩。
|
||||
|
||||
## 遥控器状态获取
|
||||
终端中执行:
|
||||
```bash
|
||||
python3 ./example/wireless_controller/wireless_controller.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。
|
||||
终端将输出每一个按键的状态。对于遥控器按键的定义和数据结构可见: https://support.unitree.com/home/zh/developer/Get_remote_control_status
|
||||
|
||||
## 前置摄像头
|
||||
使用opencv获取前置摄像头(确保在有图形界面的系统下运行, 按 ESC 退出程序):
|
||||
```bash
|
||||
python3 ./example/front_camera/camera_opencv.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。
|
||||
|
||||
## 避障开关
|
||||
```bash
|
||||
python3 ./example/obstacles_avoid_switch/obstacles_avoid_switch.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。机器人将循环开启和关闭避障功能。关于避障服务,详细见 https://support.unitree.com/home/zh/developer/ObstaclesAvoidClient
|
||||
|
||||
## 灯光音量控制
|
||||
```bash
|
||||
python3 ./example/vui_client/vui_client_example.py enp2s0
|
||||
```
|
||||
其中 `enp2s0` 为机器人所连接的网卡名称,请根据实际情况修改。机器人将循环调节音量和灯光亮度。该接口详细见 https://support.unitree.com/home/zh/developer/VuiClient
|
||||
113
vendor/unitree_sdk2_python/README.md
vendored
Normal file
113
vendor/unitree_sdk2_python/README.md
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
# unitree_sdk2_python
|
||||
Python interface for unitree sdk2
|
||||
|
||||
# Installation
|
||||
## Dependencies
|
||||
- Python >= 3.8
|
||||
- cyclonedds == 0.10.2
|
||||
- numpy
|
||||
- opencv-python
|
||||
|
||||
### Installing from source
|
||||
Execute the following commands in the terminal:
|
||||
```bash
|
||||
cd ~
|
||||
sudo apt install python3-pip
|
||||
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
|
||||
cd unitree_sdk2_python
|
||||
pip3 install -e .
|
||||
```
|
||||
## FAQ
|
||||
##### 1. Error when `pip3 install -e .`:
|
||||
```bash
|
||||
Could not locate cyclonedds. Try to set CYCLONEDDS_HOME or CMAKE_PREFIX_PATH
|
||||
```
|
||||
This error mentions that the cyclonedds path could not be found. First compile and install cyclonedds:
|
||||
|
||||
```bash
|
||||
cd ~
|
||||
git clone https://github.com/eclipse-cyclonedds/cyclonedds -b releases/0.10.x
|
||||
cd cyclonedds && mkdir build install && cd build
|
||||
cmake .. -DCMAKE_INSTALL_PREFIX=../install
|
||||
cmake --build . --target install
|
||||
```
|
||||
Enter the unitree_sdk2_python directory, set `CYCLONEDDS_HOME` to the path of the cyclonedds you just compiled, and then install unitree_sdk2_python.
|
||||
```bash
|
||||
cd ~/unitree_sdk2_python
|
||||
export CYCLONEDDS_HOME=~/cyclonedds/install
|
||||
pip3 install -e .
|
||||
```
|
||||
For details, see: https://pypi.org/project/cyclonedds/#installing-with-pre-built-binaries
|
||||
|
||||
# Usage
|
||||
The Python sdk2 interface maintains consistency with the unitree_sdk2 interface, achieving robot status acquisition and control through request-response or topic subscription/publishing. Example programs are located in the `/example` directory. Before running the examples, configure the robot's network connection as per the instructions in the document at https://support.unitree.com/home/en/developer/Quick_start.
|
||||
## DDS Communication
|
||||
In the terminal, execute:
|
||||
```bash
|
||||
python3 ./example/helloworld/publisher.py
|
||||
```
|
||||
Open a new terminal and execute:
|
||||
```bash
|
||||
python3 ./example/helloworld/subscriber.py
|
||||
```
|
||||
You will see the data output in the terminal. The data structure transmitted between `publisher.py` and `subscriber.py` is defined in `user_data.py`, and users can define the required data structure as needed.
|
||||
## High-Level Status and Control
|
||||
The high-level interface maintains consistency with unitree_sdk2 in terms of data structure and control methods. For detailed information, refer to https://support.unitree.com/home/en/developer/sports_services.
|
||||
### High-Level Status
|
||||
Execute the following command in the terminal:
|
||||
```bash
|
||||
python3 ./example/high_level/read_highstate.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected,.
|
||||
### High-Level Control
|
||||
Execute the following command in the terminal:
|
||||
```bash
|
||||
python3 ./example/high_level/sportmode_test.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected. This example program provides several test methods, and you can choose the required tests as follows:
|
||||
```python
|
||||
test.StandUpDown() # Stand up and lie down
|
||||
# test.VelocityMove() # Velocity control
|
||||
# test.BalanceAttitude() # Attitude control
|
||||
# test.TrajectoryFollow() # Trajectory tracking
|
||||
# test.SpecialMotions() # Special motions
|
||||
```
|
||||
## Low-Level Status and Control
|
||||
The low-level interface maintains consistency with unitree_sdk2 in terms of data structure and control methods. For detailed information, refer to https://support.unitree.com/home/en/developer/Basic_services.
|
||||
### Low-Level Status
|
||||
Execute the following command in the terminal:
|
||||
```bash
|
||||
python3 ./example/low_level/lowlevel_control.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected. The program will output the state of the right front leg hip joint, IMU, and battery voltage.
|
||||
### Low-Level Motor Control
|
||||
First, use the app to turn off the high-level motion service (sport_mode) to prevent conflicting instructions.
|
||||
Execute the following command in the terminal:
|
||||
```bash
|
||||
python3 ./example/low_level/lowlevel_control.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected. The left hind leg hip joint will maintain a 0-degree position (for safety, set kp=10, kd=1), and the left hind leg calf joint will continuously output 1Nm of torque.
|
||||
## Wireless Controller Status
|
||||
Execute the following command in the terminal:
|
||||
```bash
|
||||
python3 ./example/wireless_controller/wireless_controller.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected. The terminal will output the status of each key. For the definition and data structure of the remote control keys, refer to https://support.unitree.com/home/en/developer/Get_remote_control_status.
|
||||
## Front Camera
|
||||
Use OpenCV to obtain the front camera (ensure to run on a system with a graphical interface, and press ESC to exit the program):
|
||||
```bash
|
||||
python3 ./example/front_camera/camera_opencv.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected.
|
||||
|
||||
## Obstacle Avoidance Switch
|
||||
```bash
|
||||
python3 ./example/obstacles_avoid_switch/obstacles_avoid_switch.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected. The robot will cycle obstacle avoidance on and off. For details on the obstacle avoidance service, see https://support.unitree.com/home/en/developer/ObstaclesAvoidClient
|
||||
|
||||
## Light and volume control
|
||||
```bash
|
||||
python3 ./example/vui_client/vui_client_example.py enp2s0
|
||||
```
|
||||
Replace `enp2s0` with the name of the network interface to which the robot is connected.T he robot will cycle the volume and light brightness. The interface is detailed at https://support.unitree.com/home/en/developer/VuiClient
|
||||
39
vendor/unitree_sdk2_python/example/a2/audio/a2_audio_client_example.py
vendored
Normal file
39
vendor/unitree_sdk2_python/example/a2/audio/a2_audio_client_example.py
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.a2.audio.audio_client import AudioClient
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
audio_client = AudioClient()
|
||||
audio_client.SetTimeout(10.0)
|
||||
audio_client.Init()
|
||||
|
||||
ret = audio_client.GetVolume()
|
||||
print("debug GetVolume: ", ret)
|
||||
|
||||
audio_client.SetVolume(85)
|
||||
|
||||
ret = audio_client.GetVolume()
|
||||
print("debug GetVolume: ", ret)
|
||||
|
||||
audio_client.TtsMaker("大家好!我是宇树科技的机器人。语音开发测试例程运行成功! 很高兴认识你!", 0)
|
||||
time.sleep(8)
|
||||
audio_client.TtsMaker("接下来测试灯带开发例程!", 0)
|
||||
time.sleep(1)
|
||||
audio_client.LedControl(255, 0, 0)
|
||||
time.sleep(1)
|
||||
audio_client.LedControl(0, 255, 0)
|
||||
time.sleep(1)
|
||||
audio_client.LedControl(0, 0, 255)
|
||||
|
||||
time.sleep(3)
|
||||
audio_client.TtsMaker("测试完毕,谢谢大家!", 0)
|
||||
|
||||
38
vendor/unitree_sdk2_python/example/a2/audio/a2_audio_client_play_wav.py
vendored
Normal file
38
vendor/unitree_sdk2_python/example/a2/audio/a2_audio_client_play_wav.py
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.a2.audio.audio_client import AudioClient
|
||||
from wav import read_wav, play_pcm_stream
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(f"Usage: {sys.argv[0]} <network_interface> <wav_file_path>")
|
||||
sys.exit(1)
|
||||
|
||||
net_interface = sys.argv[1]
|
||||
wav_path = sys.argv[2]
|
||||
|
||||
ChannelFactoryInitialize(0, net_interface)
|
||||
audio_client = AudioClient()
|
||||
audio_client.SetTimeout(10.0)
|
||||
audio_client.Init()
|
||||
|
||||
pcm_list, sample_rate, num_channels, is_ok = read_wav(wav_path)
|
||||
print(f"[DEBUG] Read success: {is_ok}")
|
||||
print(f"[DEBUG] Sample rate: {sample_rate} Hz")
|
||||
print(f"[DEBUG] Channels: {num_channels}")
|
||||
print(f"[DEBUG] PCM byte length: {len(pcm_list)}")
|
||||
|
||||
if not is_ok or sample_rate != 16000 or num_channels != 1:
|
||||
print("[ERROR] Failed to read WAV file or unsupported format (must be 16kHz mono)")
|
||||
return
|
||||
|
||||
play_pcm_stream(audio_client, pcm_list, "example")
|
||||
audio_client.PlayStop("example")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
BIN
vendor/unitree_sdk2_python/example/a2/audio/test.wav
vendored
Normal file
BIN
vendor/unitree_sdk2_python/example/a2/audio/test.wav
vendored
Normal file
Binary file not shown.
166
vendor/unitree_sdk2_python/example/a2/audio/wav.py
vendored
Normal file
166
vendor/unitree_sdk2_python/example/a2/audio/wav.py
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
import struct
|
||||
import time
|
||||
|
||||
def read_wav(filename):
|
||||
try:
|
||||
with open(filename, 'rb') as f:
|
||||
def read(fmt):
|
||||
return struct.unpack(fmt, f.read(struct.calcsize(fmt)))
|
||||
|
||||
# === Chunk Header ===
|
||||
chunk_id, = read('<I')
|
||||
if chunk_id != 0x46464952: # "RIFF"
|
||||
print(f"[ERROR] chunk_id != 'RIFF': {hex(chunk_id)}")
|
||||
return [], -1, -1, False
|
||||
|
||||
_chunk_size, = read('<I')
|
||||
format_tag, = read('<I')
|
||||
if format_tag != 0x45564157: # "WAVE"
|
||||
print(f"[ERROR] format != 'WAVE': {hex(format_tag)}")
|
||||
return [], -1, -1, False
|
||||
|
||||
# === Subchunk1: fmt ===
|
||||
subchunk1_id, = read('<I')
|
||||
subchunk1_size, = read('<I')
|
||||
|
||||
if subchunk1_id == 0x4B4E554A: # JUNK
|
||||
f.seek(subchunk1_size, 1)
|
||||
subchunk1_id, = read('<I')
|
||||
subchunk1_size, = read('<I')
|
||||
|
||||
if subchunk1_id != 0x20746D66: # "fmt "
|
||||
print(f"[ERROR] subchunk1_id != 'fmt ': {hex(subchunk1_id)}")
|
||||
return [], -1, -1, False
|
||||
|
||||
if subchunk1_size not in [16, 18]:
|
||||
print(f"[ERROR] subchunk1_size != 16 or 18: {subchunk1_size}")
|
||||
return [], -1, -1, False
|
||||
|
||||
audio_format, = read('<H')
|
||||
if audio_format != 1:
|
||||
print(f"[ERROR] audio_format != PCM (1): {audio_format}")
|
||||
return [], -1, -1, False
|
||||
|
||||
num_channels, = read('<H')
|
||||
sample_rate, = read('<I')
|
||||
byte_rate, = read('<I')
|
||||
block_align, = read('<H')
|
||||
bits_per_sample, = read('<H')
|
||||
|
||||
expected_byte_rate = sample_rate * num_channels * bits_per_sample // 8
|
||||
if byte_rate != expected_byte_rate:
|
||||
print(f"[ERROR] byte_rate mismatch: got {byte_rate}, expected {expected_byte_rate}")
|
||||
return [], -1, -1, False
|
||||
|
||||
expected_align = num_channels * bits_per_sample // 8
|
||||
if block_align != expected_align:
|
||||
print(f"[ERROR] block_align mismatch: got {block_align}, expected {expected_align}")
|
||||
return [], -1, -1, False
|
||||
|
||||
if bits_per_sample != 16:
|
||||
print(f"[ERROR] Only 16-bit samples supported, got {bits_per_sample}")
|
||||
return [], -1, -1, False
|
||||
|
||||
if subchunk1_size == 18:
|
||||
extra_size, = read('<H')
|
||||
if extra_size != 0:
|
||||
print(f"[ERROR] extra_size != 0: {extra_size}")
|
||||
return [], -1, -1, False
|
||||
|
||||
# === Subchunk2: data ===
|
||||
while True:
|
||||
subchunk2_id, subchunk2_size = read('<II')
|
||||
if subchunk2_id == 0x61746164: # "data"
|
||||
break
|
||||
f.seek(subchunk2_size, 1)
|
||||
|
||||
raw_pcm = f.read(subchunk2_size)
|
||||
if len(raw_pcm) != subchunk2_size:
|
||||
print("[ERROR] Failed to read full PCM data")
|
||||
return [], -1, -1, False
|
||||
|
||||
return list(raw_pcm), sample_rate, num_channels, True
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] read_wave() failed: {e}")
|
||||
return [], -1, -1, False
|
||||
|
||||
|
||||
def write_wave(filename, sample_rate, samples, num_channels=1):
|
||||
try:
|
||||
import array
|
||||
if isinstance(samples[0], int):
|
||||
samples = array.array('h', samples)
|
||||
|
||||
subchunk2_size = len(samples) * 2
|
||||
chunk_size = 36 + subchunk2_size
|
||||
|
||||
with open(filename, 'wb') as f:
|
||||
# RIFF chunk
|
||||
f.write(struct.pack('<I', 0x46464952)) # "RIFF"
|
||||
f.write(struct.pack('<I', chunk_size))
|
||||
f.write(struct.pack('<I', 0x45564157)) # "WAVE"
|
||||
|
||||
# fmt subchunk
|
||||
f.write(struct.pack('<I', 0x20746D66)) # "fmt "
|
||||
f.write(struct.pack('<I', 16)) # PCM
|
||||
f.write(struct.pack('<H', 1)) # PCM format
|
||||
f.write(struct.pack('<H', num_channels))
|
||||
f.write(struct.pack('<I', sample_rate))
|
||||
f.write(struct.pack('<I', sample_rate * num_channels * 2)) # byte_rate
|
||||
f.write(struct.pack('<H', num_channels * 2)) # block_align
|
||||
f.write(struct.pack('<H', 16)) # bits per sample
|
||||
|
||||
# data subchunk
|
||||
f.write(struct.pack('<I', 0x61746164)) # "data"
|
||||
f.write(struct.pack('<I', subchunk2_size))
|
||||
f.write(samples.tobytes())
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] write_wave() failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def play_pcm_stream(client, pcm_list, stream_name="example", chunk_size=96000, sleep_time=1.0, verbose=False):
|
||||
"""
|
||||
Play PCM audio stream (16-bit little-endian format), sending data in chunks.
|
||||
|
||||
Parameters:
|
||||
client: An object with a PlayStream method
|
||||
pcm_list: list[int], PCM audio data in int16 format
|
||||
stream_name: Stream name, default is "example"
|
||||
chunk_size: Number of bytes to send per chunk, default is 96000 (3 seconds at 16kHz)
|
||||
sleep_time: Delay between chunks in seconds
|
||||
"""
|
||||
pcm_data = bytes(pcm_list)
|
||||
stream_id = str(int(time.time() * 1000)) # Unique stream ID based on current timestamp
|
||||
offset = 0
|
||||
chunk_index = 0
|
||||
total_size = len(pcm_data)
|
||||
|
||||
while offset < total_size:
|
||||
remaining = total_size - offset
|
||||
current_chunk_size = min(chunk_size, remaining)
|
||||
chunk = pcm_data[offset:offset + current_chunk_size]
|
||||
|
||||
if verbose:
|
||||
# Print info about the current chunk
|
||||
print(f"[CHUNK {chunk_index}] offset = {offset}, size = {current_chunk_size} bytes")
|
||||
print(" First 10 samples (int16): ", end="")
|
||||
for i in range(0, min(20, len(chunk) - 1), 2):
|
||||
sample = struct.unpack_from('<h', chunk, i)[0]
|
||||
print(sample, end=" ")
|
||||
print()
|
||||
|
||||
# Send the chunk
|
||||
ret_code, _ = client.PlayStream(stream_name, stream_id, chunk)
|
||||
if ret_code != 0:
|
||||
print(f"[ERROR] Failed to send chunk {chunk_index}, return code: {ret_code}")
|
||||
break
|
||||
else:
|
||||
print(f"[INFO] Chunk {chunk_index} sent successfully")
|
||||
|
||||
offset += current_chunk_size
|
||||
chunk_index += 1
|
||||
time.sleep(sleep_time)
|
||||
152
vendor/unitree_sdk2_python/example/a2/sport/a2_sport_client.py
vendored
Normal file
152
vendor/unitree_sdk2_python/example/a2/sport/a2_sport_client.py
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
import sys
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.a2.sport.sport_client import SportClient
|
||||
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="balance_stand", id=1),
|
||||
TestOption(name="stop_move", id=2),
|
||||
TestOption(name="stand_down", id=3),
|
||||
TestOption(name="recovery_stand", id=4),
|
||||
TestOption(name="move", id=5),
|
||||
TestOption(name="switch_gait", id=6),
|
||||
TestOption(name="speed_level", id=7),
|
||||
TestOption(name="get_state", id=8),
|
||||
TestOption(name="recovery_switch", id=9),
|
||||
TestOption(name="body_height", id=10),
|
||||
TestOption(name="stand_up", id=11),
|
||||
TestOption(name="enter_leftside_gait", id=12),
|
||||
TestOption(name="exit_leftside_gait", id=13),
|
||||
TestOption(name="enter_handstand", id=14),
|
||||
TestOption(name="exit_handstand", id=15),
|
||||
TestOption(name="front_flip", id=16),
|
||||
TestOption(name="back_flip", id=17),
|
||||
TestOption(name="pose", id=18),
|
||||
TestOption(name="euler", id=19),
|
||||
]
|
||||
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_: Optional[TestOption] = None
|
||||
|
||||
def convert_to_int(self, input_str: str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input().strip()
|
||||
|
||||
if input_str == "list":
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
test_option = TestOption(name="balance_stand", id=1)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = SportClient()
|
||||
sport_client.SetTimeout(25.0)
|
||||
sport_client.Init()
|
||||
|
||||
print('Input "list " to list all test option ...')
|
||||
res_count = 0
|
||||
dt = 0.02 # 50Hz
|
||||
next_tick = time.monotonic()
|
||||
while True:
|
||||
next_tick += dt
|
||||
|
||||
user_interface.terminal_handle()
|
||||
|
||||
res = 1
|
||||
if test_option.id < 0:
|
||||
# only for list/invalid input
|
||||
time.sleep(0.02)
|
||||
continue
|
||||
if test_option.id == 0:
|
||||
res = sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
res = sport_client.BalanceStand()
|
||||
elif test_option.id == 2:
|
||||
res = sport_client.StopMove()
|
||||
elif test_option.id == 3:
|
||||
res = sport_client.StandDown()
|
||||
elif test_option.id == 4:
|
||||
res = sport_client.RecoveryStand()
|
||||
elif test_option.id == 5:
|
||||
res = sport_client.Move(0.0, 0.0, 0.5)
|
||||
elif test_option.id == 6:
|
||||
res = sport_client.SwitchGait(0)
|
||||
elif test_option.id == 7:
|
||||
res = sport_client.SpeedLevel(1)
|
||||
elif test_option.id == 8:
|
||||
state_map = {}
|
||||
res = sport_client.GetState(state_map)
|
||||
print(f"fsm_id: {state_map['fsm_id']}")
|
||||
print(f"fsm_name: {state_map['fsm_name']}")
|
||||
print(f"speed_level: {state_map['speed_level']}")
|
||||
print(f"auto_recovery_switch: {state_map['auto_recovery_switch']}")
|
||||
print(f"process_state: {state_map['process_state']}")
|
||||
elif test_option.id == 9:
|
||||
res = sport_client.SetAutoRecovery(0)
|
||||
elif test_option.id == 10:
|
||||
res = sport_client.BodyHeight(0.3)
|
||||
elif test_option.id == 11:
|
||||
res = sport_client.StandUp()
|
||||
elif test_option.id == 12:
|
||||
res = sport_client.LeftSideGait(1)
|
||||
elif test_option.id == 13:
|
||||
res = sport_client.LeftSideGait(0)
|
||||
elif test_option.id == 14:
|
||||
res = sport_client.HandStand(1)
|
||||
elif test_option.id == 15:
|
||||
res = sport_client.HandStand(0)
|
||||
elif test_option.id == 16:
|
||||
res = sport_client.FrontFlip()
|
||||
elif test_option.id == 17:
|
||||
res = sport_client.BackFlip()
|
||||
elif test_option.id == 18:
|
||||
res = sport_client.BodyPosition(0.2, 0.2, -0.2, 0.2)
|
||||
elif test_option.id == 19:
|
||||
res = sport_client.Euler(0.2, 0.3, 0.3)
|
||||
|
||||
if res < 0:
|
||||
res_count += 1
|
||||
print(f"Request error for: {option_list[test_option.id].name}, code: {res}, count: {res_count}")
|
||||
else:
|
||||
res_count = 0
|
||||
print(f"Request successed: {option_list[test_option.id].name}, code: {res}")
|
||||
|
||||
time.sleep(max(0.0, next_tick - time.monotonic()))
|
||||
|
||||
53
vendor/unitree_sdk2_python/example/a2/sport/a2_sport_state.py
vendored
Normal file
53
vendor/unitree_sdk2_python/example/a2/sport/a2_sport_state.py
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize, ChannelSubscriber
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_
|
||||
|
||||
|
||||
TOPIC_HIGHSTATE = "rt/lf/sportmodestate"
|
||||
|
||||
FSM_STATE_STR = [
|
||||
"PASSIVE",
|
||||
"STAND_DOWN",
|
||||
"STAND_UP",
|
||||
"DEFAULT_MODE",
|
||||
"RUNNING_MODE",
|
||||
"CLIMB_MODE",
|
||||
"LEFT_SIDE_GAIT",
|
||||
"RIGHT_SIDE_GAIT",
|
||||
"HANDSTAND",
|
||||
"BIPED_STAND",
|
||||
"FRONT_FLIP",
|
||||
"BACK_FLIP",
|
||||
"RECOVERY",
|
||||
"BASE_HEIGHT_CTRL",
|
||||
]
|
||||
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.state = None
|
||||
|
||||
self.suber = ChannelSubscriber(TOPIC_HIGHSTATE, SportModeState_)
|
||||
self.suber.Init(self.HighStateHandler, 10)
|
||||
|
||||
def HighStateHandler(self, msg: SportModeState_):
|
||||
self.state = msg
|
||||
print(f"Position: {self.state.position[0]}, {self.state.position[1]}, {self.state.position[2]}")
|
||||
print(f"Velocity: {self.state.velocity[0]}, {self.state.velocity[1]}, {self.state.velocity[2]}")
|
||||
print(f"Mode: {FSM_STATE_STR[int(self.state.mode)]}")
|
||||
print(f"Progress: {self.state.progress}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
custom = Custom()
|
||||
|
||||
while True:
|
||||
time.sleep(10)
|
||||
|
||||
51
vendor/unitree_sdk2_python/example/b2/camera/camera_opencv.py
vendored
Normal file
51
vendor/unitree_sdk2_python/example/b2/camera/camera_opencv.py
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.b2.front_video.front_video_client import FrontVideoClient
|
||||
from unitree_sdk2py.b2.back_video.back_video_client import BackVideoClient
|
||||
import cv2
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
def display_image(window_name, data):
|
||||
# If data is a list, we need to convert it to a bytes object
|
||||
if isinstance(data, list):
|
||||
data = bytes(data)
|
||||
|
||||
# Now convert to numpy image
|
||||
image_data = np.frombuffer(data, dtype=np.uint8)
|
||||
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
|
||||
if image is not None:
|
||||
cv2.imshow(window_name, image)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
frontCameraClient = FrontVideoClient() # Create a front camera video client
|
||||
frontCameraClient.SetTimeout(3.0)
|
||||
frontCameraClient.Init()
|
||||
|
||||
backCameraClient = BackVideoClient() # Create a back camera video client
|
||||
backCameraClient.SetTimeout(3.0)
|
||||
backCameraClient.Init()
|
||||
|
||||
# Loop to continuously fetch images
|
||||
while True:
|
||||
# Get front camera image
|
||||
front_code, front_data = frontCameraClient.GetImageSample()
|
||||
if front_code == 0:
|
||||
display_image("Front Camera", front_data)
|
||||
|
||||
# Get back camera image
|
||||
back_code, back_data = backCameraClient.GetImageSample()
|
||||
if back_code == 0:
|
||||
display_image("Back Camera", back_data)
|
||||
|
||||
# Press ESC to stop
|
||||
if cv2.waitKey(20) == 27:
|
||||
break
|
||||
|
||||
# Clean up windows
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
51
vendor/unitree_sdk2_python/example/b2/camera/capture_image.py
vendored
Normal file
51
vendor/unitree_sdk2_python/example/b2/camera/capture_image.py
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.b2.front_video.front_video_client import FrontVideoClient
|
||||
from unitree_sdk2py.b2.back_video.back_video_client import BackVideoClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
# 创建前置相机客户端
|
||||
front_client = FrontVideoClient()
|
||||
front_client.SetTimeout(3.0)
|
||||
front_client.Init()
|
||||
|
||||
# 创建后置相机客户端
|
||||
back_client = BackVideoClient()
|
||||
back_client.SetTimeout(3.0)
|
||||
back_client.Init()
|
||||
|
||||
print("##################Get Front Camera Image###################")
|
||||
# 获取前置相机图像
|
||||
front_code, front_data = front_client.GetImageSample()
|
||||
|
||||
if front_code != 0:
|
||||
print("Get front camera image error. Code:", front_code)
|
||||
else:
|
||||
front_image_name = "./front_img.jpg"
|
||||
print("Front Image Saved as:", front_image_name)
|
||||
|
||||
with open(front_image_name, "+wb") as f:
|
||||
f.write(bytes(front_data))
|
||||
|
||||
print("##################Get Back Camera Image###################")
|
||||
# 获取后置相机图像
|
||||
back_code, back_data = back_client.GetImageSample()
|
||||
|
||||
if back_code != 0:
|
||||
print("Get back camera image error. Code:", back_code)
|
||||
else:
|
||||
back_image_name = "./back_img.jpg"
|
||||
print("Back Image Saved as:", back_image_name)
|
||||
|
||||
with open(back_image_name, "+wb") as f:
|
||||
f.write(bytes(back_data))
|
||||
|
||||
time.sleep(1)
|
||||
106
vendor/unitree_sdk2_python/example/b2/high_level/b2_sport_client.py
vendored
Normal file
106
vendor/unitree_sdk2_python/example/b2/high_level/b2_sport_client.py
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.b2.sport.sport_client import SportClient
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="Damp", id=0),
|
||||
TestOption(name="BalanceStand", id=1),
|
||||
TestOption(name="StopMove", id=2),
|
||||
TestOption(name="StandUp", id=3),
|
||||
TestOption(name="StandDown", id=4),
|
||||
TestOption(name="RecoveryStand", id=5),
|
||||
TestOption(name="Move", id=6),
|
||||
TestOption(name="FreeWalk", id=7),
|
||||
TestOption(name="ClassicWalk", id=8)
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.\n"
|
||||
"NOTE: Some interfaces are not demonstrated in this example for safety reasons. "
|
||||
"If you need to use them, please contact technical support: https://serviceconsole.unitree.com/index.html#/")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = SportClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
print("Input \"list\" to list all test option ...")
|
||||
|
||||
while True:
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}")
|
||||
|
||||
if test_option.id == 0:
|
||||
print(f"ret:{sport_client.Damp()}")
|
||||
elif test_option.id == 1:
|
||||
print(f"ret:{sport_client.BalanceStand()}")
|
||||
elif test_option.id == 2:
|
||||
print(f"ret:{sport_client.StopMove()}")
|
||||
elif test_option.id == 3:
|
||||
print(f"ret:{sport_client.StandUp()}")
|
||||
elif test_option.id == 4:
|
||||
print(f"ret:{sport_client.StandDown()}")
|
||||
elif test_option.id == 5:
|
||||
print(f"ret:{sport_client.RecoveryStand()}")
|
||||
elif test_option.id == 6:
|
||||
print(f"ret:{sport_client.Move(0.5,0.0,0.0)}")
|
||||
elif test_option.id == 7:
|
||||
print(f"ret:{sport_client.FreeWalk()}")
|
||||
elif test_option.id == 8:
|
||||
print(f"ret:{sport_client.ClassicWalk(True)}")
|
||||
print(f"ret:{sport_client.Move(0.1,0.0,0.0)}")
|
||||
time.sleep(2)
|
||||
print(f"ret:{sport_client.ClassicWalk(False)}")
|
||||
print(f"ret:{sport_client.Move(-0.3,0.0,0.0)}")
|
||||
time.sleep(2)
|
||||
|
||||
time.sleep(1)
|
||||
175
vendor/unitree_sdk2_python/example/b2/low_level/b2_stand_example.py
vendored
Normal file
175
vendor/unitree_sdk2_python/example/b2/low_level/b2_stand_example.py
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
import unitree_legged_const as b2
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
from unitree_sdk2py.b2.sport.sport_client import SportClient
|
||||
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.Kp = 1000.0
|
||||
self.Kd = 10.0
|
||||
self.time_consume = 0
|
||||
self.rate_count = 0
|
||||
self.sin_count = 0
|
||||
self.motiontime = 0
|
||||
self.dt = 0.002
|
||||
|
||||
self.low_cmd = unitree_go_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
|
||||
self.targetPos_1 = [0.0, 1.36, -2.65, 0.0, 1.36, -2.65,
|
||||
-0.2, 1.36, -2.65, 0.2, 1.36, -2.65]
|
||||
|
||||
self.targetPos_2 = [0.0, 0.67, -1.3, 0.0, 0.67, -1.3,
|
||||
0.0, 0.67, -1.3, 0.0, 0.67, -1.3]
|
||||
|
||||
self.targetPos_3 = [-0.5, 1.36, -2.65, 0.5, 1.36, -2.65,
|
||||
-0.5, 1.36, -2.65, 0.5, 1.36, -2.65]
|
||||
|
||||
self.startPos = [0.0] * 12
|
||||
self.duration_1 = 500
|
||||
self.duration_2 = 900
|
||||
self.duration_3 = 1000
|
||||
self.duration_4 = 900
|
||||
self.percent_1 = 0
|
||||
self.percent_2 = 0
|
||||
self.percent_3 = 0
|
||||
self.percent_4 = 0
|
||||
|
||||
self.firstRun = True
|
||||
self.done = False
|
||||
|
||||
# thread handling
|
||||
self.lowCmdWriteThreadPtr = None
|
||||
|
||||
self.crc = CRC()
|
||||
|
||||
def Init(self):
|
||||
self.InitLowCmd()
|
||||
|
||||
# create publisher #
|
||||
self.lowcmd_publisher = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateMessageHandler, 10)
|
||||
|
||||
self.sc = SportClient()
|
||||
self.sc.SetTimeout(5.0)
|
||||
self.sc.Init()
|
||||
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.sc.StandDown()
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=0.002, target=self.LowCmdWrite, name="writebasiccmd"
|
||||
)
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def InitLowCmd(self):
|
||||
self.low_cmd.head[0] = 0xFE
|
||||
self.low_cmd.head[1] = 0xEF
|
||||
self.low_cmd.level_flag = 0xFF
|
||||
self.low_cmd.gpio = 0
|
||||
for i in range(20):
|
||||
self.low_cmd.motor_cmd[i].mode = 0x01
|
||||
self.low_cmd.motor_cmd[i].q= b2.PosStopF
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = b2.VelStopF
|
||||
self.low_cmd.motor_cmd[i].kd = 0
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
def LowStateMessageHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
def LowCmdWrite(self):
|
||||
|
||||
if self.firstRun:
|
||||
for i in range(12):
|
||||
self.startPos[i] = self.low_state.motor_state[i].q
|
||||
self.firstRun = False
|
||||
|
||||
self.percent_1 += 1.0 / self.duration_1
|
||||
self.percent_1 = min(self.percent_1, 1)
|
||||
if self.percent_1 < 1:
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_1) * self.startPos[i] + self.percent_1 * self.targetPos_1[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 <= 1):
|
||||
self.percent_2 += 1.0 / self.duration_2
|
||||
self.percent_2 = min(self.percent_2, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_2) * self.targetPos_1[i] + self.percent_2 * self.targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 < 1):
|
||||
self.percent_3 += 1.0 / self.duration_3
|
||||
self.percent_3 = min(self.percent_3, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = self.targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 == 1) and (self.percent_4 <= 1):
|
||||
self.percent_4 += 1.0 / self.duration_4
|
||||
self.percent_4 = min(self.percent_4, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_4) * self.targetPos_2[i] + self.percent_4 * self.targetPos_3[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
if custom.percent_4 == 1.0:
|
||||
time.sleep(1)
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
time.sleep(1)
|
||||
20
vendor/unitree_sdk2_python/example/b2/low_level/unitree_legged_const.py
vendored
Normal file
20
vendor/unitree_sdk2_python/example/b2/low_level/unitree_legged_const.py
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
LegID = {
|
||||
"FR_0": 0, # Front right hip
|
||||
"FR_1": 1, # Front right thigh
|
||||
"FR_2": 2, # Front right calf
|
||||
"FL_0": 3,
|
||||
"FL_1": 4,
|
||||
"FL_2": 5,
|
||||
"RR_0": 6,
|
||||
"RR_1": 7,
|
||||
"RR_2": 8,
|
||||
"RL_0": 9,
|
||||
"RL_1": 10,
|
||||
"RL_2": 11,
|
||||
}
|
||||
|
||||
HIGHLEVEL = 0xEE
|
||||
LOWLEVEL = 0xFF
|
||||
TRIGERLEVEL = 0xF0
|
||||
PosStopF = 2.146e9
|
||||
VelStopF = 16000.0
|
||||
51
vendor/unitree_sdk2_python/example/b2w/camera/camera_opencv.py
vendored
Normal file
51
vendor/unitree_sdk2_python/example/b2w/camera/camera_opencv.py
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.b2.front_video.front_video_client import FrontVideoClient
|
||||
from unitree_sdk2py.b2.back_video.back_video_client import BackVideoClient
|
||||
import cv2
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
def display_image(window_name, data):
|
||||
# If data is a list, we need to convert it to a bytes object
|
||||
if isinstance(data, list):
|
||||
data = bytes(data)
|
||||
|
||||
# Now convert to numpy image
|
||||
image_data = np.frombuffer(data, dtype=np.uint8)
|
||||
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
|
||||
if image is not None:
|
||||
cv2.imshow(window_name, image)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
frontCameraClient = FrontVideoClient() # Create a front camera video client
|
||||
frontCameraClient.SetTimeout(3.0)
|
||||
frontCameraClient.Init()
|
||||
|
||||
backCameraClient = BackVideoClient() # Create a back camera video client
|
||||
backCameraClient.SetTimeout(3.0)
|
||||
backCameraClient.Init()
|
||||
|
||||
# Loop to continuously fetch images
|
||||
while True:
|
||||
# Get front camera image
|
||||
front_code, front_data = frontCameraClient.GetImageSample()
|
||||
if front_code == 0:
|
||||
display_image("Front Camera", front_data)
|
||||
|
||||
# Get back camera image
|
||||
back_code, back_data = backCameraClient.GetImageSample()
|
||||
if back_code == 0:
|
||||
display_image("Back Camera", back_data)
|
||||
|
||||
# Press ESC to stop
|
||||
if cv2.waitKey(20) == 27:
|
||||
break
|
||||
|
||||
# Clean up windows
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
51
vendor/unitree_sdk2_python/example/b2w/camera/capture_image.py
vendored
Normal file
51
vendor/unitree_sdk2_python/example/b2w/camera/capture_image.py
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.b2.front_video.front_video_client import FrontVideoClient
|
||||
from unitree_sdk2py.b2.back_video.back_video_client import BackVideoClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
# 创建前置相机客户端
|
||||
front_client = FrontVideoClient()
|
||||
front_client.SetTimeout(3.0)
|
||||
front_client.Init()
|
||||
|
||||
# 创建后置相机客户端
|
||||
back_client = BackVideoClient()
|
||||
back_client.SetTimeout(3.0)
|
||||
back_client.Init()
|
||||
|
||||
print("##################Get Front Camera Image###################")
|
||||
# 获取前置相机图像
|
||||
front_code, front_data = front_client.GetImageSample()
|
||||
|
||||
if front_code != 0:
|
||||
print("Get front camera image error. Code:", front_code)
|
||||
else:
|
||||
front_image_name = "./front_img.jpg"
|
||||
print("Front Image Saved as:", front_image_name)
|
||||
|
||||
with open(front_image_name, "+wb") as f:
|
||||
f.write(bytes(front_data))
|
||||
|
||||
print("##################Get Back Camera Image###################")
|
||||
# 获取后置相机图像
|
||||
back_code, back_data = back_client.GetImageSample()
|
||||
|
||||
if back_code != 0:
|
||||
print("Get back camera image error. Code:", back_code)
|
||||
else:
|
||||
back_image_name = "./back_img.jpg"
|
||||
print("Back Image Saved as:", back_image_name)
|
||||
|
||||
with open(back_image_name, "+wb") as f:
|
||||
f.write(bytes(back_data))
|
||||
|
||||
time.sleep(1)
|
||||
101
vendor/unitree_sdk2_python/example/b2w/high_level/b2w_sport_client.py
vendored
Normal file
101
vendor/unitree_sdk2_python/example/b2w/high_level/b2w_sport_client.py
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.b2.sport.sport_client import SportClient
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="stand_up", id=1),
|
||||
TestOption(name="stand_down", id=2),
|
||||
TestOption(name="move forward", id=3),
|
||||
TestOption(name="move lateral", id=4),
|
||||
TestOption(name="move rotate", id=5),
|
||||
TestOption(name="stop_move", id=6),
|
||||
TestOption(name="switch_gait", id=7),
|
||||
TestOption(name="switch_gait", id=8),
|
||||
TestOption(name="recovery", id=9)
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"name: {option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = SportClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
print("Input \"list\" to list all test option ...")
|
||||
|
||||
while True:
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}\n")
|
||||
|
||||
if test_option.id == 0:
|
||||
sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
sport_client.StandUp()
|
||||
elif test_option.id == 2:
|
||||
sport_client.StandDown()
|
||||
elif test_option.id == 3:
|
||||
sport_client.Move(0.3,0,0)
|
||||
elif test_option.id == 4:
|
||||
sport_client.Move(0,0.3,0)
|
||||
elif test_option.id == 5:
|
||||
sport_client.Move(0,0,0.5)
|
||||
elif test_option.id == 6:
|
||||
sport_client.StopMove()
|
||||
elif test_option.id == 7:
|
||||
sport_client.SwitchGait(0)
|
||||
elif test_option.id == 8:
|
||||
sport_client.SwitchGait(1)
|
||||
elif test_option.id == 9:
|
||||
sport_client.RecoveryStand()
|
||||
|
||||
time.sleep(1)
|
||||
196
vendor/unitree_sdk2_python/example/b2w/low_level/b2w_stand_example.py
vendored
Normal file
196
vendor/unitree_sdk2_python/example/b2w/low_level/b2w_stand_example.py
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
import unitree_legged_const as b2w
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
from unitree_sdk2py.b2.sport.sport_client import SportClient
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.Kp = 1000.0
|
||||
self.Kd = 10.0
|
||||
self.time_consume = 0
|
||||
self.rate_count = 0
|
||||
self.sin_count = 0
|
||||
self.motiontime = 0
|
||||
self.dt = 0.002
|
||||
|
||||
self.low_cmd = unitree_go_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
|
||||
self.targetPos_1 = [0.0, 1.36, -2.65, 0.0, 1.36, -2.65,
|
||||
-0.2, 1.36, -2.65, 0.2, 1.36, -2.65]
|
||||
|
||||
self.targetPos_2 = [0.0, 0.67, -1.3, 0.0, 0.67, -1.3,
|
||||
0.0, 0.67, -1.3, 0.0, 0.67, -1.3]
|
||||
|
||||
self.targetPos_3 = [-0.65, 1.36, -2.65, 0.65, 1.36, -2.65,
|
||||
-0.65, 1.36, -2.65, 0.65, 1.36, -2.65]
|
||||
|
||||
self.startPos = [0.0] * 12
|
||||
self.duration_1 = 800
|
||||
self.duration_2 = 800
|
||||
self.duration_3 = 2000
|
||||
self.duration_4 = 1500
|
||||
self.percent_1 = 0
|
||||
self.percent_2 = 0
|
||||
self.percent_3 = 0
|
||||
self.percent_4 = 0
|
||||
|
||||
self.firstRun = True
|
||||
self.done = False
|
||||
|
||||
# thread handling
|
||||
self.lowCmdWriteThreadPtr = None
|
||||
|
||||
self.crc = CRC()
|
||||
|
||||
def Init(self):
|
||||
self.InitLowCmd()
|
||||
|
||||
# create publisher #
|
||||
self.lowcmd_publisher = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateMessageHandler, 10)
|
||||
|
||||
self.sc = SportClient()
|
||||
self.sc.SetTimeout(5.0)
|
||||
self.sc.Init()
|
||||
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.sc.StandDown()
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
name="writebasiccmd", interval=self.dt, target=self.LowCmdWrite,
|
||||
)
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def InitLowCmd(self):
|
||||
self.low_cmd.head[0] = 0xFE
|
||||
self.low_cmd.head[1] = 0xEF
|
||||
self.low_cmd.level_flag = 0xFF
|
||||
self.low_cmd.gpio = 0
|
||||
for i in range(20):
|
||||
self.low_cmd.motor_cmd[i].mode = 0x01 # (PMSM) mode
|
||||
self.low_cmd.motor_cmd[i].q = b2w.PosStopF
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = b2w.VelStopF
|
||||
self.low_cmd.motor_cmd[i].kd = 0
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
def LowStateMessageHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
def LowCmdWrite(self):
|
||||
if self.firstRun:
|
||||
for i in range(12):
|
||||
self.startPos[i] = self.low_state.motor_state[i].q
|
||||
self.firstRun = False
|
||||
|
||||
self.percent_1 += 1.0 / self.duration_1
|
||||
self.percent_1 = min(self.percent_1, 1)
|
||||
if self.percent_1 < 1:
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_1) * self.startPos[i] + self.percent_1 * self.targetPos_1[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 <= 1):
|
||||
self.percent_2 += 1.0 / self.duration_2
|
||||
self.percent_2 = min(self.percent_2, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_2) * self.targetPos_1[i] + self.percent_2 * self.targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 < 1):
|
||||
self.percent_3 += 1.0 / self.duration_3
|
||||
self.percent_3 = min(self.percent_3, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = self.targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if self.percent_3 < 0.4:
|
||||
for i in range(12, 16):
|
||||
self.low_cmd.motor_cmd[i].q = 0
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = 3
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if 0.4 <= self.percent_3 < 0.8:
|
||||
for i in range(12, 16):
|
||||
self.low_cmd.motor_cmd[i].q = 0
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = -3
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if self.percent_3 >= 0.8:
|
||||
for i in range(12, 16):
|
||||
self.low_cmd.motor_cmd[i].q = 0
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 == 1) and (self.percent_4 <= 1):
|
||||
self.percent_4 += 1.0 / self.duration_4
|
||||
self.percent_4 = min(self.percent_4, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_4) * self.targetPos_2[i] + self.percent_4 * self.targetPos_3[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
if custom.percent_4 == 1.0:
|
||||
time.sleep(1)
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
time.sleep(1)
|
||||
24
vendor/unitree_sdk2_python/example/b2w/low_level/unitree_legged_const.py
vendored
Normal file
24
vendor/unitree_sdk2_python/example/b2w/low_level/unitree_legged_const.py
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
LegID = {
|
||||
"FR_0": 0, # Front right hip
|
||||
"FR_1": 1, # Front right thigh
|
||||
"FR_2": 2, # Front right calf
|
||||
"FL_0": 3,
|
||||
"FL_1": 4,
|
||||
"FL_2": 5,
|
||||
"RR_0": 6,
|
||||
"RR_1": 7,
|
||||
"RR_2": 8,
|
||||
"RL_0": 9,
|
||||
"RL_1": 10,
|
||||
"RL_2": 11,
|
||||
"FR_w": 12, # Front right wheel
|
||||
"FL_w": 13, # Front left wheel
|
||||
"RR_w": 14, # Rear right wheel
|
||||
"RL_w": 15, # Rear left wheel
|
||||
}
|
||||
|
||||
HIGHLEVEL = 0xEE
|
||||
LOWLEVEL = 0xFF
|
||||
TRIGERLEVEL = 0xF0
|
||||
PosStopF = 2.146e9
|
||||
VelStopF = 16000.0
|
||||
44
vendor/unitree_sdk2_python/example/g1/audio/g1_audio_client_example.py
vendored
Normal file
44
vendor/unitree_sdk2_python/example/g1/audio/g1_audio_client_example.py
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.g1.audio.g1_audio_client import AudioClient
|
||||
from unitree_sdk2py.g1.loco.g1_loco_client import LocoClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
audio_client = AudioClient()
|
||||
audio_client.SetTimeout(10.0)
|
||||
audio_client.Init()
|
||||
|
||||
sport_client = LocoClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
ret = audio_client.GetVolume()
|
||||
print("debug GetVolume: ",ret)
|
||||
|
||||
audio_client.SetVolume(85)
|
||||
|
||||
ret = audio_client.GetVolume()
|
||||
print("debug GetVolume: ",ret)
|
||||
|
||||
sport_client.WaveHand()
|
||||
|
||||
audio_client.TtsMaker("大家好!我是宇树科技人形机器人。语音开发测试例程运行成功! 很高兴认识你!",0)
|
||||
time.sleep(8)
|
||||
audio_client.TtsMaker("接下来测试灯带开发例程!",0)
|
||||
time.sleep(1)
|
||||
audio_client.LedControl(255,0,0)
|
||||
time.sleep(1)
|
||||
audio_client.LedControl(0,255,0)
|
||||
time.sleep(1)
|
||||
audio_client.LedControl(0,0,255)
|
||||
|
||||
time.sleep(3)
|
||||
audio_client.TtsMaker("测试完毕,谢谢大家!",0)
|
||||
|
||||
35
vendor/unitree_sdk2_python/example/g1/audio/g1_audio_client_play_wav.py
vendored
Normal file
35
vendor/unitree_sdk2_python/example/g1/audio/g1_audio_client_play_wav.py
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.g1.audio.g1_audio_client import AudioClient
|
||||
from wav import read_wav, play_pcm_stream
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print(f"Usage: python3 {sys.argv[0]} <network_interface> <wav_file_path>")
|
||||
sys.exit(1)
|
||||
|
||||
net_interface = sys.argv[1]
|
||||
wav_path = sys.argv[2]
|
||||
|
||||
ChannelFactoryInitialize(0, net_interface)
|
||||
audioClient = AudioClient()
|
||||
audioClient.SetTimeout(10.0)
|
||||
audioClient.Init()
|
||||
|
||||
pcm_list, sample_rate, num_channels, is_ok = read_wav(wav_path)
|
||||
print(f"[DEBUG] Read success: {is_ok}")
|
||||
print(f"[DEBUG] Sample rate: {sample_rate} Hz")
|
||||
print(f"[DEBUG] Channels: {num_channels}")
|
||||
print(f"[DEBUG] PCM byte length: {len(pcm_list)}")
|
||||
|
||||
if not is_ok or sample_rate != 16000 or num_channels != 1:
|
||||
print("[ERROR] Failed to read WAV file or unsupported format (must be 16kHz mono)")
|
||||
return
|
||||
|
||||
play_pcm_stream(audioClient, pcm_list, "example")
|
||||
|
||||
audioClient.PlayStop("example")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
BIN
vendor/unitree_sdk2_python/example/g1/audio/test.wav
vendored
Normal file
BIN
vendor/unitree_sdk2_python/example/g1/audio/test.wav
vendored
Normal file
Binary file not shown.
166
vendor/unitree_sdk2_python/example/g1/audio/wav.py
vendored
Normal file
166
vendor/unitree_sdk2_python/example/g1/audio/wav.py
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
import struct
|
||||
import time
|
||||
|
||||
def read_wav(filename):
|
||||
try:
|
||||
with open(filename, 'rb') as f:
|
||||
def read(fmt):
|
||||
return struct.unpack(fmt, f.read(struct.calcsize(fmt)))
|
||||
|
||||
# === Chunk Header ===
|
||||
chunk_id, = read('<I')
|
||||
if chunk_id != 0x46464952: # "RIFF"
|
||||
print(f"[ERROR] chunk_id != 'RIFF': {hex(chunk_id)}")
|
||||
return [], -1, -1, False
|
||||
|
||||
_chunk_size, = read('<I')
|
||||
format_tag, = read('<I')
|
||||
if format_tag != 0x45564157: # "WAVE"
|
||||
print(f"[ERROR] format != 'WAVE': {hex(format_tag)}")
|
||||
return [], -1, -1, False
|
||||
|
||||
# === Subchunk1: fmt ===
|
||||
subchunk1_id, = read('<I')
|
||||
subchunk1_size, = read('<I')
|
||||
|
||||
if subchunk1_id == 0x4B4E554A: # JUNK
|
||||
f.seek(subchunk1_size, 1)
|
||||
subchunk1_id, = read('<I')
|
||||
subchunk1_size, = read('<I')
|
||||
|
||||
if subchunk1_id != 0x20746D66: # "fmt "
|
||||
print(f"[ERROR] subchunk1_id != 'fmt ': {hex(subchunk1_id)}")
|
||||
return [], -1, -1, False
|
||||
|
||||
if subchunk1_size not in [16, 18]:
|
||||
print(f"[ERROR] subchunk1_size != 16 or 18: {subchunk1_size}")
|
||||
return [], -1, -1, False
|
||||
|
||||
audio_format, = read('<H')
|
||||
if audio_format != 1:
|
||||
print(f"[ERROR] audio_format != PCM (1): {audio_format}")
|
||||
return [], -1, -1, False
|
||||
|
||||
num_channels, = read('<H')
|
||||
sample_rate, = read('<I')
|
||||
byte_rate, = read('<I')
|
||||
block_align, = read('<H')
|
||||
bits_per_sample, = read('<H')
|
||||
|
||||
expected_byte_rate = sample_rate * num_channels * bits_per_sample // 8
|
||||
if byte_rate != expected_byte_rate:
|
||||
print(f"[ERROR] byte_rate mismatch: got {byte_rate}, expected {expected_byte_rate}")
|
||||
return [], -1, -1, False
|
||||
|
||||
expected_align = num_channels * bits_per_sample // 8
|
||||
if block_align != expected_align:
|
||||
print(f"[ERROR] block_align mismatch: got {block_align}, expected {expected_align}")
|
||||
return [], -1, -1, False
|
||||
|
||||
if bits_per_sample != 16:
|
||||
print(f"[ERROR] Only 16-bit samples supported, got {bits_per_sample}")
|
||||
return [], -1, -1, False
|
||||
|
||||
if subchunk1_size == 18:
|
||||
extra_size, = read('<H')
|
||||
if extra_size != 0:
|
||||
print(f"[ERROR] extra_size != 0: {extra_size}")
|
||||
return [], -1, -1, False
|
||||
|
||||
# === Subchunk2: data ===
|
||||
while True:
|
||||
subchunk2_id, subchunk2_size = read('<II')
|
||||
if subchunk2_id == 0x61746164: # "data"
|
||||
break
|
||||
f.seek(subchunk2_size, 1)
|
||||
|
||||
raw_pcm = f.read(subchunk2_size)
|
||||
if len(raw_pcm) != subchunk2_size:
|
||||
print("[ERROR] Failed to read full PCM data")
|
||||
return [], -1, -1, False
|
||||
|
||||
return list(raw_pcm), sample_rate, num_channels, True
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] read_wave() failed: {e}")
|
||||
return [], -1, -1, False
|
||||
|
||||
|
||||
def write_wave(filename, sample_rate, samples, num_channels=1):
|
||||
try:
|
||||
import array
|
||||
if isinstance(samples[0], int):
|
||||
samples = array.array('h', samples)
|
||||
|
||||
subchunk2_size = len(samples) * 2
|
||||
chunk_size = 36 + subchunk2_size
|
||||
|
||||
with open(filename, 'wb') as f:
|
||||
# RIFF chunk
|
||||
f.write(struct.pack('<I', 0x46464952)) # "RIFF"
|
||||
f.write(struct.pack('<I', chunk_size))
|
||||
f.write(struct.pack('<I', 0x45564157)) # "WAVE"
|
||||
|
||||
# fmt subchunk
|
||||
f.write(struct.pack('<I', 0x20746D66)) # "fmt "
|
||||
f.write(struct.pack('<I', 16)) # PCM
|
||||
f.write(struct.pack('<H', 1)) # PCM format
|
||||
f.write(struct.pack('<H', num_channels))
|
||||
f.write(struct.pack('<I', sample_rate))
|
||||
f.write(struct.pack('<I', sample_rate * num_channels * 2)) # byte_rate
|
||||
f.write(struct.pack('<H', num_channels * 2)) # block_align
|
||||
f.write(struct.pack('<H', 16)) # bits per sample
|
||||
|
||||
# data subchunk
|
||||
f.write(struct.pack('<I', 0x61746164)) # "data"
|
||||
f.write(struct.pack('<I', subchunk2_size))
|
||||
f.write(samples.tobytes())
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"[ERROR] write_wave() failed: {e}")
|
||||
return False
|
||||
|
||||
|
||||
def play_pcm_stream(client, pcm_list, stream_name="example", chunk_size=96000, sleep_time=1.0, verbose=False):
|
||||
"""
|
||||
Play PCM audio stream (16-bit little-endian format), sending data in chunks.
|
||||
|
||||
Parameters:
|
||||
client: An object with a PlayStream method
|
||||
pcm_list: list[int], PCM audio data in int16 format
|
||||
stream_name: Stream name, default is "example"
|
||||
chunk_size: Number of bytes to send per chunk, default is 96000 (3 seconds at 16kHz)
|
||||
sleep_time: Delay between chunks in seconds
|
||||
"""
|
||||
pcm_data = bytes(pcm_list)
|
||||
stream_id = str(int(time.time() * 1000)) # Unique stream ID based on current timestamp
|
||||
offset = 0
|
||||
chunk_index = 0
|
||||
total_size = len(pcm_data)
|
||||
|
||||
while offset < total_size:
|
||||
remaining = total_size - offset
|
||||
current_chunk_size = min(chunk_size, remaining)
|
||||
chunk = pcm_data[offset:offset + current_chunk_size]
|
||||
|
||||
if verbose:
|
||||
# Print info about the current chunk
|
||||
print(f"[CHUNK {chunk_index}] offset = {offset}, size = {current_chunk_size} bytes")
|
||||
print(" First 10 samples (int16): ", end="")
|
||||
for i in range(0, min(20, len(chunk) - 1), 2):
|
||||
sample = struct.unpack_from('<h', chunk, i)[0]
|
||||
print(sample, end=" ")
|
||||
print()
|
||||
|
||||
# Send the chunk
|
||||
ret_code, _ = client.PlayStream(stream_name, stream_id, chunk)
|
||||
if ret_code != 0:
|
||||
print(f"[ERROR] Failed to send chunk {chunk_index}, return code: {ret_code}")
|
||||
break
|
||||
else:
|
||||
print(f"[INFO] Chunk {chunk_index} sent successfully")
|
||||
|
||||
offset += current_chunk_size
|
||||
chunk_index += 1
|
||||
time.sleep(sleep_time)
|
||||
192
vendor/unitree_sdk2_python/example/g1/high_level/g1_arm5_sdk_dds_example.py
vendored
Normal file
192
vendor/unitree_sdk2_python/example/g1/high_level/g1_arm5_sdk_dds_example.py
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
|
||||
import numpy as np
|
||||
|
||||
kPi = 3.141592654
|
||||
kPi_2 = 1.57079632
|
||||
|
||||
class G1JointIndex:
|
||||
# Left leg
|
||||
LeftHipPitch = 0
|
||||
LeftHipRoll = 1
|
||||
LeftHipYaw = 2
|
||||
LeftKnee = 3
|
||||
LeftAnklePitch = 4
|
||||
LeftAnkleB = 4
|
||||
LeftAnkleRoll = 5
|
||||
LeftAnkleA = 5
|
||||
|
||||
# Right leg
|
||||
RightHipPitch = 6
|
||||
RightHipRoll = 7
|
||||
RightHipYaw = 8
|
||||
RightKnee = 9
|
||||
RightAnklePitch = 10
|
||||
RightAnkleB = 10
|
||||
RightAnkleRoll = 11
|
||||
RightAnkleA = 11
|
||||
|
||||
WaistYaw = 12
|
||||
WaistRoll = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistA = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistPitch = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistB = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
|
||||
# Left arm
|
||||
LeftShoulderPitch = 15
|
||||
LeftShoulderRoll = 16
|
||||
LeftShoulderYaw = 17
|
||||
LeftElbow = 18
|
||||
LeftWristRoll = 19
|
||||
LeftWristPitch = 20 # NOTE: INVALID for g1 23dof
|
||||
LeftWristYaw = 21 # NOTE: INVALID for g1 23dof
|
||||
|
||||
# Right arm
|
||||
RightShoulderPitch = 22
|
||||
RightShoulderRoll = 23
|
||||
RightShoulderYaw = 24
|
||||
RightElbow = 25
|
||||
RightWristRoll = 26
|
||||
RightWristPitch = 27 # NOTE: INVALID for g1 23dof
|
||||
RightWristYaw = 28 # NOTE: INVALID for g1 23dof
|
||||
|
||||
kNotUsedJoint = 29 # NOTE: Weight
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.02
|
||||
self.duration_ = 3.0
|
||||
self.counter_ = 0
|
||||
self.weight = 0.
|
||||
self.weight_rate = 0.2
|
||||
self.kp = 60.
|
||||
self.kd = 1.5
|
||||
self.dq = 0.
|
||||
self.tau_ff = 0.
|
||||
self.mode_machine_ = 0
|
||||
self.low_cmd = unitree_hg_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
self.first_update_low_state = False
|
||||
self.crc = CRC()
|
||||
self.done = False
|
||||
|
||||
self.target_pos = [
|
||||
0.0, kPi_2, 0.0, kPi_2, 0.0,
|
||||
0.0, -kPi_2, 0.0, kPi_2, 0.0,
|
||||
0.0, 0.0, 0.0
|
||||
]
|
||||
|
||||
self.arm_joints = [
|
||||
G1JointIndex.LeftShoulderPitch, G1JointIndex.LeftShoulderRoll,
|
||||
G1JointIndex.LeftShoulderYaw, G1JointIndex.LeftElbow,
|
||||
G1JointIndex.LeftWristRoll,
|
||||
G1JointIndex.RightShoulderPitch, G1JointIndex.RightShoulderRoll,
|
||||
G1JointIndex.RightShoulderYaw, G1JointIndex.RightElbow,
|
||||
G1JointIndex.RightWristRoll,
|
||||
G1JointIndex.WaistYaw,
|
||||
G1JointIndex.WaistRoll,
|
||||
G1JointIndex.WaistPitch
|
||||
]
|
||||
|
||||
def Init(self):
|
||||
# create publisher #
|
||||
self.arm_sdk_publisher = ChannelPublisher("rt/arm_sdk", LowCmd_)
|
||||
self.arm_sdk_publisher.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateHandler, 10)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
while self.first_update_low_state == False:
|
||||
time.sleep(1)
|
||||
|
||||
if self.first_update_low_state == True:
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
if self.first_update_low_state == False:
|
||||
self.first_update_low_state = True
|
||||
|
||||
def LowCmdWrite(self):
|
||||
self.time_ += self.control_dt_
|
||||
|
||||
if self.time_ < self.duration_ :
|
||||
# [Stage 1]: set robot to zero posture
|
||||
self.low_cmd.motor_cmd[G1JointIndex.kNotUsedJoint].q = 1 # 1:Enable arm_sdk, 0:Disable arm_sdk
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.
|
||||
self.low_cmd.motor_cmd[joint].q = (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 3 :
|
||||
# [Stage 2]: lift arms up
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_) / (self.duration_ * 2), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.
|
||||
self.low_cmd.motor_cmd[joint].q = ratio * self.target_pos[i] + (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 6 :
|
||||
# [Stage 3]: set robot back to zero posture
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_*3) / (self.duration_ * 3), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.
|
||||
self.low_cmd.motor_cmd[joint].q = (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 7 :
|
||||
# [Stage 4]: release arm_sdk
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_*6) / (self.duration_), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[G1JointIndex.kNotUsedJoint].q = (1 - ratio) # 1:Enable arm_sdk, 0:Disable arm_sdk
|
||||
|
||||
else:
|
||||
self.done = True
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.arm_sdk_publisher.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
if custom.done:
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
194
vendor/unitree_sdk2_python/example/g1/high_level/g1_arm7_sdk_dds_example.py
vendored
Normal file
194
vendor/unitree_sdk2_python/example/g1/high_level/g1_arm7_sdk_dds_example.py
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
|
||||
import numpy as np
|
||||
|
||||
kPi = 3.141592654
|
||||
kPi_2 = 1.57079632
|
||||
|
||||
class G1JointIndex:
|
||||
# Left leg
|
||||
LeftHipPitch = 0
|
||||
LeftHipRoll = 1
|
||||
LeftHipYaw = 2
|
||||
LeftKnee = 3
|
||||
LeftAnklePitch = 4
|
||||
LeftAnkleB = 4
|
||||
LeftAnkleRoll = 5
|
||||
LeftAnkleA = 5
|
||||
|
||||
# Right leg
|
||||
RightHipPitch = 6
|
||||
RightHipRoll = 7
|
||||
RightHipYaw = 8
|
||||
RightKnee = 9
|
||||
RightAnklePitch = 10
|
||||
RightAnkleB = 10
|
||||
RightAnkleRoll = 11
|
||||
RightAnkleA = 11
|
||||
|
||||
WaistYaw = 12
|
||||
WaistRoll = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistA = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistPitch = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistB = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
|
||||
# Left arm
|
||||
LeftShoulderPitch = 15
|
||||
LeftShoulderRoll = 16
|
||||
LeftShoulderYaw = 17
|
||||
LeftElbow = 18
|
||||
LeftWristRoll = 19
|
||||
LeftWristPitch = 20 # NOTE: INVALID for g1 23dof
|
||||
LeftWristYaw = 21 # NOTE: INVALID for g1 23dof
|
||||
|
||||
# Right arm
|
||||
RightShoulderPitch = 22
|
||||
RightShoulderRoll = 23
|
||||
RightShoulderYaw = 24
|
||||
RightElbow = 25
|
||||
RightWristRoll = 26
|
||||
RightWristPitch = 27 # NOTE: INVALID for g1 23dof
|
||||
RightWristYaw = 28 # NOTE: INVALID for g1 23dof
|
||||
|
||||
kNotUsedJoint = 29 # NOTE: Weight
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.02
|
||||
self.duration_ = 3.0
|
||||
self.counter_ = 0
|
||||
self.weight = 0.
|
||||
self.weight_rate = 0.2
|
||||
self.kp = 60.
|
||||
self.kd = 1.5
|
||||
self.dq = 0.
|
||||
self.tau_ff = 0.
|
||||
self.mode_machine_ = 0
|
||||
self.low_cmd = unitree_hg_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
self.first_update_low_state = False
|
||||
self.crc = CRC()
|
||||
self.done = False
|
||||
|
||||
self.target_pos = [
|
||||
0., kPi_2, 0., kPi_2, 0., 0., 0.,
|
||||
0., -kPi_2, 0., kPi_2, 0., 0., 0.,
|
||||
0, 0, 0
|
||||
]
|
||||
|
||||
self.arm_joints = [
|
||||
G1JointIndex.LeftShoulderPitch, G1JointIndex.LeftShoulderRoll,
|
||||
G1JointIndex.LeftShoulderYaw, G1JointIndex.LeftElbow,
|
||||
G1JointIndex.LeftWristRoll, G1JointIndex.LeftWristPitch,
|
||||
G1JointIndex.LeftWristYaw,
|
||||
G1JointIndex.RightShoulderPitch, G1JointIndex.RightShoulderRoll,
|
||||
G1JointIndex.RightShoulderYaw, G1JointIndex.RightElbow,
|
||||
G1JointIndex.RightWristRoll, G1JointIndex.RightWristPitch,
|
||||
G1JointIndex.RightWristYaw,
|
||||
G1JointIndex.WaistYaw,
|
||||
G1JointIndex.WaistRoll,
|
||||
G1JointIndex.WaistPitch
|
||||
]
|
||||
|
||||
def Init(self):
|
||||
# create publisher #
|
||||
self.arm_sdk_publisher = ChannelPublisher("rt/arm_sdk", LowCmd_)
|
||||
self.arm_sdk_publisher.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateHandler, 10)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
while self.first_update_low_state == False:
|
||||
time.sleep(1)
|
||||
|
||||
if self.first_update_low_state == True:
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
if self.first_update_low_state == False:
|
||||
self.first_update_low_state = True
|
||||
|
||||
def LowCmdWrite(self):
|
||||
self.time_ += self.control_dt_
|
||||
|
||||
if self.time_ < self.duration_ :
|
||||
# [Stage 1]: set robot to zero posture
|
||||
self.low_cmd.motor_cmd[G1JointIndex.kNotUsedJoint].q = 1 # 1:Enable arm_sdk, 0:Disable arm_sdk
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.
|
||||
self.low_cmd.motor_cmd[joint].q = (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 3 :
|
||||
# [Stage 2]: lift arms up
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_) / (self.duration_ * 2), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.
|
||||
self.low_cmd.motor_cmd[joint].q = ratio * self.target_pos[i] + (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 6 :
|
||||
# [Stage 3]: set robot back to zero posture
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_*3) / (self.duration_ * 3), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.
|
||||
self.low_cmd.motor_cmd[joint].q = (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 7 :
|
||||
# [Stage 4]: release arm_sdk
|
||||
for i,joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_*6) / (self.duration_), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[G1JointIndex.kNotUsedJoint].q = (1 - ratio) # 1:Enable arm_sdk, 0:Disable arm_sdk
|
||||
|
||||
else:
|
||||
self.done = True
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.arm_sdk_publisher.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
if custom.done:
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
141
vendor/unitree_sdk2_python/example/g1/high_level/g1_arm_action_example.py
vendored
Normal file
141
vendor/unitree_sdk2_python/example/g1/high_level/g1_arm_action_example.py
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.g1.arm.g1_arm_action_client import G1ArmActionClient
|
||||
from unitree_sdk2py.g1.arm.g1_arm_action_client import action_map
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="release arm", id=0),
|
||||
TestOption(name="shake hand", id=1),
|
||||
TestOption(name="high five", id=2),
|
||||
TestOption(name="hug", id=3),
|
||||
TestOption(name="high wave", id=4),
|
||||
TestOption(name="clap", id=5),
|
||||
TestOption(name="face wave", id=6),
|
||||
TestOption(name="left kiss", id=7),
|
||||
TestOption(name="heart", id=8),
|
||||
TestOption(name="right heart", id=9),
|
||||
TestOption(name="hands up", id=10),
|
||||
TestOption(name="x-ray", id=11),
|
||||
TestOption(name="right hand up", id=12),
|
||||
TestOption(name="reject", id=13),
|
||||
TestOption(name="right kiss", id=14),
|
||||
TestOption(name="two-hand kiss", id=15),
|
||||
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
armAction_client = G1ArmActionClient()
|
||||
armAction_client.SetTimeout(10.0)
|
||||
armAction_client.Init()
|
||||
|
||||
# actionList = armAction_client.GetActionList()
|
||||
# print("actionList\n",actionList)
|
||||
|
||||
print("Input \"list\" to list all test option ...")
|
||||
while True:
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}")
|
||||
|
||||
if test_option.id == 0:
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 1:
|
||||
armAction_client.ExecuteAction(action_map.get("shake hand"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 2:
|
||||
armAction_client.ExecuteAction(action_map.get("high five"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 3:
|
||||
armAction_client.ExecuteAction(action_map.get("hug"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 4:
|
||||
armAction_client.ExecuteAction(action_map.get("high wave"))
|
||||
elif test_option.id == 5:
|
||||
armAction_client.ExecuteAction(action_map.get("clap"))
|
||||
elif test_option.id == 6:
|
||||
armAction_client.ExecuteAction(action_map.get("face wave"))
|
||||
elif test_option.id == 7:
|
||||
armAction_client.ExecuteAction(action_map.get("left kiss"))
|
||||
elif test_option.id == 8:
|
||||
armAction_client.ExecuteAction(action_map.get("heart"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 9:
|
||||
armAction_client.ExecuteAction(action_map.get("right heart"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 10:
|
||||
armAction_client.ExecuteAction(action_map.get("hands up"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 11:
|
||||
armAction_client.ExecuteAction(action_map.get("x-ray"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 12:
|
||||
armAction_client.ExecuteAction(action_map.get("right hand up"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 13:
|
||||
armAction_client.ExecuteAction(action_map.get("reject"))
|
||||
time.sleep(2)
|
||||
armAction_client.ExecuteAction(action_map.get("release arm"))
|
||||
elif test_option.id == 14:
|
||||
armAction_client.ExecuteAction(action_map.get("right kiss"))
|
||||
elif test_option.id == 15:
|
||||
armAction_client.ExecuteAction(action_map.get("two-hand kiss"))
|
||||
|
||||
time.sleep(1)
|
||||
117
vendor/unitree_sdk2_python/example/g1/high_level/g1_loco_client_example.py
vendored
Normal file
117
vendor/unitree_sdk2_python/example/g1/high_level/g1_loco_client_example.py
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__SportModeState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_
|
||||
from unitree_sdk2py.g1.loco.g1_loco_client import LocoClient
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="Squat2StandUp", id=1),
|
||||
TestOption(name="StandUp2Squat", id=2),
|
||||
TestOption(name="move forward", id=3),
|
||||
TestOption(name="move lateral", id=4),
|
||||
TestOption(name="move rotate", id=5),
|
||||
TestOption(name="low stand", id=6),
|
||||
TestOption(name="high stand", id=7),
|
||||
TestOption(name="zero torque", id=8),
|
||||
TestOption(name="wave hand1", id=9), # wave hand without turning around
|
||||
TestOption(name="wave hand2", id=10), # wave hand and trun around
|
||||
TestOption(name="shake hand", id=11),
|
||||
TestOption(name="Lie2StandUp", id=12),
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = LocoClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
print("Input \"list\" to list all test option ...")
|
||||
while True:
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}")
|
||||
|
||||
if test_option.id == 0:
|
||||
sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
sport_client.Damp()
|
||||
time.sleep(0.5)
|
||||
sport_client.Squat2StandUp()
|
||||
elif test_option.id == 2:
|
||||
sport_client.StandUp2Squat()
|
||||
elif test_option.id == 3:
|
||||
sport_client.Move(0.3,0,0)
|
||||
elif test_option.id == 4:
|
||||
sport_client.Move(0,0.3,0)
|
||||
elif test_option.id == 5:
|
||||
sport_client.Move(0,0,0.3)
|
||||
elif test_option.id == 6:
|
||||
sport_client.LowStand()
|
||||
elif test_option.id == 7:
|
||||
sport_client.HighStand()
|
||||
elif test_option.id == 8:
|
||||
sport_client.ZeroTorque()
|
||||
elif test_option.id == 9:
|
||||
sport_client.WaveHand()
|
||||
elif test_option.id == 10:
|
||||
sport_client.WaveHand(True)
|
||||
elif test_option.id == 11:
|
||||
sport_client.ShakeHand()
|
||||
time.sleep(3)
|
||||
sport_client.ShakeHand()
|
||||
elif test_option.id == 12:
|
||||
sport_client.Damp()
|
||||
time.sleep(0.5)
|
||||
sport_client.Lie2StandUp() # When using the Lie2StandUp function, ensure that the robot faces up and the ground is hard, flat and rough.
|
||||
|
||||
time.sleep(1)
|
||||
205
vendor/unitree_sdk2_python/example/g1/low_level/g1_low_level_example.py
vendored
Normal file
205
vendor/unitree_sdk2_python/example/g1/low_level/g1_low_level_example.py
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
|
||||
import numpy as np
|
||||
|
||||
G1_NUM_MOTOR = 29
|
||||
|
||||
Kp = [
|
||||
60, 60, 60, 100, 40, 40, # legs
|
||||
60, 60, 60, 100, 40, 40, # legs
|
||||
60, 40, 40, # waist
|
||||
40, 40, 40, 40, 40, 40, 40, # arms
|
||||
40, 40, 40, 40, 40, 40, 40 # arms
|
||||
]
|
||||
|
||||
Kd = [
|
||||
1, 1, 1, 2, 1, 1, # legs
|
||||
1, 1, 1, 2, 1, 1, # legs
|
||||
1, 1, 1, # waist
|
||||
1, 1, 1, 1, 1, 1, 1, # arms
|
||||
1, 1, 1, 1, 1, 1, 1 # arms
|
||||
]
|
||||
|
||||
class G1JointIndex:
|
||||
LeftHipPitch = 0
|
||||
LeftHipRoll = 1
|
||||
LeftHipYaw = 2
|
||||
LeftKnee = 3
|
||||
LeftAnklePitch = 4
|
||||
LeftAnkleB = 4
|
||||
LeftAnkleRoll = 5
|
||||
LeftAnkleA = 5
|
||||
RightHipPitch = 6
|
||||
RightHipRoll = 7
|
||||
RightHipYaw = 8
|
||||
RightKnee = 9
|
||||
RightAnklePitch = 10
|
||||
RightAnkleB = 10
|
||||
RightAnkleRoll = 11
|
||||
RightAnkleA = 11
|
||||
WaistYaw = 12
|
||||
WaistRoll = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistA = 13 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistPitch = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
WaistB = 14 # NOTE: INVALID for g1 23dof/29dof with waist locked
|
||||
LeftShoulderPitch = 15
|
||||
LeftShoulderRoll = 16
|
||||
LeftShoulderYaw = 17
|
||||
LeftElbow = 18
|
||||
LeftWristRoll = 19
|
||||
LeftWristPitch = 20 # NOTE: INVALID for g1 23dof
|
||||
LeftWristYaw = 21 # NOTE: INVALID for g1 23dof
|
||||
RightShoulderPitch = 22
|
||||
RightShoulderRoll = 23
|
||||
RightShoulderYaw = 24
|
||||
RightElbow = 25
|
||||
RightWristRoll = 26
|
||||
RightWristPitch = 27 # NOTE: INVALID for g1 23dof
|
||||
RightWristYaw = 28 # NOTE: INVALID for g1 23dof
|
||||
|
||||
|
||||
class Mode:
|
||||
PR = 0 # Series Control for Pitch/Roll Joints
|
||||
AB = 1 # Parallel Control for A/B Joints
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.002 # [2ms]
|
||||
self.duration_ = 3.0 # [3 s]
|
||||
self.counter_ = 0
|
||||
self.mode_pr_ = Mode.PR
|
||||
self.mode_machine_ = 0
|
||||
self.low_cmd = unitree_hg_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
self.update_mode_machine_ = False
|
||||
self.crc = CRC()
|
||||
|
||||
def Init(self):
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
# create publisher #
|
||||
self.lowcmd_publisher_ = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher_.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateHandler, 10)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
while self.update_mode_machine_ == False:
|
||||
time.sleep(1)
|
||||
|
||||
if self.update_mode_machine_ == True:
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
if self.update_mode_machine_ == False:
|
||||
self.mode_machine_ = self.low_state.mode_machine
|
||||
self.update_mode_machine_ = True
|
||||
|
||||
self.counter_ +=1
|
||||
if (self.counter_ % 500 == 0) :
|
||||
self.counter_ = 0
|
||||
print(self.low_state.imu_state.rpy)
|
||||
|
||||
def LowCmdWrite(self):
|
||||
self.time_ += self.control_dt_
|
||||
|
||||
if self.time_ < self.duration_ :
|
||||
# [Stage 1]: set robot to zero posture
|
||||
for i in range(G1_NUM_MOTOR):
|
||||
ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.mode_pr = Mode.PR
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
self.low_cmd.motor_cmd[i].mode = 1 # 1:Enable, 0:Disable
|
||||
self.low_cmd.motor_cmd[i].tau = 0.
|
||||
self.low_cmd.motor_cmd[i].q = (1.0 - ratio) * self.low_state.motor_state[i].q
|
||||
self.low_cmd.motor_cmd[i].dq = 0.
|
||||
self.low_cmd.motor_cmd[i].kp = Kp[i]
|
||||
self.low_cmd.motor_cmd[i].kd = Kd[i]
|
||||
|
||||
elif self.time_ < self.duration_ * 2 :
|
||||
# [Stage 2]: swing ankle using PR mode
|
||||
max_P = np.pi * 30.0 / 180.0
|
||||
max_R = np.pi * 10.0 / 180.0
|
||||
t = self.time_ - self.duration_
|
||||
L_P_des = max_P * np.sin(2.0 * np.pi * t)
|
||||
L_R_des = max_R * np.sin(2.0 * np.pi * t)
|
||||
R_P_des = max_P * np.sin(2.0 * np.pi * t)
|
||||
R_R_des = -max_R * np.sin(2.0 * np.pi * t)
|
||||
|
||||
self.low_cmd.mode_pr = Mode.PR
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
self.low_cmd.motor_cmd[G1JointIndex.LeftAnklePitch].q = L_P_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.LeftAnkleRoll].q = L_R_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.RightAnklePitch].q = R_P_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.RightAnkleRoll].q = R_R_des
|
||||
|
||||
else :
|
||||
# [Stage 3]: swing ankle using AB mode
|
||||
max_A = np.pi * 30.0 / 180.0
|
||||
max_B = np.pi * 10.0 / 180.0
|
||||
t = self.time_ - self.duration_ * 2
|
||||
L_A_des = max_A * np.sin(2.0 * np.pi * t)
|
||||
L_B_des = max_B * np.sin(2.0 * np.pi * t + np.pi)
|
||||
R_A_des = -max_A * np.sin(2.0 * np.pi * t)
|
||||
R_B_des = -max_B * np.sin(2.0 * np.pi * t + np.pi)
|
||||
|
||||
self.low_cmd.mode_pr = Mode.AB
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
self.low_cmd.motor_cmd[G1JointIndex.LeftAnkleA].q = L_A_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.LeftAnkleB].q = L_B_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.RightAnkleA].q = R_A_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.RightAnkleB].q = R_B_des
|
||||
|
||||
max_WristYaw = np.pi * 30.0 / 180.0
|
||||
L_WristYaw_des = max_WristYaw * np.sin(2.0 * np.pi * t)
|
||||
R_WristYaw_des = max_WristYaw * np.sin(2.0 * np.pi * t)
|
||||
self.low_cmd.motor_cmd[G1JointIndex.LeftWristRoll].q = L_WristYaw_des
|
||||
self.low_cmd.motor_cmd[G1JointIndex.RightWristRoll].q = R_WristYaw_des
|
||||
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher_.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
5
vendor/unitree_sdk2_python/example/g1/readme.md
vendored
Normal file
5
vendor/unitree_sdk2_python/example/g1/readme.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
This example is a test of Unitree G1/H1-2 robot.
|
||||
|
||||
**Note:**
|
||||
idl/unitree_go is used for Unitree Go2/B2/H1/B2w/Go2w robots
|
||||
idl/unitree_hg is used for Unitree G1/H1-2 robots
|
||||
41
vendor/unitree_sdk2_python/example/go2/front_camera/camera_opencv.py
vendored
Normal file
41
vendor/unitree_sdk2_python/example/go2/front_camera/camera_opencv.py
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.go2.video.video_client import VideoClient
|
||||
import cv2
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
client = VideoClient() # Create a video client
|
||||
client.SetTimeout(3.0)
|
||||
client.Init()
|
||||
|
||||
code, data = client.GetImageSample()
|
||||
|
||||
# Request normal when code==0
|
||||
while code == 0:
|
||||
# Get Image data from Go2 robot
|
||||
code, data = client.GetImageSample()
|
||||
|
||||
# Convert to numpy image
|
||||
image_data = np.frombuffer(bytes(data), dtype=np.uint8)
|
||||
image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
|
||||
|
||||
# Display image
|
||||
cv2.imshow("front_camera", image)
|
||||
# Press ESC to stop
|
||||
if cv2.waitKey(20) == 27:
|
||||
break
|
||||
|
||||
if code != 0:
|
||||
print("Get image sample error. code:", code)
|
||||
else:
|
||||
# Capture an image
|
||||
cv2.imwrite("front_image.jpg", image)
|
||||
|
||||
cv2.destroyWindow("front_camera")
|
||||
30
vendor/unitree_sdk2_python/example/go2/front_camera/capture_image.py
vendored
Normal file
30
vendor/unitree_sdk2_python/example/go2/front_camera/capture_image.py
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
import time
|
||||
import os
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.go2.video.video_client import VideoClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
client = VideoClient()
|
||||
client.SetTimeout(3.0)
|
||||
client.Init()
|
||||
|
||||
print("##################GetImageSample###################")
|
||||
code, data = client.GetImageSample()
|
||||
|
||||
if code != 0:
|
||||
print("get image sample error. code:", code)
|
||||
else:
|
||||
imageName = "./img.jpg"
|
||||
print("ImageName:", imageName)
|
||||
|
||||
with open(imageName, "+wb") as f:
|
||||
f.write(bytes(data))
|
||||
|
||||
time.sleep(1)
|
||||
155
vendor/unitree_sdk2_python/example/go2/high_level/go2_sport_client.py
vendored
Normal file
155
vendor/unitree_sdk2_python/example/go2/high_level/go2_sport_client.py
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__SportModeState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_
|
||||
from unitree_sdk2py.go2.sport.sport_client import (
|
||||
SportClient,
|
||||
PathPoint,
|
||||
SPORT_PATH_POINT_SIZE,
|
||||
)
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="stand_up", id=1),
|
||||
TestOption(name="stand_down", id=2),
|
||||
TestOption(name="move forward", id=3),
|
||||
TestOption(name="move lateral", id=4),
|
||||
TestOption(name="move rotate", id=5),
|
||||
TestOption(name="stop_move", id=6),
|
||||
TestOption(name="hand stand", id=7),
|
||||
TestOption(name="balanced stand", id=9),
|
||||
TestOption(name="recovery", id=10),
|
||||
TestOption(name="left flip", id=11),
|
||||
TestOption(name="back flip", id=12),
|
||||
TestOption(name="free walk", id=13),
|
||||
TestOption(name="free bound", id=14),
|
||||
TestOption(name="free avoid", id=15),
|
||||
TestOption(name="walk upright", id=17),
|
||||
TestOption(name="cross step", id=18),
|
||||
TestOption(name="free jump", id=19)
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = SportClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
while True:
|
||||
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}\n")
|
||||
|
||||
if test_option.id == 0:
|
||||
sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
sport_client.StandUp()
|
||||
elif test_option.id == 2:
|
||||
sport_client.StandDown()
|
||||
elif test_option.id == 3:
|
||||
ret = sport_client.Move(0.3,0,0)
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 4:
|
||||
sport_client.Move(0,0.3,0)
|
||||
elif test_option.id == 5:
|
||||
sport_client.Move(0,0,0.5)
|
||||
elif test_option.id == 6:
|
||||
sport_client.StopMove()
|
||||
elif test_option.id == 7:
|
||||
sport_client.HandStand(True)
|
||||
time.sleep(4)
|
||||
sport_client.HandStand(False)
|
||||
elif test_option.id == 9:
|
||||
sport_client.BalanceStand()
|
||||
elif test_option.id == 10:
|
||||
sport_client.RecoveryStand()
|
||||
elif test_option.id == 11:
|
||||
ret = sport_client.LeftFlip()
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 12:
|
||||
ret = sport_client.BackFlip()
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 13:
|
||||
ret = sport_client.FreeWalk()
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 14:
|
||||
ret = sport_client.FreeBound(True)
|
||||
print("ret: ",ret)
|
||||
time.sleep(2)
|
||||
ret = sport_client.FreeBound(False)
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 15:
|
||||
ret = sport_client.FreeAvoid(True)
|
||||
print("ret: ",ret)
|
||||
time.sleep(2)
|
||||
ret = sport_client.FreeAvoid(False)
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 17:
|
||||
ret = sport_client.WalkUpright(True)
|
||||
print("ret: ",ret)
|
||||
time.sleep(4)
|
||||
ret = sport_client.WalkUpright(False)
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 18:
|
||||
ret = sport_client.CrossStep(True)
|
||||
print("ret: ",ret)
|
||||
time.sleep(4)
|
||||
ret = sport_client.CrossStep(False)
|
||||
print("ret: ",ret)
|
||||
elif test_option.id == 19:
|
||||
ret = sport_client.FreeJump(True)
|
||||
print("ret: ",ret)
|
||||
time.sleep(4)
|
||||
ret = sport_client.FreeJump(False)
|
||||
print("ret: ",ret)
|
||||
|
||||
time.sleep(1)
|
||||
39
vendor/unitree_sdk2_python/example/go2/high_level/go2_utlidar_switch.py
vendored
Normal file
39
vendor/unitree_sdk2_python/example/go2/high_level/go2_utlidar_switch.py
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.std_msgs.msg.dds_ import String_
|
||||
from unitree_sdk2py.idl.default import std_msgs_msg_dds__String_
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
# create publisher #
|
||||
self.publisher = ChannelPublisher("rt/utlidar/switch", String_)
|
||||
self.publisher.Init()
|
||||
self.low_cmd = std_msgs_msg_dds__String_()
|
||||
|
||||
def go2_utlidar_switch(self,status):
|
||||
if status == "OFF":
|
||||
self.low_cmd.data = "OFF"
|
||||
elif status == "ON":
|
||||
self.low_cmd.data = "ON"
|
||||
|
||||
self.publisher.Write(self.low_cmd)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.go2_utlidar_switch("OFF")
|
||||
|
||||
|
||||
|
||||
176
vendor/unitree_sdk2_python/example/go2/low_level/go2_stand_example.py
vendored
Normal file
176
vendor/unitree_sdk2_python/example/go2/low_level/go2_stand_example.py
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
import unitree_legged_const as go2
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
from unitree_sdk2py.go2.sport.sport_client import SportClient
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.Kp = 60.0
|
||||
self.Kd = 5.0
|
||||
self.time_consume = 0
|
||||
self.rate_count = 0
|
||||
self.sin_count = 0
|
||||
self.motiontime = 0
|
||||
self.dt = 0.002 # 0.001~0.01
|
||||
|
||||
self.low_cmd = unitree_go_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
|
||||
self._targetPos_1 = [0.0, 1.36, -2.65, 0.0, 1.36, -2.65,
|
||||
-0.2, 1.36, -2.65, 0.2, 1.36, -2.65]
|
||||
self._targetPos_2 = [0.0, 0.67, -1.3, 0.0, 0.67, -1.3,
|
||||
0.0, 0.67, -1.3, 0.0, 0.67, -1.3]
|
||||
self._targetPos_3 = [-0.35, 1.36, -2.65, 0.35, 1.36, -2.65,
|
||||
-0.5, 1.36, -2.65, 0.5, 1.36, -2.65]
|
||||
|
||||
self.startPos = [0.0] * 12
|
||||
self.duration_1 = 500
|
||||
self.duration_2 = 500
|
||||
self.duration_3 = 1000
|
||||
self.duration_4 = 900
|
||||
self.percent_1 = 0
|
||||
self.percent_2 = 0
|
||||
self.percent_3 = 0
|
||||
self.percent_4 = 0
|
||||
|
||||
self.firstRun = True
|
||||
self.done = False
|
||||
|
||||
# thread handling
|
||||
self.lowCmdWriteThreadPtr = None
|
||||
|
||||
self.crc = CRC()
|
||||
|
||||
# Public methods
|
||||
def Init(self):
|
||||
self.InitLowCmd()
|
||||
|
||||
# create publisher #
|
||||
self.lowcmd_publisher = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateMessageHandler, 10)
|
||||
|
||||
self.sc = SportClient()
|
||||
self.sc.SetTimeout(5.0)
|
||||
self.sc.Init()
|
||||
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.sc.StandDown()
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=0.002, target=self.LowCmdWrite, name="writebasiccmd"
|
||||
)
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
# Private methods
|
||||
def InitLowCmd(self):
|
||||
self.low_cmd.head[0]=0xFE
|
||||
self.low_cmd.head[1]=0xEF
|
||||
self.low_cmd.level_flag = 0xFF
|
||||
self.low_cmd.gpio = 0
|
||||
for i in range(20):
|
||||
self.low_cmd.motor_cmd[i].mode = 0x01 # (PMSM) mode
|
||||
self.low_cmd.motor_cmd[i].q= go2.PosStopF
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = go2.VelStopF
|
||||
self.low_cmd.motor_cmd[i].kd = 0
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
def LowStateMessageHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
# print("FR_0 motor state: ", msg.motor_state[go2.LegID["FR_0"]])
|
||||
# print("IMU state: ", msg.imu_state)
|
||||
# print("Battery state: voltage: ", msg.power_v, "current: ", msg.power_a)
|
||||
|
||||
def LowCmdWrite(self):
|
||||
|
||||
if self.firstRun:
|
||||
for i in range(12):
|
||||
self.startPos[i] = self.low_state.motor_state[i].q
|
||||
self.firstRun = False
|
||||
|
||||
self.percent_1 += 1.0 / self.duration_1
|
||||
self.percent_1 = min(self.percent_1, 1)
|
||||
if self.percent_1 < 1:
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_1) * self.startPos[i] + self.percent_1 * self._targetPos_1[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 <= 1):
|
||||
self.percent_2 += 1.0 / self.duration_2
|
||||
self.percent_2 = min(self.percent_2, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_2) * self._targetPos_1[i] + self.percent_2 * self._targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 < 1):
|
||||
self.percent_3 += 1.0 / self.duration_3
|
||||
self.percent_3 = min(self.percent_3, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = self._targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 == 1) and (self.percent_4 <= 1):
|
||||
self.percent_4 += 1.0 / self.duration_4
|
||||
self.percent_4 = min(self.percent_4, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_4) * self._targetPos_2[i] + self.percent_4 * self._targetPos_3[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
if custom.percent_4 == 1.0:
|
||||
time.sleep(1)
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
time.sleep(1)
|
||||
20
vendor/unitree_sdk2_python/example/go2/low_level/unitree_legged_const.py
vendored
Normal file
20
vendor/unitree_sdk2_python/example/go2/low_level/unitree_legged_const.py
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
LegID = {
|
||||
"FR_0": 0, # Front right hip
|
||||
"FR_1": 1, # Front right thigh
|
||||
"FR_2": 2, # Front right calf
|
||||
"FL_0": 3,
|
||||
"FL_1": 4,
|
||||
"FL_2": 5,
|
||||
"RR_0": 6,
|
||||
"RR_1": 7,
|
||||
"RR_2": 8,
|
||||
"RL_0": 9,
|
||||
"RL_1": 10,
|
||||
"RL_2": 11,
|
||||
}
|
||||
|
||||
HIGHLEVEL = 0xEE
|
||||
LOWLEVEL = 0xFF
|
||||
TRIGERLEVEL = 0xF0
|
||||
PosStopF = 2.146e9
|
||||
VelStopF = 16000.0
|
||||
99
vendor/unitree_sdk2_python/example/go2w/high_level/go2w_sport_client.py
vendored
Normal file
99
vendor/unitree_sdk2_python/example/go2w/high_level/go2w_sport_client.py
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__SportModeState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_
|
||||
from unitree_sdk2py.go2.sport.sport_client import SportClient
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="stand_up", id=1),
|
||||
TestOption(name="stand_down", id=2),
|
||||
TestOption(name="move", id=3),
|
||||
TestOption(name="stop_move", id=4),
|
||||
TestOption(name="speed_level", id=5),
|
||||
TestOption(name="switch_gait", id=6),
|
||||
TestOption(name="get_state", id=7),
|
||||
TestOption(name="recovery", id=8),
|
||||
TestOption(name="balance", id=9)
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print(f"Usage: python3 {sys.argv[0]} networkInterface")
|
||||
sys.exit(-1)
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = SportClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
while True:
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}\n")
|
||||
|
||||
if test_option.id == 0:
|
||||
sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
sport_client.StandUp()
|
||||
elif test_option.id == 2:
|
||||
sport_client.StandDown()
|
||||
elif test_option.id == 3:
|
||||
sport_client.Move(0.5,0,0)
|
||||
elif test_option.id == 4:
|
||||
sport_client.StopMove()
|
||||
elif test_option.id == 5:
|
||||
sport_client.SpeedLevel(1)
|
||||
elif test_option.id == 6:
|
||||
sport_client.SwitchGait(1)
|
||||
elif test_option.id == 8:
|
||||
sport_client.RecoveryStand()
|
||||
elif test_option.id == 9:
|
||||
sport_client.BalanceStand()
|
||||
|
||||
time.sleep(1)
|
||||
196
vendor/unitree_sdk2_python/example/go2w/low_level/go2w_stand_example.py
vendored
Normal file
196
vendor/unitree_sdk2_python/example/go2w/low_level/go2w_stand_example.py
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
import unitree_legged_const as go2w
|
||||
from unitree_sdk2py.go2.robot_state.robot_state_client import RobotStateClient
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
from unitree_sdk2py.go2.sport.sport_client import SportClient
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.Kp = 70.0
|
||||
self.Kd = 5.0
|
||||
self.time_consume = 0
|
||||
self.rate_count = 0
|
||||
self.sin_count = 0
|
||||
self.motiontime = 0
|
||||
self.dt = 0.002
|
||||
|
||||
self.low_cmd = unitree_go_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
|
||||
self.targetPos_1 = [0.0, 1.36, -2.65, 0.0, 1.36, -2.65,
|
||||
-0.2, 1.36, -2.65, 0.2, 1.36, -2.65]
|
||||
|
||||
self.targetPos_2 = [0.0, 0.67, -1.3, 0.0, 0.67, -1.3,
|
||||
0.0, 0.67, -1.3, 0.0, 0.67, -1.3]
|
||||
|
||||
self.targetPos_3 = [-0.35, 1.36, -2.65, 0.35, 1.36, -2.65,
|
||||
-0.5, 1.36, -2.65, 0.5, 1.36, -2.65]
|
||||
|
||||
self.startPos = [0.0] * 12
|
||||
self.duration_1 = 500
|
||||
self.duration_2 = 500
|
||||
self.duration_3 = 2000
|
||||
self.duration_4 = 900
|
||||
self.percent_1 = 0
|
||||
self.percent_2 = 0
|
||||
self.percent_3 = 0
|
||||
self.percent_4 = 0
|
||||
|
||||
self.firstRun = True
|
||||
self.done = False
|
||||
|
||||
# thread handling
|
||||
self.lowCmdWriteThreadPtr = None
|
||||
|
||||
self.crc = CRC()
|
||||
|
||||
# Public methods
|
||||
def Init(self):
|
||||
self.InitLowCmd()
|
||||
|
||||
# create publisher #
|
||||
self.lowcmd_publisher = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateMessageHandler, 10)
|
||||
|
||||
self.sc = SportClient()
|
||||
self.sc.SetTimeout(5.0)
|
||||
self.sc.Init()
|
||||
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.sc.StandUp()
|
||||
self.sc.StandDown()
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
name="writebasiccmd", interval=0.002, target=self.LowCmdWrite,
|
||||
)
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def InitLowCmd(self):
|
||||
self.low_cmd.head[0] = 0xFE
|
||||
self.low_cmd.head[1] = 0xEF
|
||||
self.low_cmd.level_flag = 0xFF
|
||||
self.low_cmd.gpio = 0
|
||||
for i in range(20):
|
||||
self.low_cmd.motor_cmd[i].mode = 0x01
|
||||
self.low_cmd.motor_cmd[i].q= go2w.PosStopF
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = go2w.VelStopF
|
||||
self.low_cmd.motor_cmd[i].kd = 0
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
def LowStateMessageHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
def LowCmdWrite(self):
|
||||
if self.firstRun:
|
||||
for i in range(12):
|
||||
self.startPos[i] = self.low_state.motor_state[i].q
|
||||
self.firstRun = False
|
||||
|
||||
self.percent_1 += 1.0 / self.duration_1
|
||||
self.percent_1 = min(self.percent_1, 1)
|
||||
if self.percent_1 < 1:
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_1) * self.startPos[i] + self.percent_1 * self.targetPos_1[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 <= 1):
|
||||
self.percent_2 += 1.0 / self.duration_2
|
||||
self.percent_2 = min(self.percent_2, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_2) * self.targetPos_1[i] + self.percent_2 * self.targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 < 1):
|
||||
self.percent_3 += 1.0 / self.duration_3
|
||||
self.percent_3 = min(self.percent_3, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = self.targetPos_2[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if self.percent_3 < 0.4:
|
||||
for i in range(12, 16):
|
||||
self.low_cmd.motor_cmd[i].q = 0
|
||||
self.low_cmd.motor_cmd[i].kp = 0.0
|
||||
self.low_cmd.motor_cmd[i].dq = 3
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if 0.4 <= self.percent_3 < 0.8:
|
||||
for i in range(12, 16):
|
||||
self.low_cmd.motor_cmd[i].q = 0
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = -3
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if self.percent_3 >= 0.8:
|
||||
for i in range(12, 16):
|
||||
self.low_cmd.motor_cmd[i].q = 0
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
if (self.percent_1 == 1) and (self.percent_2 == 1) and (self.percent_3 == 1) and (self.percent_4 <= 1):
|
||||
self.percent_4 += 1.0 / self.duration_4
|
||||
self.percent_4 = min(self.percent_4, 1)
|
||||
for i in range(12):
|
||||
self.low_cmd.motor_cmd[i].q = (1 - self.percent_4) * self.targetPos_2[i] + self.percent_4 * self.targetPos_3[i]
|
||||
self.low_cmd.motor_cmd[i].dq = 0
|
||||
self.low_cmd.motor_cmd[i].kp = self.Kp
|
||||
self.low_cmd.motor_cmd[i].kd = self.Kd
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
if custom.percent_4 == 1.0:
|
||||
time.sleep(1)
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
time.sleep(1)
|
||||
24
vendor/unitree_sdk2_python/example/go2w/low_level/unitree_legged_const.py
vendored
Normal file
24
vendor/unitree_sdk2_python/example/go2w/low_level/unitree_legged_const.py
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
LegID = {
|
||||
"FR_0": 0, # Front right hip
|
||||
"FR_1": 1, # Front right thigh
|
||||
"FR_2": 2, # Front right calf
|
||||
"FL_0": 3,
|
||||
"FL_1": 4,
|
||||
"FL_2": 5,
|
||||
"RR_0": 6,
|
||||
"RR_1": 7,
|
||||
"RR_2": 8,
|
||||
"RL_0": 9,
|
||||
"RL_1": 10,
|
||||
"RL_2": 11,
|
||||
"FR_w": 12, # Front right wheel
|
||||
"FL_w": 13, # Front left wheel
|
||||
"RR_w": 14, # Rear right wheel
|
||||
"RL_w": 15, # Rear left wheel
|
||||
}
|
||||
|
||||
HIGHLEVEL = 0xEE
|
||||
LOWLEVEL = 0xFF
|
||||
TRIGERLEVEL = 0xF0
|
||||
PosStopF = 2.146e9
|
||||
VelStopF = 16000.0
|
||||
96
vendor/unitree_sdk2_python/example/h1/high_level/h1_loco_client_example.py
vendored
Normal file
96
vendor/unitree_sdk2_python/example/h1/high_level/h1_loco_client_example.py
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
import time
|
||||
import sys
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__SportModeState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import SportModeState_
|
||||
from unitree_sdk2py.h1.loco.h1_loco_client import LocoClient
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="stand_up", id=1),
|
||||
TestOption(name="move forward", id=3),
|
||||
TestOption(name="move lateral", id=4),
|
||||
TestOption(name="move rotate", id=5),
|
||||
TestOption(name="low stand", id=6),
|
||||
TestOption(name="high stand", id=7),
|
||||
TestOption(name="zero torque", id=8)
|
||||
]
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = LocoClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
while True:
|
||||
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}\n")
|
||||
|
||||
if test_option.id == 0:
|
||||
sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
sport_client.StandUp()
|
||||
elif test_option.id == 3:
|
||||
sport_client.Move(0.3,0,0)
|
||||
elif test_option.id == 4:
|
||||
sport_client.Move(0,0.3,0)
|
||||
elif test_option.id == 5:
|
||||
sport_client.Move(0,0,0.3)
|
||||
elif test_option.id == 6:
|
||||
sport_client.LowStand()
|
||||
elif test_option.id == 7:
|
||||
sport_client.HighStand()
|
||||
elif test_option.id == 8:
|
||||
sport_client.ZeroTorque()
|
||||
|
||||
time.sleep(1)
|
||||
167
vendor/unitree_sdk2_python/example/h1/low_level/h1_low_level_example.py
vendored
Normal file
167
vendor/unitree_sdk2_python/example/h1/low_level/h1_low_level_example.py
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
import unitree_legged_const as h1
|
||||
import numpy as np
|
||||
|
||||
H1_NUM_MOTOR = 20
|
||||
|
||||
class H1JointIndex:
|
||||
# Right leg
|
||||
kRightHipYaw = 8
|
||||
kRightHipRoll = 0
|
||||
kRightHipPitch = 1
|
||||
kRightKnee = 2
|
||||
kRightAnkle = 11
|
||||
# Left leg
|
||||
kLeftHipYaw = 7
|
||||
kLeftHipRoll = 3
|
||||
kLeftHipPitch = 4
|
||||
kLeftKnee = 5
|
||||
kLeftAnkle = 10
|
||||
|
||||
kWaistYaw = 6
|
||||
|
||||
kNotUsedJoint = 9
|
||||
|
||||
# Right arm
|
||||
kRightShoulderPitch = 12
|
||||
kRightShoulderRoll = 13
|
||||
kRightShoulderYaw = 14
|
||||
kRightElbow = 15
|
||||
# Left arm
|
||||
kLeftShoulderPitch = 16
|
||||
kLeftShoulderRoll = 17
|
||||
kLeftShoulderYaw = 18
|
||||
kLeftElbow = 19
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.01
|
||||
self.duration_ = 10.0
|
||||
self.counter_ = 0
|
||||
self.kp_low_ = 60.0
|
||||
self.kp_high_ = 200.0
|
||||
self.kd_low_ = 1.5
|
||||
self.kd_high_ = 5.0
|
||||
self.low_cmd = unitree_go_msg_dds__LowCmd_()
|
||||
self.InitLowCmd()
|
||||
self.low_state = None
|
||||
self.crc = CRC()
|
||||
|
||||
def Init(self):
|
||||
# # create publisher #
|
||||
self.lowcmd_publisher_ = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher_.Init()
|
||||
|
||||
# # create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateHandler, 10)
|
||||
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
self.report_rpy_ptr_ = RecurrentThread(
|
||||
interval=0.1, target=self.ReportRPY, name="report_rpy"
|
||||
)
|
||||
|
||||
self.report_rpy_ptr_.Start()
|
||||
|
||||
def is_weak_motor(self,motor_index):
|
||||
return motor_index in {
|
||||
H1JointIndex.kLeftAnkle,
|
||||
H1JointIndex.kRightAnkle,
|
||||
H1JointIndex.kRightShoulderPitch,
|
||||
H1JointIndex.kRightShoulderRoll,
|
||||
H1JointIndex.kRightShoulderYaw,
|
||||
H1JointIndex.kRightElbow,
|
||||
H1JointIndex.kLeftShoulderPitch,
|
||||
H1JointIndex.kLeftShoulderRoll,
|
||||
H1JointIndex.kLeftShoulderYaw,
|
||||
H1JointIndex.kLeftElbow,
|
||||
}
|
||||
|
||||
def InitLowCmd(self):
|
||||
self.low_cmd.head[0] = 0xFE
|
||||
self.low_cmd.head[1] = 0xEF
|
||||
self.low_cmd.level_flag = 0xFF
|
||||
self.low_cmd.gpio = 0
|
||||
for i in range(H1_NUM_MOTOR):
|
||||
if self.is_weak_motor(i):
|
||||
self.low_cmd.motor_cmd[i].mode = 0x01
|
||||
else:
|
||||
self.low_cmd.motor_cmd[i].mode = 0x0A
|
||||
self.low_cmd.motor_cmd[i].q= h1.PosStopF
|
||||
self.low_cmd.motor_cmd[i].kp = 0
|
||||
self.low_cmd.motor_cmd[i].dq = h1.VelStopF
|
||||
self.low_cmd.motor_cmd[i].kd = 0
|
||||
self.low_cmd.motor_cmd[i].tau = 0
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
def ReportRPY(self):
|
||||
print("rpy: [",self.low_state.imu_state.rpy[0],", "
|
||||
,self.low_state.imu_state.rpy[1],", "
|
||||
,self.low_state.imu_state.rpy[2],"]"
|
||||
)
|
||||
|
||||
def LowCmdWrite(self):
|
||||
self.time_ += self.control_dt_
|
||||
self.time_ = np.clip(self.time_ , 0.0, self.duration_)
|
||||
|
||||
# set robot to zero posture
|
||||
for i in range(H1_NUM_MOTOR):
|
||||
ratio = self.time_ / self.duration_
|
||||
self.low_cmd.motor_cmd[i].tau = 0.
|
||||
self.low_cmd.motor_cmd[i].q = (1.0 - ratio) * self.low_state.motor_state[i].q
|
||||
self.low_cmd.motor_cmd[i].dq = 0.
|
||||
self.low_cmd.motor_cmd[i].kp = self.kp_low_ if self.is_weak_motor(i) else self.kp_high_
|
||||
self.low_cmd.motor_cmd[i].kd = self.kd_low_ if self.is_weak_motor(i) else self.kd_high_
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher_.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
if custom.time_ == custom.duration_:
|
||||
time.sleep(1)
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
time.sleep(1)
|
||||
5
vendor/unitree_sdk2_python/example/h1/low_level/unitree_legged_const.py
vendored
Normal file
5
vendor/unitree_sdk2_python/example/h1/low_level/unitree_legged_const.py
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
HIGHLEVEL = 0xEE
|
||||
LOWLEVEL = 0xFF
|
||||
TRIGERLEVEL = 0xF0
|
||||
PosStopF = 2.146e9
|
||||
VelStopF = 16000.0
|
||||
201
vendor/unitree_sdk2_python/example/h1_2/low_level/h1_2_low_level_example.py
vendored
Normal file
201
vendor/unitree_sdk2_python/example/h1_2/low_level/h1_2_low_level_example.py
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
|
||||
import numpy as np
|
||||
|
||||
H1_2_NUM_MOTOR = 27
|
||||
|
||||
class H1_2_JointIndex:
|
||||
# legs
|
||||
LeftHipYaw = 0
|
||||
LeftHipPitch = 1
|
||||
LeftHipRoll = 2
|
||||
LeftKnee = 3
|
||||
LeftAnklePitch = 4
|
||||
LeftAnkleB = 4
|
||||
LeftAnkleRoll = 5
|
||||
LeftAnkleA = 5
|
||||
RightHipYaw = 6
|
||||
RightHipPitch = 7
|
||||
RightHipRoll = 8
|
||||
RightKnee = 9
|
||||
RightAnklePitch = 10
|
||||
RightAnkleB = 10
|
||||
RightAnkleRoll = 11
|
||||
RightAnkleA = 11
|
||||
# torso
|
||||
WaistYaw = 12
|
||||
# arms
|
||||
LeftShoulderPitch = 13
|
||||
LeftShoulderRoll = 14
|
||||
LeftShoulderYaw = 15
|
||||
LeftElbow = 16
|
||||
LeftWristRoll = 17
|
||||
LeftWristPitch = 18
|
||||
LeftWristYaw = 19
|
||||
RightShoulderPitch = 20
|
||||
RightShoulderRoll = 21
|
||||
RightShoulderYaw = 22
|
||||
RightElbow = 23
|
||||
RightWristRoll = 24
|
||||
RightWristPitch = 25
|
||||
RightWristYaw = 26
|
||||
|
||||
|
||||
class Mode:
|
||||
PR = 0 # Series Control for Pitch/Roll Joints
|
||||
AB = 1 # Parallel Control for A/B Joints
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.002 # [2ms]
|
||||
self.duration_ = 3.0 # [3 s]
|
||||
self.counter_ = 0
|
||||
self.mode_pr_ = Mode.PR
|
||||
self.mode_machine_ = 0
|
||||
self.low_cmd = unitree_hg_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
self.update_mode_machine_ = False
|
||||
self.crc = CRC()
|
||||
|
||||
def Init(self):
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result['name']:
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
# create publisher #
|
||||
self.lowcmd_publisher_ = ChannelPublisher("rt/lowcmd", LowCmd_)
|
||||
self.lowcmd_publisher_.Init()
|
||||
|
||||
# create subscriber #
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateHandler, 10)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
while self.update_mode_machine_ == False:
|
||||
time.sleep(1)
|
||||
|
||||
if self.update_mode_machine_ == True:
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
if self.update_mode_machine_ == False:
|
||||
self.mode_machine_ = self.low_state.mode_machine
|
||||
self.update_mode_machine_ = True
|
||||
|
||||
self.counter_ +=1
|
||||
if (self.counter_ % 500 == 0) :
|
||||
self.counter_ = 0
|
||||
print(self.low_state.imu_state.rpy)
|
||||
|
||||
def LowCmdWrite(self):
|
||||
self.time_ += self.control_dt_
|
||||
self.low_cmd.mode_pr = Mode.PR
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
for i in range(H1_2_NUM_MOTOR):
|
||||
ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[i].mode = 1 # 1:Enable, 0:Disable
|
||||
self.low_cmd.motor_cmd[i].tau = 0.0
|
||||
self.low_cmd.motor_cmd[i].q = 0.0
|
||||
self.low_cmd.motor_cmd[i].dq = 0.0
|
||||
self.low_cmd.motor_cmd[i].kp = 100.0 if i < 13 else 50.0
|
||||
self.low_cmd.motor_cmd[i].kd = 1.0
|
||||
|
||||
if self.time_ < self.duration_ :
|
||||
# [Stage 1]: set robot to zero posture
|
||||
for i in range(H1_2_NUM_MOTOR):
|
||||
ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.mode_pr = Mode.PR
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
self.low_cmd.motor_cmd[i].mode = 1 # 1:Enable, 0:Disable
|
||||
self.low_cmd.motor_cmd[i].tau = 0.
|
||||
self.low_cmd.motor_cmd[i].q = (1.0 - ratio) * self.low_state.motor_state[i].q
|
||||
self.low_cmd.motor_cmd[i].dq = 0.
|
||||
self.low_cmd.motor_cmd[i].kp = 100.0 if i < 13 else 50.0
|
||||
self.low_cmd.motor_cmd[i].kd = 1.0
|
||||
else :
|
||||
# [Stage 2]: swing ankle using PR mode
|
||||
max_P = 0.25
|
||||
max_R = 0.25
|
||||
t = self.time_ - self.duration_
|
||||
L_P_des = max_P * np.cos(2.0 * np.pi * t)
|
||||
L_R_des = max_R * np.sin(2.0 * np.pi * t)
|
||||
R_P_des = max_P * np.cos(2.0 * np.pi * t)
|
||||
R_R_des = -max_R * np.sin(2.0 * np.pi * t)
|
||||
|
||||
Kp_Pitch = 80
|
||||
Kd_Pitch = 1
|
||||
Kp_Roll = 80
|
||||
Kd_Roll = 1
|
||||
|
||||
self.low_cmd.mode_pr = Mode.PR
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnklePitch].q = L_P_des
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnklePitch].dq = 0
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnklePitch].kp = Kp_Pitch
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnklePitch].kd = Kd_Pitch
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnkleRoll].q = L_R_des
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnkleRoll].dq = 0
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnkleRoll].kp = Kp_Roll
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftAnkleRoll].kd = Kd_Roll
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnklePitch].q = R_P_des
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnklePitch].dq = 0
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnklePitch].kp = Kp_Pitch
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnklePitch].kd = Kd_Pitch
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnkleRoll].q = R_R_des
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnkleRoll].dq = 0
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnkleRoll].kp = Kp_Roll
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightAnkleRoll].kd = Kd_Roll
|
||||
|
||||
max_wrist_roll_angle = 0.5; # [rad]
|
||||
WristRoll_des = max_wrist_roll_angle * np.sin(2.0 * np.pi * t)
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftWristRoll].q = WristRoll_des
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftWristRoll].dq = 0
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftWristRoll].kp = 50
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.LeftWristRoll].kd = 1
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightWristRoll].q = WristRoll_des
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightWristRoll].dq = 0
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightWristRoll].kp = 50
|
||||
self.low_cmd.motor_cmd[H1_2_JointIndex.RightWristRoll].kd = 1
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher_.Write(self.low_cmd)
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
198
vendor/unitree_sdk2_python/example/h2/high_level/h2_arm_sdk_dds_example.py
vendored
Normal file
198
vendor/unitree_sdk2_python/example/h2/high_level/h2_arm_sdk_dds_example.py
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize, ChannelPublisher, ChannelSubscriber
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowCmd_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_, LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
|
||||
|
||||
SMALL_SHOULDER_ROLL = np.deg2rad(20.0)
|
||||
SMALL_ELBOW = np.deg2rad(30.0)
|
||||
|
||||
|
||||
class H2JointIndex:
|
||||
# Left leg
|
||||
LeftHipPitch = 0
|
||||
LeftHipRoll = 1
|
||||
LeftHipYaw = 2
|
||||
LeftKnee = 3
|
||||
LeftAnklePitch = 4
|
||||
LeftAnkleB = 4
|
||||
LeftAnkleRoll = 5
|
||||
LeftAnkleA = 5
|
||||
|
||||
# Right leg
|
||||
RightHipPitch = 6
|
||||
RightHipRoll = 7
|
||||
RightHipYaw = 8
|
||||
RightKnee = 9
|
||||
RightAnklePitch = 10
|
||||
RightAnkleB = 10
|
||||
RightAnkleRoll = 11
|
||||
RightAnkleA = 11
|
||||
|
||||
# Waist
|
||||
WaistYaw = 12
|
||||
WaistRoll = 13
|
||||
WaistPitch = 14
|
||||
|
||||
# Left arm
|
||||
LeftShoulderPitch = 15
|
||||
LeftShoulderRoll = 16
|
||||
LeftShoulderYaw = 17
|
||||
LeftElbow = 18
|
||||
LeftWristRoll = 19
|
||||
LeftWristPitch = 20
|
||||
LeftWristYaw = 21
|
||||
|
||||
# Right arm
|
||||
RightShoulderPitch = 22
|
||||
RightShoulderRoll = 23
|
||||
RightShoulderYaw = 24
|
||||
RightElbow = 25
|
||||
RightWristRoll = 26
|
||||
RightWristPitch = 27
|
||||
RightWristYaw = 28
|
||||
|
||||
# Head
|
||||
HeadYaw = 29
|
||||
HeadPitch = 30
|
||||
|
||||
kNotUsedJoint = 31 # NOTE: Weight
|
||||
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.02
|
||||
self.duration_ = 3.0
|
||||
self.kp = 80.0
|
||||
self.kd = 1.5
|
||||
self.low_cmd = unitree_hg_msg_dds__LowCmd_()
|
||||
self.low_state = None
|
||||
self.first_update_low_state = False
|
||||
self.crc = CRC()
|
||||
self.done = False
|
||||
|
||||
self.target_pos = [
|
||||
0.0, SMALL_SHOULDER_ROLL, 0.0, SMALL_ELBOW, 0.0, 0.0, 0.0,
|
||||
0.0, -SMALL_SHOULDER_ROLL, 0.0, SMALL_ELBOW, 0.0, 0.0, 0.0,
|
||||
]
|
||||
|
||||
self.arm_joints = [
|
||||
H2JointIndex.LeftShoulderPitch, H2JointIndex.LeftShoulderRoll,
|
||||
H2JointIndex.LeftShoulderYaw, H2JointIndex.LeftElbow,
|
||||
H2JointIndex.LeftWristRoll, H2JointIndex.LeftWristPitch,
|
||||
H2JointIndex.LeftWristYaw,
|
||||
H2JointIndex.RightShoulderPitch, H2JointIndex.RightShoulderRoll,
|
||||
H2JointIndex.RightShoulderYaw, H2JointIndex.RightElbow,
|
||||
H2JointIndex.RightWristRoll, H2JointIndex.RightWristPitch,
|
||||
H2JointIndex.RightWristYaw,
|
||||
]
|
||||
|
||||
def Init(self):
|
||||
# create publisher
|
||||
self.arm_sdk_publisher = ChannelPublisher("rt/arm_sdk", LowCmd_)
|
||||
self.arm_sdk_publisher.Init()
|
||||
|
||||
# create subscriber
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateHandler, 10)
|
||||
|
||||
def Start(self):
|
||||
self.lowCmdWriteThreadPtr = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
while not self.first_update_low_state:
|
||||
time.sleep(1)
|
||||
|
||||
self.lowCmdWriteThreadPtr.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
|
||||
if not self.first_update_low_state:
|
||||
self.first_update_low_state = True
|
||||
|
||||
def LowCmdWrite(self):
|
||||
if self.low_state is None:
|
||||
return
|
||||
|
||||
self.time_ += self.control_dt_
|
||||
|
||||
if self.time_ < self.duration_:
|
||||
print("[Stage 1]: set arms to zero posture.")
|
||||
# [Stage 1]: set arms to zero posture
|
||||
self.low_cmd.motor_cmd[H2JointIndex.kNotUsedJoint].q = 1.0
|
||||
|
||||
for i, joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip(self.time_ / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.0
|
||||
self.low_cmd.motor_cmd[joint].q = (
|
||||
(1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
)
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.0
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 3:
|
||||
print("[Stage 2]: lift arms up.")
|
||||
# [Stage 2]: lift arms up
|
||||
for i, joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_) / (self.duration_ * 2), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.0
|
||||
self.low_cmd.motor_cmd[joint].q = (
|
||||
ratio * self.target_pos[i] + (1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
)
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.0
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 6:
|
||||
print("[Stage 3]: set arms back to zero posture.")
|
||||
# [Stage 3]: set arms back to zero posture
|
||||
for i, joint in enumerate(self.arm_joints):
|
||||
ratio = np.clip((self.time_ - self.duration_ * 3) / (self.duration_ * 3), 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[joint].tau = 0.0
|
||||
self.low_cmd.motor_cmd[joint].q = (
|
||||
(1.0 - ratio) * self.low_state.motor_state[joint].q
|
||||
)
|
||||
self.low_cmd.motor_cmd[joint].dq = 0.0
|
||||
self.low_cmd.motor_cmd[joint].kp = self.kp
|
||||
self.low_cmd.motor_cmd[joint].kd = self.kd
|
||||
|
||||
elif self.time_ < self.duration_ * 7:
|
||||
print("[Stage 4]: release arm_sdk.")
|
||||
# [Stage 4]: release arm_sdk
|
||||
ratio = np.clip((self.time_ - self.duration_ * 6) / self.duration_, 0.0, 1.0)
|
||||
self.low_cmd.motor_cmd[H2JointIndex.kNotUsedJoint].q = 1.0 - ratio
|
||||
|
||||
else:
|
||||
self.done = True
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.arm_sdk_publisher.Write(self.low_cmd)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
if custom.done:
|
||||
print("Done!")
|
||||
sys.exit(-1)
|
||||
111
vendor/unitree_sdk2_python/example/h2/high_level/h2_loco_client_example.py
vendored
Normal file
111
vendor/unitree_sdk2_python/example/h2/high_level/h2_loco_client_example.py
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
import sys
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.h2.loco.h2_loco_client import LocoClient
|
||||
|
||||
|
||||
@dataclass
|
||||
class TestOption:
|
||||
name: str
|
||||
id: int
|
||||
|
||||
|
||||
option_list = [
|
||||
TestOption(name="damp", id=0),
|
||||
TestOption(name="start", id=1),
|
||||
TestOption(name="stand_up", id=2),
|
||||
TestOption(name="zero_torque", id=3),
|
||||
TestOption(name="stop_move", id=4),
|
||||
TestOption(name="get_fsm_id", id=5),
|
||||
TestOption(name="get_fsm_mode", id=6),
|
||||
TestOption(name="set_fsm_id", id=7),
|
||||
TestOption(name="set_velocity", id=8),
|
||||
TestOption(name="move", id=9),
|
||||
TestOption(name="switch_move_mode", id=10),
|
||||
TestOption(name="set_speed_mode", id=11),
|
||||
]
|
||||
|
||||
|
||||
class UserInterface:
|
||||
def __init__(self):
|
||||
self.test_option_ = None
|
||||
|
||||
def convert_to_int(self, input_str):
|
||||
try:
|
||||
return int(input_str)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def terminal_handle(self):
|
||||
input_str = input("Enter id or name: \n")
|
||||
|
||||
if input_str == "list":
|
||||
self.test_option_.name = None
|
||||
self.test_option_.id = None
|
||||
for option in option_list:
|
||||
print(f"{option.name}, id: {option.id}")
|
||||
return
|
||||
|
||||
for option in option_list:
|
||||
if input_str == option.name or self.convert_to_int(input_str) == option.id:
|
||||
self.test_option_.name = option.name
|
||||
self.test_option_.id = option.id
|
||||
print(f"Test: {self.test_option_.name}, test_id: {self.test_option_.id}")
|
||||
return
|
||||
|
||||
print("No matching test option found.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
test_option = TestOption(name=None, id=None)
|
||||
user_interface = UserInterface()
|
||||
user_interface.test_option_ = test_option
|
||||
|
||||
sport_client = LocoClient()
|
||||
sport_client.SetTimeout(10.0)
|
||||
sport_client.Init()
|
||||
|
||||
print("Input \"list\" to list all test option ...")
|
||||
while True:
|
||||
user_interface.terminal_handle()
|
||||
|
||||
print(f"Updated Test Option: Name = {test_option.name}, ID = {test_option.id}\n")
|
||||
|
||||
if test_option.id == 0:
|
||||
sport_client.Damp()
|
||||
elif test_option.id == 1:
|
||||
sport_client.Start()
|
||||
elif test_option.id == 2:
|
||||
sport_client.StandUp()
|
||||
elif test_option.id == 3:
|
||||
sport_client.ZeroTorque()
|
||||
elif test_option.id == 4:
|
||||
sport_client.StopMove()
|
||||
elif test_option.id == 5:
|
||||
code, fsm_id = sport_client.GetFsmId()
|
||||
print("GetFsmId:", code, fsm_id)
|
||||
elif test_option.id == 6:
|
||||
code, fsm_mode = sport_client.GetFsmMode()
|
||||
print("GetFsmMode:", code, fsm_mode)
|
||||
elif test_option.id == 7:
|
||||
sport_client.SetFsmId(4)
|
||||
elif test_option.id == 8:
|
||||
sport_client.SetVelocity(0.0, 0.0, 1.0, 4.0)
|
||||
elif test_option.id == 9:
|
||||
sport_client.Move(0.0, 0.0, 2)
|
||||
elif test_option.id == 10:
|
||||
sport_client.SwitchMoveMode(True)
|
||||
elif test_option.id == 11:
|
||||
sport_client.SetSpeedMode(1)
|
||||
|
||||
time.sleep(1)
|
||||
206
vendor/unitree_sdk2_python/example/h2/low_level/h2_ankle_swing_example.py
vendored
Normal file
206
vendor/unitree_sdk2_python/example/h2/low_level/h2_ankle_swing_example.py
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize, ChannelPublisher, ChannelSubscriber
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowCmd_, LowState_
|
||||
from unitree_sdk2py.utils.crc import CRC
|
||||
from unitree_sdk2py.utils.thread import RecurrentThread
|
||||
|
||||
|
||||
H2_NUM_MOTOR = 31
|
||||
HG_CMD_TOPIC = "rt/lowcmd"
|
||||
HG_STATE_TOPIC = "rt/lowstate"
|
||||
|
||||
Kp = [
|
||||
200, 200, 200, 200, 200, 200, # legs
|
||||
200, 200, 200, 200, 200, 200, # legs
|
||||
300, 300, 300, # waist
|
||||
100, 100, 100, 100, 50, 50, 50, # arms
|
||||
100, 100, 100, 100, 50, 50, 50, # arms
|
||||
50, 10 # head
|
||||
]
|
||||
|
||||
Kd = [
|
||||
3, 3, 3, 3, 3, 3, # legs
|
||||
3, 3, 3, 3, 3, 3, # legs
|
||||
5, 5, 5, # waist
|
||||
2, 2, 2, 2, 2, 2, 2, # arms
|
||||
2, 2, 2, 2, 2, 2, 2, # arms
|
||||
2, 0.1 # head
|
||||
]
|
||||
|
||||
joint_idx_in_idl = [
|
||||
0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 10, 11,
|
||||
12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21,
|
||||
22, 23, 24, 25, 26, 27, 28,
|
||||
29, 30
|
||||
]
|
||||
|
||||
|
||||
class Mode:
|
||||
PR = 0
|
||||
AB = 1
|
||||
|
||||
|
||||
class H2JointIndex:
|
||||
LeftHipPitch = 0
|
||||
LeftHipRoll = 1
|
||||
LeftHipYaw = 2
|
||||
LeftKnee = 3
|
||||
LeftAnkleRoll = 4
|
||||
LeftAnkleRollRaw = 4
|
||||
LeftAnklePitch = 5
|
||||
LeftAnklePitchRaw = 5
|
||||
RightHipPitch = 6
|
||||
RightHipRoll = 7
|
||||
RightHipYaw = 8
|
||||
RightKnee = 9
|
||||
RightAnkleRoll = 10
|
||||
RightAnkleRollRaw = 10
|
||||
RightAnklePitch = 11
|
||||
RightAnklePitchRaw = 11
|
||||
WaistYaw = 12
|
||||
WaistRoll = 13
|
||||
WaistA = 13
|
||||
WaistPitch = 14
|
||||
WaistB = 14
|
||||
LeftShoulderPitch = 15
|
||||
LeftShoulderRoll = 16
|
||||
LeftShoulderYaw = 17
|
||||
LeftElbow = 18
|
||||
LeftWristRoll = 19
|
||||
LeftWristpitch = 20
|
||||
LeftWristyaw = 21
|
||||
RightShoulderPitch = 22
|
||||
RightShoulderRoll = 23
|
||||
RightShoulderYaw = 24
|
||||
RightElbow = 25
|
||||
RightWristRoll = 26
|
||||
RightWristpitch = 27
|
||||
RightWristyaw = 28
|
||||
HEAD_PITCH = 29
|
||||
HEAD_YAW = 30
|
||||
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.time_ = 0.0
|
||||
self.control_dt_ = 0.002
|
||||
self.duration_ = 3.0
|
||||
self.mode_pr_ = Mode.PR
|
||||
self.mode_machine_ = 0
|
||||
self.update_mode_machine_ = False
|
||||
|
||||
self.low_cmd = LowCmd_()
|
||||
self.low_state = None
|
||||
self.crc = CRC()
|
||||
|
||||
def Init(self):
|
||||
# try to shutdown motion control-related service
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
status, result = self.msc.CheckMode()
|
||||
while result.get("name"):
|
||||
self.msc.ReleaseMode()
|
||||
status, result = self.msc.CheckMode()
|
||||
time.sleep(1)
|
||||
|
||||
self.lowcmd_publisher_ = ChannelPublisher(HG_CMD_TOPIC, LowCmd_)
|
||||
self.lowcmd_publisher_.Init()
|
||||
|
||||
self.lowstate_subscriber_ = ChannelSubscriber(HG_STATE_TOPIC, LowState_)
|
||||
self.lowstate_subscriber_.Init(self.LowStateHandler, 10)
|
||||
|
||||
def Start(self):
|
||||
self.control_thread_ = RecurrentThread(
|
||||
interval=self.control_dt_, target=self.LowCmdWrite, name="control"
|
||||
)
|
||||
while not self.update_mode_machine_:
|
||||
time.sleep(0.1)
|
||||
self.control_thread_.Start()
|
||||
|
||||
def LowStateHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
if not self.update_mode_machine_:
|
||||
self.mode_machine_ = self.low_state.mode_machine
|
||||
self.update_mode_machine_ = True
|
||||
|
||||
def LowCmdWrite(self):
|
||||
if self.low_state is None:
|
||||
return
|
||||
|
||||
self.time_ += self.control_dt_
|
||||
|
||||
# base fill for all joints we care about
|
||||
self.low_cmd.mode_pr = self.mode_pr_
|
||||
self.low_cmd.mode_machine = self.mode_machine_
|
||||
|
||||
for i in range(H2_NUM_MOTOR):
|
||||
slot = joint_idx_in_idl[i]
|
||||
self.low_cmd.motor_cmd[slot].mode = 1
|
||||
self.low_cmd.motor_cmd[slot].tau = 0.0
|
||||
self.low_cmd.motor_cmd[slot].dq = 0.0
|
||||
self.low_cmd.motor_cmd[slot].kp = Kp[i]
|
||||
self.low_cmd.motor_cmd[slot].kd = Kd[i]
|
||||
|
||||
if self.time_ < self.duration_:
|
||||
ratio = float(np.clip(self.time_ / self.duration_, 0.0, 1.0))
|
||||
for i in range(H2_NUM_MOTOR):
|
||||
slot = joint_idx_in_idl[i]
|
||||
self.low_cmd.motor_cmd[slot].q = (1.0 - ratio) * self.low_state.motor_state[slot].q
|
||||
elif self.time_ < self.duration_ * 2.0:
|
||||
self.mode_pr_ = Mode.PR
|
||||
self.low_cmd.mode_pr = self.mode_pr_
|
||||
max_P = np.pi * 30.0 / 180.0
|
||||
max_R = np.pi * 30.0 / 180.0
|
||||
t = self.time_ - self.duration_
|
||||
L_P_des = max_P * np.sin(2.0 * np.pi * t)
|
||||
L_R_des = max_R * np.sin(2.0 * np.pi * t)
|
||||
R_P_des = max_P * np.sin(2.0 * np.pi * t)
|
||||
R_R_des = -max_R * np.sin(2.0 * np.pi * t)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.LeftAnklePitch]].q = float(L_P_des)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.LeftAnkleRoll]].q = float(L_R_des)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.RightAnklePitch]].q = float(R_P_des)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.RightAnkleRoll]].q = float(R_R_des)
|
||||
else:
|
||||
self.mode_pr_ = Mode.AB
|
||||
self.low_cmd.mode_pr = self.mode_pr_
|
||||
max_A = np.pi * 30.0 / 180.0
|
||||
max_B = np.pi * 10.0 / 180.0
|
||||
t = self.time_ - self.duration_ * 2.0
|
||||
L_A_des = +max_A * np.sin(np.pi * t)
|
||||
L_B_des = +max_B * np.sin(np.pi * t + np.pi)
|
||||
R_A_des = -max_A * np.sin(np.pi * t)
|
||||
R_B_des = -max_B * np.sin(np.pi * t + np.pi)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.LeftAnklePitchRaw]].q = float(L_A_des)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.LeftAnkleRollRaw]].q = float(L_B_des)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.RightAnklePitchRaw]].q = float(R_A_des)
|
||||
self.low_cmd.motor_cmd[joint_idx_in_idl[H2JointIndex.RightAnkleRollRaw]].q = float(R_B_des)
|
||||
|
||||
self.low_cmd.crc = self.crc.Crc(self.low_cmd)
|
||||
self.lowcmd_publisher_.Write(self.low_cmd)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
custom.Start()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
|
||||
28
vendor/unitree_sdk2_python/example/helloworld/publisher.py
vendored
Normal file
28
vendor/unitree_sdk2_python/example/helloworld/publisher.py
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
import time
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelPublisher, ChannelFactoryInitialize
|
||||
from user_data import *
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ChannelFactoryInitialize()
|
||||
|
||||
# Create a publisher to publish the data defined in UserData class
|
||||
pub = ChannelPublisher("topic", UserData)
|
||||
pub.Init()
|
||||
|
||||
for i in range(30):
|
||||
# Create a Userdata message
|
||||
msg = UserData(" ", 0)
|
||||
msg.string_data = "Hello world"
|
||||
msg.float_data = time.time()
|
||||
|
||||
# Publish message
|
||||
if pub.Write(msg, 0.5):
|
||||
print("Publish success. msg:", msg)
|
||||
else:
|
||||
print("Waitting for subscriber.")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
pub.Close()
|
||||
20
vendor/unitree_sdk2_python/example/helloworld/subscriber.py
vendored
Normal file
20
vendor/unitree_sdk2_python/example/helloworld/subscriber.py
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import time
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
from user_data import *
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ChannelFactoryInitialize()
|
||||
# Create a subscriber to subscribe the data defined in UserData class
|
||||
sub = ChannelSubscriber("topic", UserData)
|
||||
sub.Init()
|
||||
|
||||
while True:
|
||||
msg = sub.Read()
|
||||
if msg is not None:
|
||||
print("Subscribe success. msg:", msg)
|
||||
else:
|
||||
print("No data subscribed.")
|
||||
break
|
||||
sub.Close()
|
||||
9
vendor/unitree_sdk2_python/example/helloworld/user_data.py
vendored
Normal file
9
vendor/unitree_sdk2_python/example/helloworld/user_data.py
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
from dataclasses import dataclass
|
||||
from cyclonedds.idl import IdlStruct
|
||||
|
||||
|
||||
# This class defines user data consisting of a float data and a string data
|
||||
@dataclass
|
||||
class UserData(IdlStruct, typename="UserData"):
|
||||
string_data: str
|
||||
float_data: float
|
||||
36
vendor/unitree_sdk2_python/example/motionSwitcher/motion_switcher_example.py
vendored
Normal file
36
vendor/unitree_sdk2_python/example/motionSwitcher/motion_switcher_example.py
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.comm.motion_switcher.motion_switcher_client import MotionSwitcherClient
|
||||
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.msc = MotionSwitcherClient()
|
||||
self.msc.SetTimeout(5.0)
|
||||
self.msc.Init()
|
||||
|
||||
def selectMode(self,name):
|
||||
ret = self.msc.SelectMode(name)
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
selectMode = "ai"
|
||||
# selectMode = "normal"
|
||||
# selectMode = "advanced"
|
||||
# selectMode = "ai-w" # for wheeled robot
|
||||
ret = custom.selectMode(selectMode)
|
||||
print("ret: ",ret)
|
||||
|
||||
38
vendor/unitree_sdk2_python/example/obstacles_avoid/obstacles_avoid_move.py
vendored
Normal file
38
vendor/unitree_sdk2_python/example/obstacles_avoid/obstacles_avoid_move.py
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.go2.obstacles_avoid.obstacles_avoid_client import ObstaclesAvoidClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
try:
|
||||
client = ObstaclesAvoidClient()
|
||||
client.SetTimeout(3.0)
|
||||
client.Init()
|
||||
|
||||
while not client.SwitchGet()[1]:
|
||||
client.SwitchSet(True)
|
||||
time.sleep(0.1)
|
||||
|
||||
print("obstacles avoid switch on")
|
||||
|
||||
client.UseRemoteCommandFromApi(True)
|
||||
time.sleep(0.5)
|
||||
client.Move(0.5, 0.0, 0.0)
|
||||
time.sleep(1.0) # move 1s
|
||||
client.Move(0.0, 0.0, 0.0)
|
||||
client.UseRemoteCommandFromApi(False)
|
||||
time.sleep(1.0)
|
||||
client.MoveToAbsolutePosition(0.0, 0.0, 0.0)
|
||||
client.MoveToIncrementPosition(0.0, 0.0, 0.0)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
client.Move(0.0, 0.0, 0.0)
|
||||
client.UseRemoteCommandFromApi(False)
|
||||
print("exit!!")
|
||||
|
||||
94
vendor/unitree_sdk2_python/example/obstacles_avoid/obstacles_avoid_switch.py
vendored
Normal file
94
vendor/unitree_sdk2_python/example/obstacles_avoid/obstacles_avoid_switch.py
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.go2.obstacles_avoid.obstacles_avoid_client import ObstaclesAvoidClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
client = ObstaclesAvoidClient()
|
||||
client.SetTimeout(3.0)
|
||||
client.Init()
|
||||
|
||||
while True:
|
||||
print("##################GetServerApiVersion###################")
|
||||
code, serverAPiVersion = client.GetServerApiVersion()
|
||||
if code != 0:
|
||||
print("get server api error. code:", code)
|
||||
else:
|
||||
print("get server api version:", serverAPiVersion)
|
||||
|
||||
if serverAPiVersion != client.GetApiVersion():
|
||||
print("api version not equal.")
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
print("##################SwitchGet###################")
|
||||
code, enable = client.SwitchGet()
|
||||
if code != 0:
|
||||
print("switch get error. code:", code)
|
||||
else:
|
||||
print("switch get success. enable:", enable)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
print("##################SwitchSet (on)###################")
|
||||
code = client.SwitchSet(True)
|
||||
if code != 0:
|
||||
print("switch set error. code:", code)
|
||||
else:
|
||||
print("switch set success.")
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
print("##################SwitchGet###################")
|
||||
code, enable1 = client.SwitchGet()
|
||||
if code != 0:
|
||||
print("switch get error. code:", code)
|
||||
else:
|
||||
print("switch get success. enable:", enable1)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
print("##################SwitchSet (off)###################")
|
||||
code = client.SwitchSet(False)
|
||||
if code != 0:
|
||||
print("switch set error. code:", code)
|
||||
else:
|
||||
print("switch set success.")
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
print("##################SwitchGet###################")
|
||||
code, enable1 = client.SwitchGet()
|
||||
if code != 0:
|
||||
print("switch get error. code:", code)
|
||||
else:
|
||||
print("switch get success. enable:", enable1)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
|
||||
print("##################SwitchSet (enable)###################")
|
||||
|
||||
code = client.SwitchSet(enable)
|
||||
if code != 0:
|
||||
print("switch set error. code:", code)
|
||||
else:
|
||||
print("switch set success. enable:", enable)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
print("##################SwitchGet###################")
|
||||
code, enable = client.SwitchGet()
|
||||
if code != 0:
|
||||
print("switch get error. code:", code)
|
||||
else:
|
||||
print("switch get success. enable:", enable)
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
77
vendor/unitree_sdk2_python/example/vui_client/vui_client_example.py
vendored
Normal file
77
vendor/unitree_sdk2_python/example/vui_client/vui_client_example.py
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelFactoryInitialize
|
||||
from unitree_sdk2py.go2.vui.vui_client import VuiClient
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
client = VuiClient()
|
||||
client.SetTimeout(3.0)
|
||||
client.Init()
|
||||
|
||||
for i in range(1, 11):
|
||||
print("#################GetBrightness####################")
|
||||
code, level = client.GetBrightness()
|
||||
|
||||
if code != 0:
|
||||
print("get brightness error. code:", code)
|
||||
else:
|
||||
print("get brightness success. level:", level)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
print("#################SetBrightness####################")
|
||||
|
||||
code = client.SetBrightness(i)
|
||||
|
||||
if code != 0:
|
||||
print("set brightness error. code:", code)
|
||||
else:
|
||||
print("set brightness success. level:", i)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
print("#################SetBrightness 0####################")
|
||||
|
||||
code = client.SetBrightness(0)
|
||||
|
||||
if code != 0:
|
||||
print("set brightness error. code:", code)
|
||||
else:
|
||||
print("set brightness 0 success.")
|
||||
|
||||
for i in range(1, 11):
|
||||
print("#################GetVolume####################")
|
||||
code, level = client.GetVolume()
|
||||
|
||||
if code != 0:
|
||||
print("get volume error. code:", code)
|
||||
else:
|
||||
print("get volume success. level:", level)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
print("#################SetVolume####################")
|
||||
|
||||
code = client.SetVolume(i)
|
||||
|
||||
if code != 0:
|
||||
print("set volume error. code:", code)
|
||||
else:
|
||||
print("set volume success. level:", i)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
print("#################SetVolume 0####################")
|
||||
|
||||
code = client.SetVolume(0)
|
||||
|
||||
if code != 0:
|
||||
print("set volume error. code:", code)
|
||||
else:
|
||||
print("set volume 0 success.")
|
||||
131
vendor/unitree_sdk2_python/example/wireless_controller/wireless_controller.py
vendored
Normal file
131
vendor/unitree_sdk2_python/example/wireless_controller/wireless_controller.py
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
import time
|
||||
import sys
|
||||
import struct
|
||||
|
||||
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelFactoryInitialize
|
||||
|
||||
# Uncomment the following two lines when using Go2、Go2-W、B2、B2-W、H1 robot
|
||||
# from unitree_sdk2py.idl.default import unitree_go_msg_dds__LowState_
|
||||
# from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowState_
|
||||
|
||||
# Uncomment the following two lines when using G1、H1-2 robot
|
||||
from unitree_sdk2py.idl.default import unitree_hg_msg_dds__LowState_
|
||||
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_
|
||||
|
||||
class unitreeRemoteController:
|
||||
def __init__(self):
|
||||
# key
|
||||
self.Lx = 0
|
||||
self.Rx = 0
|
||||
self.Ry = 0
|
||||
self.Ly = 0
|
||||
|
||||
# button
|
||||
self.L1 = 0
|
||||
self.L2 = 0
|
||||
self.R1 = 0
|
||||
self.R2 = 0
|
||||
self.A = 0
|
||||
self.B = 0
|
||||
self.X = 0
|
||||
self.Y = 0
|
||||
self.Up = 0
|
||||
self.Down = 0
|
||||
self.Left = 0
|
||||
self.Right = 0
|
||||
self.Select = 0
|
||||
self.F1 = 0
|
||||
self.F3 = 0
|
||||
self.Start = 0
|
||||
|
||||
def parse_botton(self,data1,data2):
|
||||
self.R1 = (data1 >> 0) & 1
|
||||
self.L1 = (data1 >> 1) & 1
|
||||
self.Start = (data1 >> 2) & 1
|
||||
self.Select = (data1 >> 3) & 1
|
||||
self.R2 = (data1 >> 4) & 1
|
||||
self.L2 = (data1 >> 5) & 1
|
||||
self.F1 = (data1 >> 6) & 1
|
||||
self.F3 = (data1 >> 7) & 1
|
||||
self.A = (data2 >> 0) & 1
|
||||
self.B = (data2 >> 1) & 1
|
||||
self.X = (data2 >> 2) & 1
|
||||
self.Y = (data2 >> 3) & 1
|
||||
self.Up = (data2 >> 4) & 1
|
||||
self.Right = (data2 >> 5) & 1
|
||||
self.Down = (data2 >> 6) & 1
|
||||
self.Left = (data2 >> 7) & 1
|
||||
|
||||
def parse_key(self,data):
|
||||
lx_offset = 4
|
||||
self.Lx = struct.unpack('<f', data[lx_offset:lx_offset + 4])[0]
|
||||
rx_offset = 8
|
||||
self.Rx = struct.unpack('<f', data[rx_offset:rx_offset + 4])[0]
|
||||
ry_offset = 12
|
||||
self.Ry = struct.unpack('<f', data[ry_offset:ry_offset + 4])[0]
|
||||
L2_offset = 16
|
||||
L2 = struct.unpack('<f', data[L2_offset:L2_offset + 4])[0] # Placeholder,unused
|
||||
ly_offset = 20
|
||||
self.Ly = struct.unpack('<f', data[ly_offset:ly_offset + 4])[0]
|
||||
|
||||
|
||||
def parse(self,remoteData):
|
||||
self.parse_key(remoteData)
|
||||
self.parse_botton(remoteData[2],remoteData[3])
|
||||
|
||||
print("debug unitreeRemoteController: ")
|
||||
print("Lx:", self.Lx)
|
||||
print("Rx:", self.Rx)
|
||||
print("Ry:", self.Ry)
|
||||
print("Ly:", self.Ly)
|
||||
|
||||
print("L1:", self.L1)
|
||||
print("L2:", self.L2)
|
||||
print("R1:", self.R1)
|
||||
print("R2:", self.R2)
|
||||
print("A:", self.A)
|
||||
print("B:", self.B)
|
||||
print("X:", self.X)
|
||||
print("Y:", self.Y)
|
||||
print("Up:", self.Up)
|
||||
print("Down:", self.Down)
|
||||
print("Left:", self.Left)
|
||||
print("Right:", self.Right)
|
||||
print("Select:", self.Select)
|
||||
print("F1:", self.F1)
|
||||
print("F3:", self.F3)
|
||||
print("Start:", self.Start)
|
||||
print("\n")
|
||||
|
||||
|
||||
class Custom:
|
||||
def __init__(self):
|
||||
self.low_state = None
|
||||
self.remoteController = unitreeRemoteController()
|
||||
|
||||
def Init(self):
|
||||
self.lowstate_subscriber = ChannelSubscriber("rt/lf/lowstate", LowState_)
|
||||
self.lowstate_subscriber.Init(self.LowStateMessageHandler, 10)
|
||||
|
||||
|
||||
def LowStateMessageHandler(self, msg: LowState_):
|
||||
self.low_state = msg
|
||||
wireless_remote_data = self.low_state.wireless_remote
|
||||
self.remoteController.parse(wireless_remote_data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
print("WARNING: Please ensure there are no obstacles around the robot while running this example.")
|
||||
input("Press Enter to continue...")
|
||||
|
||||
if len(sys.argv)>1:
|
||||
ChannelFactoryInitialize(0, sys.argv[1])
|
||||
else:
|
||||
ChannelFactoryInitialize(0)
|
||||
|
||||
custom = Custom()
|
||||
custom.Init()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
3
vendor/unitree_sdk2_python/pyproject.toml
vendored
Normal file
3
vendor/unitree_sdk2_python/pyproject.toml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[build-system]
|
||||
requires = ["setuptools", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
21
vendor/unitree_sdk2_python/setup.py
vendored
Normal file
21
vendor/unitree_sdk2_python/setup.py
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(name='unitree_sdk2py',
|
||||
version='1.0.1',
|
||||
author='UnitreeRobotics',
|
||||
author_email='unitree@unitree.com',
|
||||
long_description=open('README.md').read(),
|
||||
long_description_content_type="text/markdown",
|
||||
license="BSD-3-Clause",
|
||||
packages=find_packages(include=['unitree_sdk2py','unitree_sdk2py.*']),
|
||||
description='Unitree robot sdk version 2 for python',
|
||||
project_urls={
|
||||
"Source Code": "https://github.com/unitreerobotics/unitree_sdk2_python",
|
||||
},
|
||||
python_requires='>=3.8',
|
||||
install_requires=[
|
||||
"cyclonedds==0.10.2",
|
||||
"numpy",
|
||||
"opencv-python",
|
||||
],
|
||||
)
|
||||
15
vendor/unitree_sdk2_python/unitree_sdk2py/__init__.py
vendored
Normal file
15
vendor/unitree_sdk2_python/unitree_sdk2py/__init__.py
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
from . import idl, utils, core, rpc, comm, go2, b2, g1, h1, h2, a2
|
||||
|
||||
__all__ = [
|
||||
"idl",
|
||||
"utils",
|
||||
"core",
|
||||
"rpc",
|
||||
"comm",
|
||||
"go2",
|
||||
"b2",
|
||||
"g1",
|
||||
"h1",
|
||||
"h2",
|
||||
"a2",
|
||||
]
|
||||
1
vendor/unitree_sdk2_python/unitree_sdk2py/a2/__init__.py
vendored
Normal file
1
vendor/unitree_sdk2_python/unitree_sdk2py/a2/__init__.py
vendored
Normal file
@ -0,0 +1 @@
|
||||
|
||||
0
vendor/unitree_sdk2_python/unitree_sdk2py/a2/audio/__init__.py
vendored
Normal file
0
vendor/unitree_sdk2_python/unitree_sdk2py/a2/audio/__init__.py
vendored
Normal file
26
vendor/unitree_sdk2_python/unitree_sdk2py/a2/audio/audio_api.py
vendored
Normal file
26
vendor/unitree_sdk2_python/unitree_sdk2py/a2/audio/audio_api.py
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
"""
|
||||
" service name
|
||||
"""
|
||||
AUDIO_SERVICE_NAME = "voice"
|
||||
|
||||
"""
|
||||
" service api version
|
||||
"""
|
||||
AUDIO_API_VERSION = "1.0.0.0"
|
||||
|
||||
"""
|
||||
" api id
|
||||
"""
|
||||
ROBOT_API_ID_AUDIO_TTS = 1001
|
||||
ROBOT_API_ID_AUDIO_ASR = 1002
|
||||
ROBOT_API_ID_AUDIO_START_PLAY = 1003
|
||||
ROBOT_API_ID_AUDIO_STOP_PLAY = 1004
|
||||
ROBOT_API_ID_AUDIO_GET_VOLUME = 1005
|
||||
ROBOT_API_ID_AUDIO_SET_VOLUME = 1006
|
||||
ROBOT_API_ID_AUDIO_SET_RGB_LED = 1010
|
||||
|
||||
"""
|
||||
" error code
|
||||
"""
|
||||
AUDIO_ERR_COMM = 100
|
||||
|
||||
74
vendor/unitree_sdk2_python/unitree_sdk2py/a2/audio/audio_client.py
vendored
Normal file
74
vendor/unitree_sdk2_python/unitree_sdk2py/a2/audio/audio_client.py
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
import json
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from ...rpc.client import Client
|
||||
from .audio_api import *
|
||||
|
||||
|
||||
"""
|
||||
" class AudioClient
|
||||
"""
|
||||
class AudioClient(Client):
|
||||
def __init__(self):
|
||||
super().__init__(AUDIO_SERVICE_NAME, False)
|
||||
self.tts_index = 0
|
||||
|
||||
def Init(self):
|
||||
# set api version
|
||||
self._SetApiVerson(AUDIO_API_VERSION)
|
||||
|
||||
# regist api
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_TTS, 0)
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_ASR, 0)
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_START_PLAY, 0)
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_STOP_PLAY, 0)
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_GET_VOLUME, 0)
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_SET_VOLUME, 0)
|
||||
self._RegistApi(ROBOT_API_ID_AUDIO_SET_RGB_LED, 0)
|
||||
|
||||
## API Call ##
|
||||
def TtsMaker(self, text: str, speaker_id: int) -> int:
|
||||
p = {}
|
||||
p["index"] = self.tts_index
|
||||
p["text"] = text
|
||||
p["speaker_id"] = speaker_id
|
||||
self.tts_index += 1
|
||||
parameter = json.dumps(p)
|
||||
code, data = self._Call(ROBOT_API_ID_AUDIO_TTS, parameter)
|
||||
return code
|
||||
|
||||
def GetVolume(self):
|
||||
p = {}
|
||||
parameter = json.dumps(p)
|
||||
code, data = self._Call(ROBOT_API_ID_AUDIO_GET_VOLUME, parameter)
|
||||
if code == 0:
|
||||
return code, json.loads(data)
|
||||
else:
|
||||
return code, None
|
||||
|
||||
def SetVolume(self, volume: int) -> int:
|
||||
p = {}
|
||||
p["volume"] = volume
|
||||
parameter = json.dumps(p)
|
||||
code, data = self._Call(ROBOT_API_ID_AUDIO_SET_VOLUME, parameter)
|
||||
return code
|
||||
|
||||
def LedControl(self, R: int, G: int, B: int) -> int:
|
||||
p = {}
|
||||
p["R"] = R
|
||||
p["G"] = G
|
||||
p["B"] = B
|
||||
parameter = json.dumps(p)
|
||||
code, data = self._Call(ROBOT_API_ID_AUDIO_SET_RGB_LED, parameter)
|
||||
return code
|
||||
|
||||
def PlayStream(self, app_name: str, stream_id: str, pcm_data: bytes):
|
||||
param = json.dumps({"app_name": app_name, "stream_id": stream_id})
|
||||
pcm_list = list(pcm_data)
|
||||
return self._CallRequestWithParamAndBin(ROBOT_API_ID_AUDIO_START_PLAY, param, pcm_list)
|
||||
|
||||
def PlayStop(self, app_name: str) -> int:
|
||||
parameter = json.dumps({"app_name": app_name})
|
||||
code, data = self._Call(ROBOT_API_ID_AUDIO_STOP_PLAY, parameter)
|
||||
return 0
|
||||
|
||||
0
vendor/unitree_sdk2_python/unitree_sdk2py/a2/sport/__init__.py
vendored
Normal file
0
vendor/unitree_sdk2_python/unitree_sdk2py/a2/sport/__init__.py
vendored
Normal file
41
vendor/unitree_sdk2_python/unitree_sdk2py/a2/sport/sport_api.py
vendored
Normal file
41
vendor/unitree_sdk2_python/unitree_sdk2py/a2/sport/sport_api.py
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
"""
|
||||
" service name
|
||||
"""
|
||||
ROBOT_SPORT_SERVICE_NAME = "sport"
|
||||
|
||||
"""
|
||||
" service api version
|
||||
"""
|
||||
ROBOT_SPORT_API_VERSION = "1.0.0.1"
|
||||
|
||||
"""
|
||||
" api id
|
||||
"""
|
||||
ROBOT_SPORT_API_ID_DAMP = 1001
|
||||
ROBOT_SPORT_API_ID_BALANCESTAND = 1002
|
||||
ROBOT_SPORT_API_ID_STOPMOVE = 1003
|
||||
ROBOT_SPORT_API_ID_STANDUP = 1004
|
||||
ROBOT_SPORT_API_ID_STANDDOWN = 1005
|
||||
ROBOT_SPORT_API_ID_RECOVERYSTAND = 1006
|
||||
ROBOT_SPORT_API_ID_EULER = 1007
|
||||
ROBOT_SPORT_API_ID_MOVE = 1008
|
||||
ROBOT_SPORT_API_ID_BODYPOSITION = 1009
|
||||
ROBOT_SPORT_API_ID_SWITCHGAIT = 1011
|
||||
ROBOT_SPORT_API_ID_BODYHEIGHT = 1013
|
||||
ROBOT_SPORT_API_ID_SPEEDLEVEL = 1015
|
||||
ROBOT_SPORT_API_ID_LEFTSIDEGAIT = 1016
|
||||
ROBOT_SPORT_API_ID_RIGHTSIDEGAIT = 1017
|
||||
ROBOT_SPORT_API_ID_HANDSTAND = 1018
|
||||
ROBOT_SPORT_API_ID_BIPEDSTAND = 1019
|
||||
ROBOT_SPORT_API_ID_FRONTFLIP = 1020
|
||||
ROBOT_SPORT_API_ID_BACKFLIP = 1021
|
||||
ROBOT_SPORT_API_ID_SETAUTORECOVERY = 1040
|
||||
ROBOT_SPORT_API_ID_GETSTATE = 1034
|
||||
|
||||
"""
|
||||
" error code
|
||||
"""
|
||||
# server side
|
||||
SPORT_ERR_SERVER_OVERTIME = 4201
|
||||
SPORT_ERR_SERVER_NOT_INIT = 4205
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user