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
26 extern "C" {
27 #endif
28 
29 
30 /**
31  * @brief Struct containing state of a ringbuffer and pointer to
32  * dynamically allocated memory.
33  */
34 typedef 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
39 } rc_ringbuf_t;
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  */
73 int 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  */
109 int 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  */
124 double 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  */
137 double rc_ringbuf_std_dev(rc_ringbuf_t buf);
138 
139 
140 #ifdef __cplusplus
141 }
142 #endif
143 
144 #endif // RC_RING_BUFFER_H
145 
146 /** @} end group math*/
rc_ringbuf_t rc_ringbuf_empty(void)
Returns an rc_ringbuf_t struct which is completely zero&#39;d out with no memory allocated for it...
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_get_value(rc_ringbuf_t *buf, int position)
Fetches the float which is &#39;position&#39; steps behind the last value added to the buffer.
struct rc_ringbuf_t rc_ringbuf_t
Struct containing state of a ringbuffer and pointer to dynamically allocated memory.
int initialized
flag indicating if memory has been allocated for the buffer
Definition: ring_buffer.h:38
int rc_ringbuf_free(rc_ringbuf_t *buf)
Frees the memory allocated for buffer buf.
double rc_ringbuf_std_dev(rc_ringbuf_t buf)
Returns the standard deviation of all values in the ring buffer.
Struct containing state of a ringbuffer and pointer to dynamically allocated memory.
Definition: ring_buffer.h:34
int rc_ringbuf_insert(rc_ringbuf_t *buf, double val)
Puts a new float into the ring buffer and updates the index accordingly.
int index
index of the most recently added value
Definition: ring_buffer.h:37
int size
number of elements the buffer can hold
Definition: ring_buffer.h:36
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.
double * d
pointer to dynamically allocated data
Definition: ring_buffer.h:35