import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire"; import { Empty } from "./google/protobuf/empty"; export declare const protobufPackage = ""; export interface ControlAxis { /** * Entity to subscribe under. Empty string => connector's own * --entity-id (the typical case: a companion-board joystick driver * publishing under the same vehicle's namespace). */ entityId: string; /** * Keelson subject to subscribe to. Must be a TimestampedFloat-valued * subject. Common picks: joystick_x_pct (steering), joystick_y_pct * (throttle), wheel_position_pct (helm wheel), lever_position_pct * (engine telegraph), joystick_rt_pct (right-trigger as accelerator). */ subject: string; /** Source-id glob pattern within the entity. */ sourceId: string; /** * Source range hint. False (default) = bipolar source in [-100, 100], * 0 = neutral; we map to [-1.0, 1.0] by dividing by 100. True = * unipolar source in [0, 100] (e.g. joystick_rt_pct, a trigger); * we map raw=0 to 0.0 (neutral) and raw=100 to +1.0 (full forward). * Reverse is not reachable through a unipolar source; use a bipolar * source if you need it. */ unipolar: boolean; /** * Flip the sign after scaling. Useful when the producer's positive * direction is opposite the autopilot's (e.g. some sticks publish * positive Y for backward). */ invert: boolean; } export interface ControlAxisMapping { /** * ------------------------------------------------------------------- * Contract for publishers feeding these axes * ------------------------------------------------------------------- * Publishers MUST publish continuously (on a fixed cadence, NOT * on-change-only) for the entire duration they are driving an axis * — including when the value isn't changing. Recommended rate: * 10-20 Hz. * * This is load-bearing: the connector is sample-driven (one MAVLink * RC_CHANNELS_OVERRIDE per arriving Zenoh sample for mavlink2keelson; * equivalent framing for other actuation transports), and ArduPilot * times the override out after ~3 s of no frames. Silence on the * Zenoh wire is the stop signal — so an on-change-only publisher * looks identical to a publisher dropout once the value stops * changing. Make sure your upstream emits whether or not the value * changed. * ------------------------------------------------------------------- * * Per-axis subject mapping. v1 (ArduPilot Rover frame) recognizes * only "steering" and "throttle" — they resolve to the autopilot's * RCMAP_ROLL and RCMAP_THROTTLE RC channels respectively, via the * existing channel autodetect. Unknown axis names cause the RPC to * reply with ErrorResponse listing the allowed values. * * Future Plane / Copter support would add "roll", "pitch", "yaw". * Unmapped axes default to neutral PWM (1500us) in the emitted * RC_CHANNELS_OVERRIDE — useful for layered manual+auto control * ("autonomy steers, joystick controls throttle"). */ axes: { [key: string]: ControlAxis; }; /** * Minimum interval between RC_OVERRIDE emissions, in seconds. * 0 (default) = emit on every axis arrival. With both axes updating * at the same producer cadence this doubles the wire rate; setting * min_interval_s to e.g. 0.05 caps the output at 20 Hz. */ minIntervalS: number; /** * Dead-man: if any mapped axis's last sample is older than this * (in seconds, wall clock) the connector stops emitting * RC_CHANNELS_OVERRIDE, letting ArduPilot's own RC override timer * expire and return control to the autopilot mode. This is what * catches a Zenoh-side dropout — without it, the override would * survive a network split indefinitely. * * 0 (unset) = use the connector default of 1.0 s, which assumes * upstreams publish at >= 10 Hz (lots of headroom for jitter). Set * explicitly to tighten or loosen; values above ArduPilot's * RC_OVERRIDE_TIME (~3 s default) are pointless because ArduPilot * would time out first. The dead-man cannot be disabled by design. */ maxAxisAgeS: number; } export interface ControlAxisMapping_AxesEntry { key: string; value: ControlAxis | undefined; } export interface ControlAxisMappingAck { } export declare const ControlAxis: MessageFns; export declare const ControlAxisMapping: MessageFns; export declare const ControlAxisMapping_AxesEntry: MessageFns; export declare const ControlAxisMappingAck: MessageFns; export interface VehicleControl { /** * Replace the active control-axis mapping atomically. An empty axes * map = stop driving (undeclare every axis subscriber). Calling this * RPC is the only way to make the vehicle drivable after a connector * start. */ set_control_mapping(request: ControlAxisMapping): Promise; /** * Return the currently-active mapping. Useful for operators * inspecting state set by another client. */ get_control_mapping(request: Empty): Promise; } export declare const VehicleControlServiceName = "VehicleControl"; export declare class VehicleControlClientImpl implements VehicleControl { private readonly rpc; private readonly service; constructor(rpc: Rpc, opts?: { service?: string; }); set_control_mapping(request: ControlAxisMapping): Promise; get_control_mapping(request: Empty): Promise; } interface Rpc { request(service: string, method: string, data: Uint8Array): Promise; } type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; export type DeepPartial = T extends Builtin ? T : T extends globalThis.Array ? globalThis.Array> : T extends ReadonlyArray ? ReadonlyArray> : T extends {} ? { [K in keyof T]?: DeepPartial; } : Partial; type KeysOfUnion = T extends T ? keyof T : never; export type Exact = P extends Builtin ? P : P & { [K in keyof P]: Exact; } & { [K in Exclude>]: never; }; export interface MessageFns { encode(message: T, writer?: BinaryWriter): BinaryWriter; decode(input: BinaryReader | Uint8Array, length?: number): T; fromJSON(object: any): T; toJSON(message: T): unknown; create, I>>(base?: I): T; fromPartial, I>>(object: I): T; } export {};