Robot Control Library
ring_buffer.h
Go to the documentation of this file.
1/**
2 * <rc/math/ring_buffer.h>
3 *
4 * @brief ring buffer implementation for double-precision floats
5 *
6 * Ring buffers are FIFO (first in first out) buffers of fixed length which
7 * efficiently boot out the oldest value when full. They are particularly well
8 * suited for storing the last n values in a discrete time filter.
9 *
10 * The user creates their own instance of a buffer and passes a pointer to the
11 * these ring_buf functions to perform normal operations.
12 *
13 * @author James Strawson
14 * @date 2016
15 *
16 * @addtogroup Ring_Buffer
17 * @ingroup Math
18 * @{
19 */
20
21
22#ifndef RC_RING_BUFFER_H
23#define RC_RING_BUFFER_H
24
25#ifdef __cplusplus
26extern "C" {
27#endif
28
29
30/**
31 * @brief Struct containing state of a ringbuffer and pointer to
32 * dynamically allocated memory.
33 */
34typedef struct rc_ringbuf_t {
35 double* d; ///< pointer to dynamically allocated data
36 int size; ///< number of elements the buffer can hold
37 int index; ///< index of the most recently added value
38 int initialized;///< flag indicating if memory has been allocated for the buffer
40
41#define RC_RINGBUF_INITIALIZER {\
42 .d = NULL,\
43 .size = 0,\
44 .index = 0,\
45 .initialized = 0}
46
47/**
48 * @brief Returns an rc_ringbuf_t struct which is completely zero'd out
49 * with no memory allocated for it.
50 *
51 * This is essential for declaring new ring buffers since structs declared
52 * inside of functions are not necessarily zero'd out which can cause the struct
53 * to contain problematic contents leading to segfaults. New ring buffers should
54 * be initialized with this before calling rc_ringbuf_alloc.
55 *
56 * @return empty and ready-to-allocate rc_ringbuf_t
57 */
59
60/**
61 * @brief Allocates memory for a ring buffer and initializes an
62 * rc_ringbuf_t struct.
63 *
64 * If buf is already the right size then it is left untouched. Otherwise any
65 * existing memory allocated for buf is freed to avoid memory leaks and new
66 * memory is allocated.
67 *
68 * @param buf Pointer to user's buffer
69 * @param[in] size Number of elements to allocate space for
70 *
71 * @return Returns 0 on success or -1 on failure.
72 */
73int rc_ringbuf_alloc(rc_ringbuf_t* buf, int size);
74
75/**
76 * @brief Frees the memory allocated for buffer buf.
77 *
78 * Also set the initialized flag to 0 so other functions don't try to access
79 * unallocated memory.
80 *
81 * @param buf Pointer to user's buffer
82 *
83 * @return Returns 0 on success or -1 on failure.
84 */
86
87/**
88 * @brief Sets all values in the buffer to 0.0f and sets the buffer index
89 * back to 0.
90 *
91 * @param buf Pointer to user's buffer
92 *
93 * @return Returns 0 on success or -1 on failure.
94 */
96
97/**
98 * @brief Puts a new float into the ring buffer and updates the index
99 * accordingly.
100 *
101 * If the buffer was full then the oldest value in the buffer is automatically
102 * removed.
103 *
104 * @param buf Pointer to user's buffer
105 * @param[in] val The value to be inserted
106 *
107 * @return Returns 0 on success or -1 on failure.
108 */
109int rc_ringbuf_insert(rc_ringbuf_t* buf, double val);
110
111/**
112 * @brief Fetches the float which is 'position' steps behind the last value
113 * added to the buffer.
114 *
115 * If 'position' is given as 0 then the most recent value is returned. The
116 * position obviously can't be larger than (buffer size - 1).
117 *
118 * @param buf Pointer to user's buffer
119 * @param[in] position steps back in the buffer to fetch the value from
120 *
121 * @return Returns the requested float. Prints an error message and returns
122 * -1.0f on error.
123 */
124double rc_ringbuf_get_value(rc_ringbuf_t* buf, int position);
125
126/**
127 * @brief Returns the standard deviation of all values in the ring buffer.
128 *
129 * Note that if the buffer has not yet been filled completely before calling
130 * this, then the starting values of 0.0f in the unfilled portion of the buffer
131 * will still be part of the calculation.
132 *
133 * @param[in] buf Pointer to user's buffer
134 *
135 * @return Returns the standard deviation of all values in the ring buffer.
136 */
138
139
140#ifdef __cplusplus
141}
142#endif
143
144#endif // RC_RING_BUFFER_H
145
146/** @} end group math*/
int rc_ringbuf_alloc(rc_ringbuf_t *buf, int size)
Allocates memory for a ring buffer and initializes an rc_ringbuf_t struct.
double rc_ringbuf_std_dev(rc_ringbuf_t buf)
Returns the standard deviation of all values in the ring buffer.
double rc_ringbuf_get_value(rc_ringbuf_t *buf, int position)
Fetches the float which is 'position' steps behind the last value added to the buffer.
rc_ringbuf_t rc_ringbuf_empty(void)
Returns an rc_ringbuf_t struct which is completely zero'd out with no memory allocated for it.
int rc_ringbuf_insert(rc_ringbuf_t *buf, double val)
Puts a new float into the ring buffer and updates the index accordingly.
int rc_ringbuf_reset(rc_ringbuf_t *buf)
Sets all values in the buffer to 0.0f and sets the buffer index back to 0.
int rc_ringbuf_free(rc_ringbuf_t *buf)
Frees the memory allocated for buffer buf.
struct rc_ringbuf_t rc_ringbuf_t
Struct containing state of a ringbuffer and pointer to dynamically allocated memory.
Struct containing state of a ringbuffer and pointer to dynamically allocated memory.
Definition: ring_buffer.h:34
int size
number of elements the buffer can hold
Definition: ring_buffer.h:36
int index
index of the most recently added value
Definition: ring_buffer.h:37
int initialized
flag indicating if memory has been allocated for the buffer
Definition: ring_buffer.h:38
double * d
pointer to dynamically allocated data
Definition: ring_buffer.h:35