Force & Tactile Messages (C++)

Force/torque sensing and haptic types in horus::msg::. Include via <horus/msg/force.hpp>.

Quick Reference

TypeKey FieldsUse Case
WrenchStampedforce (Vector3), torque (Vector3), point_of_application (Point3), frame_idForce/torque sensor
ForceCommandtarget_force (Vector3), target_torque (Vector3), force_mode[6], gains[6], max_deviationForce control
ContactInfostate (CONTACT_STATE_*), contact_force, contact_normal (Vector3), contact_point (Point3), confidenceContact detection
HapticFeedbackvibration_intensity, vibration_frequency, duration_seconds, force_feedback (Vector3), pattern_type, enabledHaptic devices
ImpedanceParametersstiffness[6], damping[6], inertia[6], force_limits[6], enabledImpedance control

WrenchStamped — Force/Torque Sensor

horus::msg::WrenchStamped wrench{};
wrench.force.x = 0.0;    // Fx (N)
wrench.force.y = 0.0;    // Fy (N)
wrench.force.z = -9.81;  // Fz (N) — gravity
wrench.torque.x = 0.0;   // Tx (Nm)
wrench.torque.y = 0.1;   // Ty (Nm)
wrench.torque.z = 0.0;   // Tz (Nm)
wrench.timestamp_ns = 0;

ForceCommand — Force Control

horus::msg::ForceCommand cmd{};
cmd.target_force.z = -5.0;   // push down 5N
cmd.force_mode[2] = 1;       // z-axis under force control (1 = force, 0 = position)
cmd.gains[2] = 0.5;          // Kp_fz
cmd.max_deviation.z = 0.02;  // max 2 cm deviation from setpoint
cmd.timeout_seconds = 0.5;   // 0 = no timeout

Stiffness and damping are not ForceCommand fields — they live on ImpedanceParameters as double stiffness[6] / double damping[6] (diagonals ordered [x, y, z, rx, ry, rz]), alongside inertia[6], force_limits[6] and enabled.

ContactInfo — Collision Detection

// In a contact detection node:
auto contact = contact_sub_->recv();
if (contact && contact->get()->state != horus::msg::CONTACT_STATE_NO_CONTACT) {
    double force_n = contact->get()->contact_force;  // magnitude, in Newtons
    horus::log::warn("contact", "Contact detected, force=" + std::to_string(force_n) + "N");
}

state is a uint8_t compared against the CONTACT_STATE_* constants in <horus/msg/force.hpp>: CONTACT_STATE_NO_CONTACT (0), CONTACT_STATE_INITIAL_CONTACT (1), CONTACT_STATE_STABLE_CONTACT (2), CONTACT_STATE_CONTACT_LOSS (3), CONTACT_STATE_SLIDING (4), CONTACT_STATE_IMPACT (5).

HapticFeedback — Haptic Devices

horus::msg::HapticFeedback haptic{};
haptic.vibration_intensity = 0.8f;    // 0.0-1.0
haptic.vibration_frequency = 250.0f;  // Hz
haptic.duration_seconds = 0.5f;
haptic.force_feedback.z = -1.0;       // Vector3 of double, Newtons
haptic.pattern_type = 1;              // 0 = constant, 1 = pulse, 2 = ramp
haptic.enabled = 1;                   // 0 = off, 1 = on
haptic.timestamp_ns = 0;

The three vibration_*/duration_seconds fields are float, while force_feedback is a Vector3 of double. pattern_type and enabled are plain uint8_t — there are no named PATTERN_* constants on the C++ side, so write the literal values above.

ImpedanceParameters — Impedance Control

horus::msg::ImpedanceParameters imp{};
// Each array is a matrix diagonal ordered [x, y, z, rx, ry, rz],
// so index 2 is the z axis.
imp.stiffness[2] = 200.0;    // Kz
imp.damping[2] = 20.0;       // Dz
imp.inertia[2] = 1.0;        // Mz — virtual inertia
imp.force_limits[2] = 30.0;  // Fz_max (N)
imp.enabled = 1;             // 0 = off, 1 = on
imp.timestamp_ns = 0;

Value-initialise with {} and set only the axes you need: every entry you leave alone stays 0, i.e. no stiffness or damping on that axis.

See Also