Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ecdcbbe
♻️ refactor(driver factory): Call serial port open from driver constr…
NestorDP Feb 1, 2026
b0b2ac1
♻️ refactor(driver) Remove parameterized contructor from virtual class
NestorDP Feb 1, 2026
e8f3215
📝 docs(driver): Update UML class diagram
NestorDP Feb 1, 2026
2d0eaa2
🎨 style(driver test): Remove uncrustify failure
NestorDP Feb 1, 2026
13c1140
♻️ refactor(serial_port): Create new enu class to naming errors, upda…
NestorDP Feb 2, 2026
bea5169
📝 docs(driver): Inherite descriptions comments from virtual class
NestorDP Feb 2, 2026
6d164e0
✨ feat(driver): Create mapSerialError function member
NestorDP Feb 2, 2026
2ca76e0
♻️ refactor(serial_port): Create cheks errors for open and close func…
NestorDP Feb 2, 2026
0939843
♻️ refactor(serial_port): Remove default catch
NestorDP Feb 3, 2026
5e8980f
✨ feat(driver): Create init function member
NestorDP Feb 3, 2026
ec5bee9
📝 docs(driver): Update UML class diagram
NestorDP Feb 3, 2026
f435009
🎨 style(driver test): Remove uncrustify and cpplint failures
NestorDP Feb 3, 2026
16a9944
📝 docs(driver): Fix typo in documentation comments
NestorDP Feb 4, 2026
85e286e
🎨 style(serial port): Fix wrong use of spaces
NestorDP Feb 4, 2026
1c40ad4
✅ test(driver): Fix comment
NestorDP Feb 4, 2026
794340c
📝 docs(driver): Fix parameter name in documentation comment
NestorDP Feb 4, 2026
1ec12f6
♻️ refactor(serial_port) Check buffer boundaries (CWE-120, CWE-20)
NestorDP Feb 4, 2026
7d647d1
♻️ refactor(driver) Map all serial errors in mapSerialError function
NestorDP Feb 4, 2026
6e9634c
♻️ refactor(serial_port) Make Check buffer boundaries explicit
NestorDP Feb 4, 2026
0d76b77
♻️ refactor(serial_port) Ignore codacy boundary check
NestorDP Feb 4, 2026
79d2e27
🧹 cleanup(serial_port): Remove ignore codacy boundary check
NestorDP Feb 4, 2026
20a3079
🐛 fix(serial): Ignore thrwo from serial.close
NestorDP Feb 5, 2026
ca14b82
🛠️ chore(little_base cmake): Upgrae the C++ standard to 23
NestorDP Feb 5, 2026
5e2990b
♻️ refactor(driver): Call driver init from factory create
NestorDP Feb 5, 2026
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
Binary file modified docs/figures/driver_class_diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion littlebot_base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20)
project(littlebot_base)

if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 23)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
Expand Down
31 changes: 13 additions & 18 deletions littlebot_base/include/littlebot_base/i_littlebot_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,6 @@ class ILittlebotDriver
*/
static constexpr char kStatusChar{'S'};

/**
* @brief Construct a new Littlebot Driver object
*
* @param serial_port Shared pointer to the serial port interface
* @param rt_buffer Shared pointer to the real-time buffer interface for wheel data
*/
ILittlebotDriver(
std::shared_ptr<ISerialPort> serial_port,
std::shared_ptr<IRTBuffer<WheelRTData>> rt_state_buffer,
std::shared_ptr<IRTBuffer<WheelRTData>> rt_command_buffer,
const std::vector<std::string> & joint_names)
{
(void)serial_port;
(void)rt_state_buffer;
(void)rt_command_buffer;
(void)joint_names;
}

/**
* @brief Prevent copy and assignment
*/
Expand All @@ -69,6 +51,13 @@ class ILittlebotDriver
*/
virtual ~ILittlebotDriver() = default;

/**
* @brief Initialize the driver
*
* @return DriverError The result of the initialization
*/
virtual DriverError init() noexcept = 0;

/**
* @brief Read the current state from the RT buffer
*
Expand Down Expand Up @@ -120,6 +109,12 @@ class ILittlebotDriver
* @return const DriverErrorCounters& Reference to the error counters structure
*/
virtual const DriverErrorCounters & getErrorCounters() const noexcept = 0;

protected:
/**
* @brief Default constructor for the ILittlebotDriver class
*/
ILittlebotDriver() = default;
};

} // namespace littlebot_base
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@

#pragma once

#include <expected>
#include <memory>
#include <string>
#include <vector>

#include "littlebot_base/types.hpp"

namespace littlebot_base
{

Expand All @@ -29,7 +32,7 @@ class ILittlebotDriverFactory
public:
virtual ~ILittlebotDriverFactory() = default;

virtual std::shared_ptr<ILittlebotDriver> create(
virtual std::expected<std::shared_ptr<ILittlebotDriver>, DriverError> create(
const std::string & port,
int baudrate,
const std::vector<std::string> & joint_names) = 0;
Expand Down
58 changes: 47 additions & 11 deletions littlebot_base/include/littlebot_base/i_serial_port.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,34 +30,67 @@
namespace littlebot_base
{

enum class SerialError
{
None,
PortUnavailable,
InsufficientPermissions,
ConfigBaudrateFailed,
ReadFailed,
WriteFailed,
AlreadyOpen,
NotOpen,
NotClosed,
Unknown
};

class ISerialPort
{
public:
/**
* @brief Maximum size of a frame that can be sent/received
*/
static constexpr size_t kMaxFrameSize = 256;

/**
* @brief Deconstructor for the ISerialPort class
*
*/
virtual ~ISerialPort() = default;

/**
* @brief Open the serial port (uses default or stored parameters)
* @brief Open the serial port
*
* @param port Serial port device path (e.g., "/dev/ttyUSB0")
* @param baudrate Baud rate for the serial communication
* @return SerialError indicating success or type of failure
*/
virtual bool open(std::string port, int baudrate) = 0;
virtual SerialError open(std::string port, int baudrate) noexcept = 0;

/**
* @brief Close the serial port
*
* @return SerialError indicating success or type of failure
*/
virtual void close() = 0;
virtual SerialError close() noexcept = 0;

/**
* @brief Read Packet from the serial port
*
* @param payload Vector to store the read packet data.
* Implementations must ensure the frame size never exceeds kMaxFrameSize.
* @return Number of bytes read
*/
virtual int read(std::vector<uint8_t> & payload) = 0;
virtual int read(std::vector<uint8_t> & payload) noexcept = 0;

/**
* @brief Write Packet to the serial port
*
* @param payload Vector containing the packet data to write
* payload.size() must be <= kMaxFrameSize.
* @return Number of bytes written
*/
virtual int write(const std::vector<uint8_t> & payload) = 0;
virtual int write(const std::vector<uint8_t> & payload) noexcept = 0;

/**
* @brief Check if the serial port is open
Expand Down Expand Up @@ -85,23 +118,26 @@ class ISerialPort
/**
* @brief Read data stream from the serial port
*/
virtual void readStream() = 0;
virtual void readStream() noexcept = 0;

/**
* @brief Get data from the received packet
*
* @param buffer Shared pointer to string buffer to store received data
* @return true if a complete frame was extracted
* @return false if no complete frame was available
*/
virtual bool tryExtractFrame(std::vector<uint8_t> & payload) = 0;
virtual bool tryExtractFrame(std::vector<uint8_t> & payload) noexcept = 0;

/**
* @brief Build packet to be sent through serial port
*
* @param buffer Shared pointer to string buffer to store data to be sent
* @param payload Vector containing the packet data to send
* @param frame String to store the built packet
*/
virtual void buildFrame(
const std::vector<uint8_t> & payload,
std::string & frame) = 0;
std::string & frame) noexcept = 0;

/**
* @brief Buffer to store received data
Expand All @@ -114,12 +150,12 @@ class ISerialPort
libserial::Serial serial_;

/**
* @brief Caracter to start the message
* @brief Character to start the message
*/
static constexpr char kStartByte{'['};

/**
* @brief Caracter to end the message
* @brief Character to end the message
*/
static constexpr char kEndByte{']'};

Expand Down
63 changes: 49 additions & 14 deletions littlebot_base/include/littlebot_base/littlebot_driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,72 +35,97 @@ class LittlebotDriver : public ILittlebotDriver
* @brief Construct a new Littlebot Driver object
*
* @param serial_port Shared pointer to the serial port interface
* @param rt_buffer Shared pointer to the real-time buffer interface for wheel data
* @param rt_state_buffer Shared pointer to the real-time buffer interface for wheel state data
* @param rt_command_buffer Shared pointer to the real-time buffer interface for wheel command data
* @param joint_names Vector of joint names
* @param port Serial port name
* @param baudrate Serial port baudrate
*/
LittlebotDriver(
std::shared_ptr<ISerialPort> serial_port,
std::shared_ptr<IRTBuffer<WheelRTData>> rt_state_buffer,
std::shared_ptr<IRTBuffer<WheelRTData>> rt_command_buffer,
const std::vector<std::string> & joint_names);
const std::vector<std::string> & joint_names,
std::string port,
int baudrate);

~LittlebotDriver() override = default;

/**
* @brief Initialize the driver
*
* \inheritdoc
*
* Override the virtual method from ILittlebotDriver
*/
DriverError init() noexcept override;

/**
* @brief Read the current state from the RT buffer
*
* @param state Reference to WheelRTData structure to store the read data
* \inheritdoc
*
* @note This method is RT-safe (control loop)
* Override the virtual method from ILittlebotDriver
*/
void readRTData(WheelRTData & state) const noexcept override;

/**
* @brief Write the command to the RT buffer
*
* @param command Reference to WheelRTData structure containing the command data
* \inheritdoc
*
* @note This method is RT-safe (control loop)
* Override the virtual method from ILittlebotDriver
*/
void writeRTData(const WheelRTData & command) noexcept override;

/**
* @brief Receive data from the hardware and update the RT buffer
*
* @return true if data was received successfully
* @return false if an error occurred
* \inheritdoc
*
* @note This method is NOT RT-safe (executor / IO thread)
* Override the virtual method from ILittlebotDriver
*/
bool requestStatus() noexcept override;

/**
* @brief Send command data to the hardware
*
* @return true if data was sent successfully
* @return false if an error occurred
* \inheritdoc
*
* @note This method is NOT RT-safe (executor / IO thread)
* Override the virtual method from ILittlebotDriver
*/
bool sendCommand() noexcept override;

/**
* @brief Get the last error that occurred
*
* @return DriverError The last error code
* \inheritdoc
*
* Override the virtual method from ILittlebotDriver
*/
DriverError getLastError() const noexcept override {return last_error_;}

/**
* @brief Get the error counters
*
* @return const DriverErrorCounters& Reference to the error counters structure
* \inheritdoc
*
* Override the virtual method from ILittlebotDriver
*/
const DriverErrorCounters & getErrorCounters() const noexcept override
{
return error_counters_;
}

private:
/**
* @brief Map SerialError to DriverError
*
* @param error SerialError to map
* @return DriverError Mapped DriverError
*/
static DriverError mapSerialError(SerialError error) noexcept;

/**
* @brief Error counters for the driver
*/
Expand All @@ -126,6 +151,16 @@ class LittlebotDriver : public ILittlebotDriver
*/
std::shared_ptr<IRTBuffer<WheelRTData>> rt_command_buffer_;

/**
* @brief Serial port name
*/
std::string port_;

/**
* @brief Serial port baudrate
*/
int baudrate_{0};

/**
* @brief Vector of wheels (Not RT-safe)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@

#pragma once

#include <expected>
#include <memory>
#include <string>
#include <vector>

#include "littlebot_base/i_littlebot_driver_factory.hpp"

namespace littlebot_base
{
class LittlebotDriverFactory : public ILittlebotDriverFactory
{
public:
std::shared_ptr<ILittlebotDriver> create(
std::expected<std::shared_ptr<ILittlebotDriver>, DriverError> create(
const std::string & port,
int baudrate,
const std::vector<std::string> & joint_names) override;
Expand Down
Loading
Loading