
Siplab wristband
bastocon/sparse-pose-benchmark
Bachelor Thesis Paper: Sparse Pose Estimation data collection, evaluation backend, frontend, as well as all resources for the creation of the Hidden Dataset using commodity sensors.

Bachelor Thesis Paper: Sparse Pose Estimation data collection, evaluation backend, frontend, as well as all resources for the creation of the Hidden Dataset using commodity sensors.
UWB adaptor is an open-source printed circuit board by bastocon, from the bastocon/sparse-pose-benchmark repository on GitHub, published under the MIT licence. It is a 2-layer board of 35 × 15.9 mm with 14 parts on 43 nets, routed with 203 tracks and 62 vias.
It is built around the DWM1000 and MIC5216-3.3YM5-TR. Its parts include 4 resistors, 4 connectors, 3 capacitors, 1 IC and 1 diode. It belongs with the radio and wireless boards of this library.
Benchmarking Deep Learning-Based Pose Estimation from Sparse IMUs
These are the interesting subdirectories:
Insert needed datasets here. It could be, that this folder needs to be created first.
data
├── smplx_models
│ └── smpl
│ └── SMPL_FEMALE.npz
│ └── ...
├── AMASS
│ └── ACCAD
│ └── ...
├── ...Contains all evaluated methods, and under /pip also the evaluate.py and preprocess.py used for the benchmark.
Contains the code for the platform, seperated in /frontend and /backend.
The server is located in /src/platform/backend/src/index.ts, and the default submissions directory in /src/platform/backend/submissions.
Each subdirectory has its own README's.
/uwb_wearables/recording/processing. uwb_wearables in general contains all the code for hardware and firmware of the commodity sensors. The recording/processing directory in particular contains the code to process the raw uwb.csv and imu.csv, including the orientation estimator./processing contains all the post-processing. It also contains info.csv and shape.csv if you need the cut intervals, beta shape parameters or similar.VirtualCaliper is the program used to generate the SMPL shape parameters.Do one of these things:
Setup or rebuild:
docker-compose build
To create a non-persistent session to execute the evaluation:
docker-compose run --rm --remove-orphans pip-env
Optional: If you want to be sure, that it builds correctly after changes, do:
docker-compose build --no-cache
Same as for the backend, but use vis-env. e.g. docker-compose run --rm --remove-orphans vis-env.
Note that the visualizer.py files need to be run with xvfb-run -s "-screen 0 1280x720x24" python path/to/visualizer.py, as the docker does not has access to the display.
We have the following environments: uip, pip-env, mocap. You can find them under
/pip_env.yml. Please refer to /pip_env_README.md and worst case /docker/pip-env/Dockerfile in the comments for an installation guide. The setup for rbdl was not easy. Works with python 3.7./mocap_env.yml/src/experimental/UIP/environment.yml. As this python version differs, rbdl might has to be re-build. Works with python 3.8.17.Use pip-env. Be in project root. These scripts automatically evaluate all .pt files named as the datasets that are in a folder. You always have to provide the path of the folder and not the files for this evaluation.
Preparation:
uip_db.pt, totalcapture.pt, amass.pt, gip_person1.pt, gip_perspn2.pt, hidden.pt in folder/ - no substructure.config.json (optional but recommended), submission_info.json (really optional, used for the display of information on the website).Example config.json:
{
"eval_tran": true
}Run the evaluation of the benchmark:
python ./src/experimental/pip/evaluate.py eval --path <path_to_folder>If you also run GIP (as its predicted as two single person), or want to re-evaluate the overall scores, additionally do this to calculate the overall scores.
python ./src/experimental/pip/evaluate.py overall --path <path_to_folder>The result will be in folder/evaluation.json. The first part shows the results per dataset per sequence, and the last rows ("overall") have the final results. More details can be found in the Additional Information section.
For clearity: An example file structure
/.../submissions/1_PIP
├── amass.py
├── totalcapture.pt
├── ...
├── config.json
├── submission_info.jsonTip: If you only want to test things and run different versions, create an archive folder inside your actual evaluation folder. As the backend only searches for the exact files in the top level, they are not evaluated.
E.g. folder/totalcapture.pt will be evauated, but folder/archive/totalcapture.pt will not.
Uses environment "pip-env".
Go into project root. Preprocess:
python src/experimental/pip/preprocess.pyEvaluating PIP on a method:
python src/experimental/pip/evaluate.py predict --dataset <dataset>with dataset in [hidden, totalcapture, uip_db, amass, gip_person1, gip_person2]
Get the output in a unified format. It creates an output file in the project root that has to be moved where desired.
python src/experimental/utils/change_pt_file.py correct_pip_output <path-to-results-file.pt>Use environment "uip" from src/experimental/UIP/environment.yml file, I used python 3.8.17.
Go into /src/experimental/UIP
For preprocessing:
python modules/dataset/preprocess.pyFor evaluating UIP on a dataset:
python modules/evaluate/evaluator.py --network UIP\
--ckpt_path data/processed/UIP/pretrained.pt\
--data_dir data/processed/UIP/ground_truth_datasets/HiddenDataset\
--eval_trans\
--normalize_uwb\
--add_guassian_noise\
--model_args_file config/model_args.json\
--eval_save_dir data/processed/UIP/evaluation_res/HiddenDatasetTo change the UIP output from the per-sequence based file to one file for benchmark evaluation:
python src/experimental/utils/change_pt_file.py correct_uip_output <path/to/uip-output-folder> <path/to/gt-file-for-betas-gender>
# Or specifically (notice that UIP creates folders with spaces, do not forget the "")
python src/experimental/utils/change_pt_file.py correct_uip_output "/local/home/**/data/processed/UIP/result/HiddenDataset/Ultra Inertial Poser" /local/home/**/data/processed/ground_truth_datasets/hidden_test_gt.ptThis produces an output, that has to be renamed and put into one submission folder for evaluation.
Check out the official UIP GitHub README for open questions.
Use pip-env environment, same as in PIP method.
For a pleasant experience, start in project root. Comment the datasets you want to use in the process.py before execution. Preprocessing
python src/experimental/PNP/process.pyPrediction: Comment in/out the datasets you want to run in test.py before execution.
cd src/experimental/PNP
python test.pyGet the output in a unified format. It creates an output file in the project root that has to be moved where desired.
python src/experimental/utils/change_pt_file.py correct_pnp_output <path-to-results-file.pt>To visualize a sequence, and/or ground truth to it, use this:
python ./tracking/processing/vis.py --input <gt-file.pt> --output <prediction.pt> --seq 1 --second-input <gip-person2.pt> --origin--input expects a ground truth file, specifically a file in which there is pose of shape [N, T, 24, 3].--output expects a prediction file, specifically a file which has keys 0, ..., N-1 and where each i has a pose of shape [T, 24, 3].--seq The sequence ID to show--second-input same as --input, but especially useful for visualization of a second person like in GIP-DB.--origin to reset origin in x and z axis (no height).Can be found in /src/platform, seperated into frontend and backend.
To test it:
cd /src/platform/frontend
ng servecd /src/platform/backend
npm run devThis is the template for the evaluation.json file, generated for each method. All of the following values can be null/nan.
{ sequence_metrics: { [dataset: string]: { [sequenceId: number]: { frames: number, tran_win_count: number, angle_mean: number, angle_std: number, sip_mean: number, sip_std: number, joint_pos_mean: number, joint_pos_std: number, jitter_mean: number, jitter_std: number, abs_jitter_mean: number, abs_jitter_std: number, drift_mean: number, drift_std: number, foot_pen_mean: number, foot_pen_std: number, foot_sliding_mean: number, mpjve_mean: number, mpjve_std: number, trans_2m_mean: number, trans_5m_mean: number, }, ... } }, overall: { [dataset: string]: { frames: number, angle: number, sip: number, joint_pos: number, jitter: number, abs_jitter: number, drift: number, foot_pen: number, foot_sliding: number, mpjve: number, trans_2m: number, trans_5m: number, }, ... } }
This is generaetd for each method from the server and optional, it defines the public information for each submission.
{ shortName: string, version: string, fullName: string, pubTitle: string, pubAuthors: string, pubVenue: string, pubUrl: string, description: string, hardware: string, parameters: string, availability: string, availabilityUrl: string, status: string, contactEmail: string }
This project is released under the MIT license. Our code is partially based on PIP.
Recorded at SIP Lab, Computer Science Department, ETH Zurich, Switzerland.
The sequences are numbered AA01, AA02, AA03 where AA is the subject identifier. Not all subjects have all three sequences.
In the main directory are the test.pt and train.pt, which contain the dataset with the synthetic magnetometer variant. This is the default version of this dataset. pose is stored in axis angle format. Note that tran does not start at origin to ensure compatibility for the camera feed.
test.pt has the following keys:
acc, ori, betas, gender, vuwb, offset (= None)train.pt has the following keys:
acc, ori, betas, gender, vuwb, offset (= None), pose, tranThis directory contains all the videos for each subject. Note that not the subject (TM**) does not have videos, and for some sequences only 3 of 4 cameras worked. The subfolders are front, back, left, right indicating from where you usually see the person from. As most participants looked at the instructor, front is the default viewing direction for most people, the other directions are derived from that. The videos are pre-cut, but you have to do the exact frame-synchronization.
In the Extras folder, one can find additional versions of the dataset, with more data access for advanced processing.
It contains test_no-mag.pt and train_no-mag with the same test and train data and keys, but where the orientation estimation is done without magnetometer readings. This leads to a significantly higher orientation error and more difficulty to estimate pose from.
It also contains the sequences with the following raw data. We recommend checking out the code and how it was generated, before using them. Wo = World frame of OptiTrack, so in which it was recorded. Wx= World frame of Xsens, where the pose originates. vis = Visualization/export frame (Y-up), this is the system in which everything like pose is exported by default if nothing is mentioned otherwise. Check out the paper "Benchmarking Deep Learning-Based Pose Estimation" for a more detailed definition of the coordinate systems etc.
"pose": to_numpy(pose_vis), # (N, 72)
"pose_wo": to_numpy(pose_wo), # (N, 72) in wo frame
"pose_unoptimized_vis": to_numpy(archive_pose_vis), # (N, 72) in vis frame, but no optimization"
"pose_raw_xsensframe": to_numpy(data1["poses"][begin_idx:end_idx+1]), # (N, 72) in Xsens frame
"tran": to_numpy(tran_vis), # (N, 3), Optitrack Translation in vis frame
"tran_wo": to_numpy(tran_wo), # (N, 3), Optitrack Translation in wo frame
"tran_unoptimized_vis": to_numpy(archive_tran_vis), # (N, 3) OptiTrack translation in vis frame, but no optimization
"tran_raw_xsensframe": to_numpy(data1["trans"][begin_idx:end_idx+1]), # (N, 3) in Xsens frame
# sensor readings
"rot": to_numpy(rot_vis), # (N, S, 3, 3) rotmat
"rot_wo": to_numpy(rot_wo), # (N, S, 3, 3) rotmat in wo frame
"acc": to_numpy(acc_vis), # (N, S, 3)
"acc_wo": to_numpy(acc_wo), # (N, S, 3) in wo frame
"acc_sensor": to_numpy(acc_sensor), # (N, S, 3) sensor frame acc
"acc_gtrotated": to_numpy(acc_vis_opt), # (N, S, 3) # acc rotated with optitrack rot to remove sensor drift
"uwb": to_numpy(uwb), # (N, S, S), sensor UWB, frame independant
# OptiTrack ground truth
'opt_rot': to_numpy(opt_rot_vis), # (N, S, 3, 3) rotmat
'opt_rot_wo': to_numpy(opt_rot_wo), # (N, S, 3, 3) rotmat in wo frame
'opt_rot_wo_raw': to_numpy(archive_opt_rot_wo), # (N, S, 3, 3) rotmat in wo frame, but no filtering
'opt_acc': to_numpy(opt_acc), # (N, S, 3)| Qty | Value | Footprint | References |
|---|---|---|---|
| 2 | 10k | Resistor_SMD:R_0402_1005Metric | R1, R2 |
| 2 | 1uF | Capacitor_SMD:C_0402_1005Metric | C1, C2 |
| 2 | 538850208 | siplab:Molex_SlimStack_53885-0208_2x10_P0.50mm_Vertical | J5, J6 |
| 2 | 541020204 | siplab:Molex_SlimStack_54102-0204_2x10_P0.50mm_Vertical | J4, J7 |
| 1 | 100k | Resistor_SMD:R_0402_1005Metric | R3 |
| 1 | 100nF | Capacitor_SMD:C_0402_1005Metric | C3 |
| 1 | 3k | Resistor_SMD:R_0402_1005Metric | R4 |
| 1 | DWM1000 | RF_Module:DWM1000 | DWM1 |
| 1 | MIC5216-3.3YM5 | Package_TO_SOT_SMD:SOT-23-5 | U1 |
| 1 | RED | LED_SMD:LED_0603_1608Metric | D1 |
It measures 35 × 15.9 mm and has 2 copper layers, 1.6 mm thick.
14 parts, built around the DWM1000 and MIC5216-3.3YM5-TR. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.
From the bastocon/sparse-pose-benchmark repository on GitHub, at the commit this page was made from: the board is src/tracking/uwb_wearables/hardware/UWB_adaptor/UWB_adaptor.kicad_pcb and its schematic src/tracking/uwb_wearables/hardware/UWB_adaptor/UWB_adaptor.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).

bastocon/sparse-pose-benchmark
Bachelor Thesis Paper: Sparse Pose Estimation data collection, evaluation backend, frontend, as well as all resources for the creation of the Hidden Dataset using commodity sensors.



jh247247/DW1000-fan-video
Using UWB to make an indoor location system, to get a fan to point at me.


repowered-electronics/UWB_Module_Hardware
Hardware files for our DWM1000 based localization module

JEB12345/DWM100_Breakout
A Breakout board to mount a DWM1000 module onto SUPERball's XBee WiFi slot on the Sensor Board

Kmshanley/MiniRobots
Firmware and PCB desgin for mini robots with UWB localization and lidar mapping
