Skip to content

Language

Currency

SOLID Design in Practice: Plug-and-Play Gimbal Expansion with gimbal-sdk

by AMOVLAB 23 Jul 2025 0 Comments

When the amount of code increases from hundreds to tens of thousands of lines, a small change may cause a chain of red errors; I want to add new functions, but find that the old logic is difficult to start with; when handing over the code, colleagues need to trace it back repeatedly to understand it. In fact, these are all manifestations of failure to implement design principles. This article is intended for you who have a certain C++ foundation but lack system engineering experience.gimbal-sdk For example, I will use visible code and reproducible experiments to quickly understand the five design principles of SOLID, and intuitively feel the immediate benefits it can bring to the project.

01 What is SOLID?

SOLID is an acronym for five words and is a core design concept that every developer who writes complex software must master:

S(Single Responsibility Principle)-Single Responsibility Principle: Each class/module only does one thing.
O(Open/Closed Principle)-Opening and closing principle: New functions can be expanded, but old code should not be touched.
L(Liskov Substitution Principle)-Richter Substitution Principle: Subclasses can safely replace parent classes anywhere.
I(Interface Segregation Principle)-Interface isolation principle: The interface should be small, dedicated, and not bloated.
D(Dependency Inversion Principle)- Dependency inversion principle: The upper-layer code should not rely on the underlying implementation, but on abstraction.

02 Project practice

gimbal-sdk

When working on robot projects, we often encounter this problem: we need to connect to a variety of PTZs (camera or laser equipment that can control rotation), and each PTZ has different protocols and communication methods. If the support is directly "hard-coded", the result is that each time a model is added, the code must be changed significantly. When the communication method is changed (such as changing from serial port to TCP/IP), the system must be started over again. The system becomes more and more bloated and difficult to maintain. AMOVLAB's gimbal-sdk does the opposite. By following SOLID design principles, it allows you to easily expand new models, switch communication methods, and even test each component independently. Adding models, changing protocols, and doing tests all become orderly.

Single Responsibility Principle (SRP)

Application points
Each module should focus on one responsibility to avoid functional clutter.
Project practice
1. IOStreamBase class: It is only responsible for "data stream sending and receiving" and does not care about any protocol packages or control logic.
2. amovGimbalBase and its subclasses: only care about "how to control the PTZ", not what ports are used at the bottom.
Code example

// Communication only
class IOStreamBase {
public:
    virtual size_t write(const uint8_t *buf, size_t len) = 0;
    virtual size_t read(uint8_t *buf, size_t len) = 0;
…
};
// Gimbal control only
class IamovGimbalBase {
public:
    virtual int setGimabalPos (const AMOV_GIMBAL_POS_T &pos);
…
};

Advantages: The code is clear. If you encounter a bug, you only need to check one module. Modifying a certain function will not affect the entire code.

Open-Closed Principle (OCP)

Application points
Support function expansion through inheritance and composition to avoid modifying existing code.
Project practice
1. When adding a new gimbal model, inherit amovGimbalBase and register the factory.
2. When changing the communication protocol, implement a new IOStreamBase subclass.

Code example

class g1GimbalDriver : protected amovGimbalBase { 
    static amovGimbal::amovGimbalBase
*creat(amovGimbal::IOStreamBase *_IO)
    {
        return new g1GimbalDriver(_IO);
    }
};
// Register the factory function in the list
callbackMap amovGimbals =

{{"G1", g1GimbalDriver::creat}};
// New model: no changes needed in the main workflow
auto* gimbal = new amovGimbal::gimbal("G1", io);

Advantages: It is easy to expand, reduces the risk of modification, and the system structure is stable.

Richter Substitution Principle (LSP)

Application points
When using base class pointers or references, there is no need to care about specific subclasses, and program logic is not affected.
Project practice
All gimbals inherit amovGimbalBase, the main process gets a base class pointer, which can be operated uniformly regardless of the specific model (G1/G2/AT10, etc.).

Code example

auto* gimbal = new amovGimbal::gimbal("G1", io);
gimbal->setAngle(0, 0, 0); // Works with G1, G2, and AT10

Advantages: Realize true polymorphism, unified logic, and high code reusability.

Interface Segregation Principle (ISP)

Application points Interfaces should be concise and specific, avoiding unnecessary methods.Project practice 1. IOStreamBase only writes the core reading and writing methods of communication, and does not throw in "logs and tests" together. 2. C and C++ have their own interfaces, and the caller can choose according to needs.Code example

class IOStreamBase {
    virtual size_t write(const uint8_t *buf, size_t len) = 0;
    virtual size_t read(uint8_t *buf, size_t len) = 0;
    // No unrelated methods
};

Advantages: The interface is easy to use, the functions are focused, and redundancy is avoided.

Dependency Inversion Principle (DIP)

Application points
High-level modules should rely on interfaces or abstract classes to avoid direct dependence on underlying implementations.
Project practice
1. The PTZ control module only relies on IOStreamBase and does not need to pay attention to communication details.
2. MockStream can be injected to replace real communication during testing.

Code example

class MockStream : public IOStreamBase { /* Mock communication for testing */ };
amovGimbalBase* gimbal = new G1GimbalDriver(new MockStream());

Advantages: Support module replacement and unit testing to enhance system flexibility.

gimbal-sdk design highlights:

  • Interface priority: All modules rely on abstract interfaces and are completely free from binding to specific hardware and protocols.

  • The division of labor is clear: The factory is responsible for the creation, the driver is only responsible for the movement of the gimbal, the IO is focused on data transmission and reception, and each model does its own thing.

  • Clear hierarchy and strong scalability: The structure is easy to understand, and local modifications can take effect. It is a hands-on example for learning SOLID and layered architecture.

03 How Beginners Learn and Practice

Read from the interface

First read through the core abstractions such as GimbalBase and IOStreamBase to clarify the responsibilities and dependency boundaries of each layer.

write an extension

Add a new virtual PTZ or MockStream to verify the plug-in effect of "access without changing the main process".

Make a counterexample

For example, deliberately write IO and driver in the same category, and then try to add new models to compare maintenance and testing costs.

Continuous review

Every time you read or write a piece of code, pay attention to whether it only does one thing? If we want to add functions, can we not touch the old logic?

Resource Express
The source code has been made available through the SpireCV project.
Source code link:https://gitee.com/amovlab/SpireCV/tree/master/gimbal_ctrl
If you have any questions, or want to learn more about a code example of a certain principle, please leave a message or communicate!

Leave a comment

All blog comments are checked prior to publishing

Thanks for subscribing!

This email has been registered!

Shop the look

Choose Options

Recently Viewed

Edit Option
Back In Stock Notification
Terms & Conditions
What is Lorem Ipsum? Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Why do we use it? It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
this is just a warning
Login
Shopping Cart
0 items