# Jump analysis (jump\_analysis)

Measure **vertical jump height** from the user’s hip movement in pixels.

This mode needs a user-provided height (`userHeightCm`).

See also:

* [Shared query parameters (Tracking + Upload Tracking)](/posetracker-api/posetracker-api-query-parameters.md)
* [Upload Tracking endpoint (video & image)](/posetracker-api/use-posetracker-on-uploaded-files/upload-tracking-endpoint-video-and-image.md)
* [WebView messages (Upload Tracking)](/posetracker-api/use-posetracker-on-uploaded-files/upload-tracking-endpoint-video-and-image/webview-native-messages.md)

### Overview

#### What you get

* Live **jump detection** and **jump height** estimates.
* A one-time **calibration** step to lock a baseline and scale.
* Optional **device pitch correction**.

#### Key features

* Uses only **hip keypoints** (`left_hip`, `right_hip`).
* Works in **real time** (`/pose_tracker/tracking`) and on **video** (`/pose_tracker/upload_tracking`).
* Emits simple PostMessage events: `posture`, `jump_calibration`, `jump_started`, `jump_height`, `jump_summary`, `error`.

### Prerequisites

#### Required query parameters

* `exercise=jump_analysis`
* `token=...`
* `userHeightCm=...` (number, centimeters)

If `userHeightCm` is missing or invalid, the iframe sends an `error` event with:

* `error: "jump_analysis_missing_height"`

#### Optional query parameters

* `devicePitchDeg=...` (number, degrees)
  * Used to compensate for a camera pitched up/down.
  * See **Measurement algorithm**.

#### Tracking prerequisites (pose)

* Both hip keypoints must be detected with **score > 0.5**.
* The full body should be visible.
* The camera must stay fixed.

### Comparison: jump\_analysis vs air\_time\_jump

Use this when you can provide user height.

| Aspect      | jump\_analysis                                                       | air\_time\_jump                                                |
| ----------- | -------------------------------------------------------------------- | -------------------------------------------------------------- |
| User height | Required (`userHeightCm`)                                            | Not required                                                   |
| Calibration | Yes (stable standing → `baselineY` + `cmPerPixel` from frame height) | No (dynamic baseline from recent frames)                       |
| Scale       | Pixel-to-cm via `cmPerPixel`                                         | Time-to-height via physics                                     |
| Formula     | `jumpHeightCm = (baselineY - minY) * cmPerPixel`                     | `h = (1/8)*g*t²`, then cm                                      |
| Outputs     | jumpHeightCm, deltaPixels, cmPerPixel, baselineY, minY               | jumpHeightCm, airTimeMs, airTimeSeconds, baselineY, minY       |
| Use when    | User height is known; you want a scale tied to frame/user            | User height unknown; you want a simple, physics-based estimate |

Also see: [Air time jump (air\_time\_jump)](/posetracker-api/use-posetracker-on-real-time-camera-webcam/query-params-details/exercise-optional/air-time-jump-air_time_jump.md)

### Exercise detection

Always pass `exercise=jump_analysis` to enable jump height mode.

### API endpoints

#### Live (camera)

Base URL:

```
https://app.posetracker.com/pose_tracker/tracking
```

Example:

```
https://app.posetracker.com/pose_tracker/tracking?token=YOUR_API_KEY&exercise=jump_analysis&userHeightCm=178
```

#### Upload Tracking (video)

Base URL:

```
https://app.posetracker.com/pose_tracker/upload_tracking
```

Example:

```
https://app.posetracker.com/pose_tracker/upload_tracking?token=YOUR_API_KEY&source=video&exercise=jump_analysis&userHeightCm=178
```

Common optional flags on video:

* `export=true` (keeps the last frame visible and enables export UI)
* `skeleton=true|false`
* `keypoints=true` (plan-gated)

### PostMessage events

These events are sent from the iframe/WebView to your host app.

If you’re new to placement messages, read: [Exercise Placement](/posetracker-api/use-posetracker-on-real-time-camera-webcam/tracking-endpoint-message-to-handle/exercise-placement.md).

#### `posture`

Sent continuously to guide placement.

```json
{
  "type": "posture",
  "message": "...",
  "direction": "in-frame",
  "ready": false,
  "requirements": []
}
```

#### `jump_calibration` (jump\_analysis only)

Sent while the user is standing still for calibration.

Payload varies by version.

You should treat this as:

* a progress/ready signal
* plus optional debug fields (baseline, scale)

```json
{
  "type": "jump_calibration",
  "ready": false,
  "message": "Hold still"
}
```

#### `jump_started`

Sent once when upward movement crosses the detection threshold.

```json
{
  "type": "jump_started"
}
```

#### `jump_height`

Sent during measurement of a jump.

```json
{
  "type": "jump_height",
  "jumpHeightCm": 34.2,
  "deltaPixels": 171,
  "cmPerPixel": 0.2,
  "baselineY": 512.3,
  "minY": 341.3,
  "devicePitchDegUsed": 0,
  "final": true
}
```

Notes:

* `deltaPixels = baselineY - minY` (hip Y decreases when the user goes up).
* `final=true` indicates the jump is completed (landing detected).

#### `jump_result`

Sent at the end of a jump.

```json
{ 
  type: "jump_result",
  jumpNumber: number,
  jumpHeightCm: number,
  airTimeMs?: number,
  airTimeSeconds?: number,
  baselineY?: number,
  minY?: number,
  deltaPixels?: number,
  visibleHips?: object
}
```

#### `jump_summary` (video)

Sent at the end of a video analysis. And after every new jump (after the `jump_result`) on real-time mode.

Multiple jumps can be detected in a single clip.

Heights are in **centimeters**.

```json
{
  "type": "jump_summary",
  "totalJumps": 3,
  "avgJumpHeight": 32.1,
  "maxJumpHeight": 38.4,
  "minJumpHeight": 27.9,
  "final": true
}
```

#### `error`

Sent on invalid config or runtime failures.

```json
{
  "type": "error",
  "error": "jump_analysis_missing_height",
  "message": "userHeightCm is required"
}
```

### Placement overlay behavior

* Uses the standard placement system (`posture`).
* You should keep the user **centered** and **fully in frame**.
* Calibration only becomes ready when hip Y is stable for \~1 second.

### User flow

1. **Placement**: wait for `posture.ready=true`.
2. **Calibration**: wait for `jump_calibration.ready=true`.
3. **Jump**:
   * Receive `jump_started`.
   * Receive `jump_height` updates.
   * Consider the jump complete when `jump_height.final=true`.

### Measurement algorithm

#### 1) Hip signal

* Read `left_hip` and `right_hip` keypoints.
* Require **score > 0.5**.
* Use a single hip Y signal (implementation may average hips).

#### 2) Baseline calibration

* The user must stand still for a short stable window (\~1s).
* Baseline:

```
baselineY = average(hipY over stable window)
```

#### 3) Pixel-to-cm scale

Scale is derived from user height and the frame height.

```
cmPerPixel = userHeightCm / (frameHeight * 0.9)
cmPerPixel = clamp(cmPerPixel, 0.2, 2.0)
```

Important:

* Current implementation does **not** use ankle-to-hip pixel distance.
* It uses **frame height × 0.9** as an approximate body span.

#### 4) Jump detection + landing

* Jump starts when hip moves up by **> 15 px** from baseline.

```
started when (baselineY - hipY) > 15
```

* Landing when hip returns to within **10 px** of baseline.

```
landed when abs(hipY - baselineY) < 10
```

#### 5) Height calculation

During the jump, track the minimum hip Y (`minY`).

```
deltaPixels = baselineY - minY
jumpHeightCm = deltaPixels * cmPerPixel
```

#### 6) Optional pitch correction

If `devicePitchDeg` is provided, height can be corrected by:

```
pitchRad = devicePitchDeg * PI / 180
jumpHeightCmCorrected = jumpHeightCm / cos(pitchRad)
```

The handler clamps the pitch it uses.

### Integration examples

#### Web (iframe)

```html
<iframe
  id="posetracker"
  src="https://app.posetracker.com/pose_tracker/tracking?token=YOUR_API_KEY&exercise=jump_analysis&userHeightCm=178"
  style="width:100%;height:100%;border:0;"
  allow="camera;microphone"
></iframe>

<script>
  window.addEventListener('message', (event) => {
    const msg = event.data;
    if (!msg || !msg.type) return;

    switch (msg.type) {
      case 'posture':
        // show msg.message, gate your UI on msg.ready
        break;
      case 'jump_calibration':
        // show calibration progress; wait for ready=true
        break;
      case 'jump_started':
        // start your timer/animation
        break;
      case 'jump_height':
        // msg.jumpHeightCm + debug fields
        break;
      case 'jump_summary':
        // video-only aggregate
        break;
      case 'error':
        console.error(msg);
        break;
    }
  });
</script>
```

#### Upload Tracking (video URL)

```
https://app.posetracker.com/pose_tracker/upload_tracking?token=YOUR_API_KEY&source=video&videoSrc=https://your-cdn.com/jump.mp4&exercise=jump_analysis&userHeightCm=178&export=true
```

When `export=true`, the last analyzed frame stays visible.

### Best practices and limitations

#### Best practices

* Keep the camera fixed and avoid zoom changes.
* Keep the user fully visible (especially hips).
* Ask the user to stand still for calibration.

#### Limitations

* Absolute height depends on the `userHeightCm` you provide.
* Any camera pitch reduces vertical pixel motion. Use `devicePitchDeg` when you can.
* This measures **hip vertical displacement**, not true COM displacement.

### Troubleshooting

* Getting `jump_analysis_missing_height`:
  * Pass `userHeightCm` as a number in centimeters.
* Calibration never becomes ready:
  * Improve lighting.
  * Ensure hips are visible and stable.
  * Reduce camera shake.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://posetracker.gitbook.io/posetracker-api/use-posetracker-on-real-time-camera-webcam/query-params-details/exercise-optional/jump-analysis-jump_analysis.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
