Skip to content
design
Instruments

Rudder

The rudder angle on a half circle, positive to starboard, with a bar or a needle and a setpoint marker.

On this page
040-40
Autopilot: the bar, its command and the zones, zoomed onto the arc
040-40
Helm: the needle and a setpoint being adjusted
Emergency tiller, sensor starting
The autopilot steering downwind on a live feed: the rudder following its command into the caution zone, a setpoint being adjusted at the helm, and a sensor starting.
Code
import {
  AdviceType,
  InstrumentState,
  ObcRudderVariant,
  Priority,
  Rudder,
  TickmarkStyle,
  type AngleAdvice,
} from "@bosunkit/instruments";
import { useEffect, useState, type CSSProperties, type Dispatch, type ReactElement, type SetStateAction } from "react";

export const description: string =
  "The autopilot steering downwind in a quartering sea on a live feed: the commanded angle swings to meet each wave, " +
  "the rudder follows it, the caution zone near the stops triggers when the command goes past 25 degrees, and the " +
  "helmsman adjusts the setpoint on a second dial while the emergency tiller's sensor starts up.";

/** Hard over on a Hanse 460 is about 38 degrees; past 25 the rudder stalls and the pilot is losing the boat. */
const MAX_ANGLE: number = 40;

const ADVICES: AngleAdvice[] = [
  { minAngle: -8, maxAngle: 8, type: AdviceType.advice, hinted: true },
  { minAngle: 25, maxAngle: 40, type: AdviceType.caution, hinted: true },
  { minAngle: -40, maxAngle: -25, type: AdviceType.caution, hinted: true },
];

const PANEL: CSSProperties = {
  display: "flex",
  flexWrap: "wrap",
  alignItems: "flex-end",
  justifyContent: "center",
  gap: 24,
  width: "100%",
  maxWidth: 660,
};

const FIGURE: CSSProperties = { display: "flex", flexDirection: "column", alignItems: "center", gap: 6, margin: 0 };
const CAPTION: CSSProperties = { fontSize: 13, color: "var(--text-dim)", textAlign: "center", maxWidth: 240 };

/** The pilot's commanded angle in degrees at a time in seconds, positive to starboard. */
function commandAt(time: number): number {
  const set: number = Math.max(0, Math.sin(time / 9)) ** 4;
  return 14 * Math.sin((2 * Math.PI * time) / 8) + 14 * set * Math.sign(Math.sin((2 * Math.PI * time) / 8));
}

export default function Showcase(): ReactElement {
  const [second, setSecond]: [number, Dispatch<SetStateAction<number>>] = useState<number>(0);

  useEffect((): (() => void) => {
    const interval: number = window.setInterval((): void => {
      setSecond((previous: number): number => previous + 1);
    }, 1000);
    return (): void => {
      window.clearInterval(interval);
    };
  }, []);

  const command: number = Math.round(commandAt(second));
  // The hydraulic drive takes about a second to reach the command.
  const angle: number = commandAt(second - 1);

  // On the helm dial the helmsman moves the setpoint between 5 and 15 degrees to starboard every ten seconds,
  // turning the knob for the last two.
  const helmSetpoint: number = Math.floor(second / 10) % 2 === 0 ? 5 : 15;
  const adjusting: boolean = second % 10 >= 8;

  return (
    <div style={PANEL}>
      <figure style={FIGURE}>
        <div style={{ width: 300, height: 170 }}>
          <Rudder
            angle={angle}
            variant={ObcRudderVariant.Bar}
            maxAngle={MAX_ANGLE}
            setpoint={command}
            autoAtSetpoint
            autoAtSetpointDeadband={2}
            setpointAtZeroDeadband={0.5}
            animateSetpoint
            advices={ADVICES}
            priority={Priority.enhanced}
            tickmarkStyle={TickmarkStyle.enhanced}
            showLabels
            zoomToFitArc
          />
        </div>
        <figcaption style={CAPTION}>Autopilot: the bar, its command and the zones, zoomed onto the arc</figcaption>
      </figure>

      <figure style={FIGURE}>
        <Rudder
          angle={angle}
          variant={ObcRudderVariant.Needle}
          maxAngle={MAX_ANGLE}
          setpoint={helmSetpoint}
          newSetpoint={adjusting ? (helmSetpoint === 5 ? 15 : 5) : undefined}
          touching={adjusting}
          animateSetpoint
          advices={ADVICES}
          tickmarksInside
          showLabels
          faceDiameter={150}
        />
        <figcaption style={CAPTION}>Helm: the needle and a setpoint being adjusted</figcaption>
      </figure>

      <figure style={FIGURE}>
        <Rudder
          angle={0}
          maxAngle={MAX_ANGLE}
          setpoint={0}
          setpointOverride
          atSetpoint
          state={InstrumentState.loading}
          faceDiameter={110}
        />
        <figcaption style={CAPTION}>Emergency tiller, sensor starting</figcaption>
      </figure>
    </div>
  );
}

The rudder instrument shows the rudder angle on the lower half of a circle, with zero at the bottom. A positive angle is to starboard and the scale spans plus and minus maxAngle, 90 degrees by default. The bar variant fills the arc from zero, the needle variant turns a pointer, and a setpoint marker shows the commanded angle. It ports obc-rudder; the overview lists the other instruments.

Examples

Rudder

The rudder 12 degrees to port, filled from the zero mark at the bottom.
Code
import { Rudder } from "@bosunkit/instruments";
import type { ReactElement } from "react";

export const description: string = "The rudder 12 degrees to port, filled from the zero mark at the bottom.";

export default function RudderExample(): ReactElement {
  return (
    <div style={{ width: 200, height: 200 }}>
      <Rudder angle={-12} />
    </div>
  );
}

Small face

A rudder on a face pinned to 180 pixels, which sizes itself and needs no surrounding box.
Code
import { Rudder } from "@bosunkit/instruments";
import type { ReactElement } from "react";

export const description: string =
  "A rudder on a face pinned to 180 pixels, which sizes itself and needs no surrounding box.";

export default function SmallFace(): ReactElement {
  return <Rudder angle={-12} faceDiameter={180} />;
}

Feedback and command

Pass the measured rudder angle as the value and the commanded angle as the setpoint. Positive angles describe starboard in this component. Confirm that convention in the equipment adapter; reversing a sensor's sign in a page style would make the numeric and drawn values disagree.

Choose maxAngle from the installed equipment and retain a numeric reading near the dial. A setpoint marker shows a requested angle, not proof that the rudder moved. Keep actuator mode, feedback loss and command failure visible in the containing control view.

Props

PropTypeDefaultDescription
anglenumber | undefined0Rudder angle in degrees; positive fills to starboard.
variantObcRudderVariant | undefinedObcRudderVariant.BarDisplay variant: filled arc from zero (default) or a rotating needle.
maxAnglenumber | undefined90Symmetric ± range around the bottom zero (default 90°).
showLabelsboolean | undefinedfalseShow numeric angle labels at tickmarks.
tickmarksInsideboolean | undefinedfalseWhether to render tickmarks inside the ring.
stateInstrumentState | undefinedInstrumentState.activeInstrument state: active (default), loading or off. loading and off draw the bar, the needle and the setpoint marker in the muted frame colors.
priorityPriority | undefinedPriority.regularColor priority: regular (gray palette, default) or enhanced (blue palette) for the bar, the needle and the setpoint marker.
tickmarkStyleTickmarkStyle | undefinedTickmarkStyle.regularTickmark color style. regular (default) draws every tick in the dim tertiary color; enhanced draws ticks in the brighter primary color and tertiary ticks in the secondary color.
advicesAngleAdvice[] | undefined[]Caution/alert arcs; triggered state derives from the SETPOINT being in range.
zoomToFitArcboolean | undefinedfalseEnlarge the visible arc to fill the container.
faceDiameternumber | undefined–Outer-ring diameter in CSS pixels. When set, the instrument renders at a fixed intrinsic size derived from the ring, arc shape and label reserve — so instruments sharing the same value have identical ring circumference regardless of label width or arc extent. When unset (default), the instrument fills its container.
classNamestring | undefined–Class names added to the instrument's root element.
setpointnumber | undefined–Target setpoint value.
newSetpointnumber | undefined–Adjustment preview (2-step interface): while defined, the original setpoint marker dims and a focus-state marker renders at this value.
atSetpointboolean | undefinedfalseManual at-setpoint override; used when autoAtSetpoint is false.
touchingboolean | undefinedfalseUser is physically interacting with the control. Forces focus rendering and suppresses at-setpoint detection while true.
autoAtSetpointboolean | undefinedtrueEnable automatic at-setpoint detection (default true).
autoAtSetpointDeadbandnumber | undefined2Tolerance for auto at-setpoint detection (default 2).
setpointAtZeroDeadbandnumber | undefined0.5Zero-snap tolerance for the marker's equalZero state (default 0.5).
setpointOverrideboolean | undefinedfalseDerive the setpoint color from priority even when loading/off.
animateSetpointboolean | undefinedfalseEnable the CSS-animated confirm transition.
  • Rate of turn: how fast the vessel turns for that rudder angle.
  • Heading: where the bow points.
  • Data integrity: the states a value can be in, and what the crew does.