Heave
The vertical motion of the vessel in meters, with a trend band and advice zones.
On this page
Code
import {
AdviceType,
Heave,
ObcHeaveType,
Priority,
Readout,
ReadoutSize,
VesselImage,
type LinearAdvice,
} from "@bosunkit/instruments";
import { useEffect, useState, type CSSProperties, type Dispatch, type ReactElement, type SetStateAction } from "react";
export const description: string =
"Hove to in a building swell on a live feed: the yacht rides the heave beside its scale, the band of the last ten " +
"seconds reaches the advice and caution zones as the sets come through, and a bar column repeats it on a wider " +
"range.";
/** The swell where boarding the tender gets awkward, and where it stops. */
const ADVICE: LinearAdvice[] = [
{ min: 0.8, max: 1.2, type: AdviceType.advice, hinted: false },
{ min: -1.2, max: -0.8, type: AdviceType.advice, hinted: false },
{ min: 1.2, max: 3, type: AdviceType.caution, hinted: true },
{ min: -3, max: -1.2, type: AdviceType.caution, hinted: true },
];
const WIDE_ADVICE: LinearAdvice[] = [
{ min: 2, max: 5, type: AdviceType.caution, hinted: true },
{ min: -5, max: -2, type: AdviceType.caution, hinted: true },
];
const SAMPLE_SECONDS: number = 0.5;
const TREND_SECONDS: number = 10;
const PANEL: CSSProperties = {
display: "flex",
flexWrap: "wrap",
alignItems: "center",
justifyContent: "center",
gap: 24,
width: "100%",
maxWidth: 660,
};
const COLUMN: CSSProperties = { display: "flex", flexDirection: "column", gap: 16 };
/** Heave in meters at a time in seconds: two wave trains under an envelope that builds and eases as sets pass. */
function heaveAt(time: number): number {
const envelope: number = 0.7 + 0.45 * Math.sin(time / 12);
return envelope * (0.9 * Math.sin((2 * Math.PI * time) / 7) + 0.45 * Math.sin((2 * Math.PI * time) / 4.3 + 1));
}
/** The lowest and highest heave over the trend window ending at `time`. */
function trendAt(time: number): { low: number; high: number } {
let low: number = Number.POSITIVE_INFINITY;
let high: number = Number.NEGATIVE_INFINITY;
for (let past: number = 0; past <= TREND_SECONDS; past += SAMPLE_SECONDS) {
const value: number = heaveAt(time - past);
low = Math.min(low, value);
high = Math.max(high, value);
}
return { low, high };
}
export default function Showcase(): ReactElement {
const [sample, setSample]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);
useEffect((): (() => void) => {
const interval: number = window.setInterval((): void => {
setSample((previous: number): number => previous + 1);
}, SAMPLE_SECONDS * 1000);
return (): void => {
window.clearInterval(interval);
};
}, []);
const time: number = sample * SAMPLE_SECONDS;
const heave: number = heaveAt(time);
const { low, high }: { low: number; high: number } = trendAt(time);
return (
<div style={PANEL}>
<div style={{ width: 280, height: 280 }}>
<Heave
heave={heave}
minTrendHeave={low}
maxTrendHeave={high}
instrumentRange={3}
gainScale={2}
draftOffset={0.2}
vesselImage={VesselImage.sailingYachtFore}
advice={ADVICE}
priority={Priority.enhanced}
type={ObcHeaveType.vessel}
/>
</div>
<div style={{ width: 120, height: 280 }}>
<Heave
heave={heave}
minTrendHeave={low}
maxTrendHeave={high}
instrumentRange={5}
advice={WIDE_ADVICE}
type={ObcHeaveType.bar}
/>
</div>
<div style={COLUMN}>
<Readout label="Heave" value={heave} fractionDigits={1} unit="m" src="Motion sensor" size={ReadoutSize.large} />
<Readout label="Lowest, 10 s" value={low} fractionDigits={1} unit="m" />
<Readout label="Highest, 10 s" value={high} fractionDigits={1} unit="m" />
</div>
</div>
);
}
The heave instrument shows how far the vessel rises and falls, in meters, positive up. A scale column carries the
current value and a band between the recent lowest and highest heave, and the default layout sets it beside a vessel
silhouette that rides the motion. The scale spans plus and minus instrumentRange, 10 meters by default. It ports
obc-heave; the overview lists the other instruments.
Examples
Heave
Code
import { Heave } from "@bosunkit/instruments";
import type { ReactElement } from "react";
export const description: string = "The vessel 0.6 meters above its mean height.";
export default function HeaveExample(): ReactElement {
return (
<div style={{ width: 200, height: 200 }}>
<Heave heave={0.6} />
</div>
);
}
With vessel
Code
import { Heave } from "@bosunkit/instruments";
import type { ReactElement } from "react";
export const description: string = "The vessel with the band between its recent lowest and highest heave.";
export default function WithVessel(): ReactElement {
return (
<div style={{ width: 200, height: 200 }}>
<Heave heave={0.6} minTrendHeave={-0.9} maxTrendHeave={1.4} />
</div>
);
}
Bar
Code
import { Heave, ObcHeaveType } from "@bosunkit/instruments";
import type { ReactElement } from "react";
export const description: string = "The scale column on its own, for a narrow strip beside another instrument.";
export default function Bar(): ReactElement {
return (
<div style={{ width: 200, height: 200 }}>
<Heave heave={0.6} minTrendHeave={-0.9} maxTrendHeave={1.4} type={ObcHeaveType.bar} />
</div>
);
}
Reference and recent range
Heave is vertical motion in meters, positive upward. Identify the motion reference and supply recent minimum and maximum values from a stated window. That envelope is not a forecast or a safety limit.
Keep the range steady while comparing motion, and explain a clipped extreme with the numeric reading. Sensor alignment, filtering and availability belong to the data adapter. A flat line or centered vessel must not imply that an unavailable motion sensor reports a calm sea.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| heave | number | undefined | 0 | Current heave in meters (positive up). |
| gainScale | number | undefined | 10 | Visual gain divisor applied to the vessel's vertical motion. |
| minTrendHeave | number | undefined | 0 | Lower edge of the recent heave trend band, meters. |
| maxTrendHeave | number | undefined | 0 | Upper edge of the recent heave trend band, meters. |
| draftOffset | number | undefined | 0 | Static vertical offset of the vessel silhouette, meters. |
| advice | LinearAdvice[] | undefined | [] | Heave advice zones; triggered when the trend band overlaps the range. |
| instrumentRange | number | undefined | 10 | Full-scale heave of the instrument in meters (symmetric ±). |
| vesselImage | VesselImage | undefined | VesselImage.psvFore | Fore-view vessel silhouette riding the heave. |
| priority | Priority | undefined | Priority.regular | Color priority: regular (gray palette, default) or enhanced (blue palette) for the scale fill and the trend
band. |
| type | ObcHeaveType | undefined | ObcHeaveType.vessel | vessel (default) frames the scale next to a vessel silhouette; bar
renders the scale column on its own. |
| className | string | undefined | – | Class names added to the instrument's root element. |