Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/agents/reviewer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ End with totals + verdict: APPROVE / REQUEST CHANGES.
- [ ] SOLID: one concern per class, constructor injection, depend on abstractions, no duplicated logic.

**Interfaces & errors (WARNING)**
- [ ] `virtual ~I() = default` — never `= 0`. No exceptions — `std::optional`/status enums.
- [ ] Interfaces: `protected:` non-virtual `~I() = default` — no `virtual` or `= 0` destructor, no ownership or deletion through an interface pointer. No exceptions — `std::optional`/status enums.

**Testing (WARNING)**
- [ ] `TEST_F` on `float` — no `TYPED_TEST`, no multi-type, never plain `TEST()`.
Expand Down
2 changes: 1 addition & 1 deletion .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Essentials (full detail in AGENTS.md):
- **Embedded** — no `#pragma GCC optimize` / `optimize` attribute (they block inlining); the consumer sets optimization flags per TU; `OPTIMIZE_FOR_SPEED` (forced inlining) on hot paths.
- **No comments** (except license/NOLINT). Allman braces, brace-init, PascalCase/camelCase.
- **Tests** — `TEST_F` on `float`, `StrictMock` only, never plain `TEST()`, no redundant cases.
- **No exceptions** — `std::optional`/status enums; interfaces `virtual ~I() = default`.
- **No exceptions** — `std::optional`/status enums; interfaces get a `protected:` non-virtual `~I() = default`, never a virtual destructor.
- **Be terse** — minimal prose; report file paths + pass/fail.
2 changes: 1 addition & 1 deletion .github/instructions/robotics-cpp.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Use `math::IsFinite` for finiteness checks: a consumer may still build with `-ff
- SOLID principles — constructor injection, depend on abstractions
- DRY — extract shared logic into helpers or templates
- RAII for resource management
- **No pure virtual destructors**: Never declare `virtual ~Interface() = 0`. Pure virtual destructors force the compiler to emit a thunk and a separate body, wasting memory on embedded targets. Use `virtual ~Interface() = default` if a virtual destructor is required, or omit it entirely when the class is never deleted through a base pointer.
- **Protected, non-virtual interface destructors**: declare `~Interface() = default` in a `protected:` section, never `virtual ~Interface()` (defaulted or `= 0`). A virtual destructor puts a deleting destructor in every implementation's vtable, which links `operator delete` (and with it `malloc`/`free`) into heap-free firmware, and under multiple inheritance adds a thunk per base. The protected destructor makes deletion through an interface pointer a compile error. Concrete classes declare no destructor unless they need one, and callers hold the concrete type rather than a `std::unique_ptr` to the interface.
- No virtual calls in ISR-callable or real-time critical paths

## Documentation — MANDATORY
Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ and included as `numerical/<domain>/…`.

## Interfaces & errors

- Interfaces = pure virtual classes; `virtual ~I() = default` — **never** `= 0` destructors.
- Interfaces = pure virtual classes with a `protected:`, non-virtual `~I() = default` — **never** a `virtual` or `= 0` destructor. A virtual one puts a deleting destructor in every vtable, which links `operator delete`/`free` into heap-free firmware.
- Concrete classes declare no destructor unless they need one. Never own or delete through an interface pointer (no `std::unique_ptr<I>`): hold the concrete type, pass `I&`.
- No exceptions. Use `std::optional<T>` or status enums. `assert`/`really_assert` for preconditions.
- SOLID + DIP: constructor injection; depend on abstractions. RAII. No virtual calls in real-time paths.

Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ Essentials (full detail in AGENTS.md):
- **Embedded** — no `#pragma GCC optimize` / `optimize` attribute (they block inlining); the consumer sets optimization flags per TU; `OPTIMIZE_FOR_SPEED` (forced inlining) on hot paths.
- **No comments** (except license/NOLINT). Allman braces, brace-init, PascalCase/camelCase.
- **Tests** — `TEST_F` on `float`, `StrictMock` only, never plain `TEST()`, no redundant cases.
- **No exceptions** — `std::optional`/status enums; interfaces `virtual ~I() = default`.
- **No exceptions** — `std::optional`/status enums; interfaces get a `protected:` non-virtual `~I() = default`, never a virtual destructor.
- **Be terse** — minimal prose; report file paths + pass/fail.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ if (NOT TARGET numerical.math)
FetchContent_Declare(
numerical_toolbox
GIT_REPOSITORY https://github.com/embedded-pro/numerical-toolbox-cpp.git
GIT_TAG adfc10d342591df8e46a0b1f0a91329bc76023e0 # main
GIT_TAG 63c9b91f4f6f1b306bc15fbf59d01a106da02697 # main
)

set(NUMERICAL_TOOLBOX_ENABLE_OPTIMIZATIONS ${ROBOTICS_TOOLBOX_ENABLE_OPTIMIZATIONS} CACHE BOOL "" FORCE)
Expand Down
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ this roadmap needs that upstream does not ship yet are specified and built upstr
Generic algorithms live in numerical-toolbox-cpp and are referenced here as **NT** plus its
master-list item number (NT53 is upstream item 53). A robotics item that depends on one needs a
numerical-toolbox pin that ships it. NT53–NT65 have shipped upstream, and their links point to the upstream
docs; using them needs a pin at or after `1f6d717` (the current pin, `adfc10d`, predates them).
docs; the current pin (`63c9b91`) includes them.

| # | Component | Upstream module | Spec / doc | Needed by |
|------|-------------------------------------------------------|----------------------|-----------------------------------|----------------------------------------------------------------------------|
Expand Down
2 changes: 1 addition & 1 deletion roadmap/dynamics/ChainDynamicsModel/implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ library turns a link description into those interfaces. This adapter does: it im

```cpp
template<typename T, std::size_t Dof> # static_assert(std::is_floating_point_v<T>); instantiated for float
class InverseDynamicsModel: # new interface, virtual ~InverseDynamicsModel() = default
class InverseDynamicsModel: # new interface, protected ~InverseDynamicsModel() = default
virtual StateVector ComputeInverseDynamics(const StateVector& q, const StateVector& qDot,
const StateVector& qDDot) const = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class CoriolisMatrix: # stateless
JointVector TransposeTimesVelocity(links, q, q̇) const # Cᵀ(q, q̇) q̇

template<typename T, std::size_t Dof, std::size_t NumParams>
class InertialRegressor: # interface, virtual ~InertialRegressor() = default
class InertialRegressor: # interface, protected ~InertialRegressor() = default
virtual Matrix<T, Dof, NumParams> Compute(q, q̇, q̇r, q̈r) const = 0 # Y with Y·π = M q̈r + C q̇r + g

template<typename T, std::size_t NumLinks>
Expand Down
2 changes: 1 addition & 1 deletion roadmap/kinematics/GeometricJacobian/implementation.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class GeometricJacobian: # stateless

template<typename T, std::size_t TaskDim, std::size_t Dof> # DI seam used by all task-space controllers
class JacobianProvider:
virtual ~JacobianProvider() = default
protected ~JacobianProvider() = default # non-virtual; never deleted through the interface
virtual math::Matrix<T, TaskDim, Dof> Jacobian(const JointVector& q) const = 0
virtual math::Vector<T, TaskDim> BiasAcceleration(const JointVector& q, const JointVector& qDot) const = 0 # J̇·q̇
virtual SE3Transform<T> ToolPose(const JointVector& q) const = 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ definition: CubicSplineTrajectory spec → Data structures).
template<typename T, std::size_t Dof> using JointVector = math::Vector<T, Dof>

template<typename T, std::size_t Dof> # static_assert(std::is_floating_point_v<T>); instantiated for float
class PathGeometry: # DI, virtual ~PathGeometry() = default — fixed path q(s), s ∈ [0, 1]
class PathGeometry: # DI, protected ~PathGeometry() = default — fixed path q(s), s ∈ [0, 1]
virtual JointVector Position(T s) const = 0 # q(s)
virtual JointVector FirstDerivative(T s) const = 0 # q'(s)
virtual JointVector SecondDerivative(T s) const = 0 # q''(s)
Expand All @@ -29,7 +29,7 @@ struct JointBounds:
JointVector velocityMax # q̇max > 0

template<typename T, std::size_t Dof>
class JointLimits: # DI, virtual ~JointLimits() = default
class JointLimits: # DI, protected ~JointLimits() = default
virtual PathCoefficients<T, Dof> Coefficients(T s) const = 0
virtual const JointBounds<T, Dof>& Bounds() const = 0

Expand Down
5 changes: 3 additions & 2 deletions robotics/dynamics/EulerLagrangeDynamics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ namespace dynamics
using StateVector = math::Vector<T, Dof>;
using MassMatrix = math::SquareMatrix<T, Dof>;

virtual ~EulerLagrangeDynamics() = default;

virtual MassMatrix ComputeMassMatrix(const StateVector& q) const = 0;
virtual StateVector ComputeCoriolisTerms(const StateVector& q, const StateVector& qDot) const = 0;
virtual StateVector ComputeGravityTerms(const StateVector& q) const = 0;

protected:
~EulerLagrangeDynamics() = default;
};
}
5 changes: 3 additions & 2 deletions robotics/dynamics/NewtonEulerBody.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ namespace dynamics
using Vector3 = math::Vector<T, 3>;
using InertiaMatrix = math::SquareMatrix<T, 3>;

virtual ~NewtonEulerBody() = default;

virtual T ComputeMass() const = 0;
virtual InertiaMatrix ComputeInertia() const = 0;

protected:
~NewtonEulerBody() = default;
};
}
Loading