Skip to content

Commit

Permalink
Updating library with further definitions and return value process
Browse files Browse the repository at this point in the history
  • Loading branch information
Johnnykoch02 committed Feb 18, 2024
1 parent 0df7586 commit 57ac19b
Show file tree
Hide file tree
Showing 12 changed files with 535 additions and 51 deletions.
109 changes: 97 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@
The TerriBull Device Manager is a comprehensive system designed for managing various types of VEX devices. It provides a framework for initializing and controlling devices such as motors, IMUs, and other peripherals using a unified interface. This system is built on top of the PROS library for VEX Robotics, leveraging its functionalities for device communication and control. More specific documentation related to using the library will be coming soon.

## Features
- **Device Support**: Supports a wide range of devices including motors, IMUs, distance sensors, vision sensors, and more.
- **Dynamic Initialization**: Devices can be dynamically initialized with specific configurations such as gear sets and brake modes for motors.
- **Velocity Control**: Allows setting motor velocities with fine-tuned control, considering the gear set configuration.
- **Extensible Design**: Designed to be easily extendable for additional device types and functionalities.
- **Device Management**: from external computers, you can easily control and manage your VEX specific devices on a V5 brain. This can be used to offload compute power to
- **Device Support**: The framework supports a comprehensive range of VEX devices, including motors, IMUs, rotation sensors, distance sensors, vision sensors, and ADI (Analog/Digital Inputs).
- **Dynamic Initialization and Configuration**: Devices can be dynamically initialized and configured with specific parameters such as gear sets for motors, enabling flexible and adaptive use cases.
- **Velocity and Position Control**: Provides API for setting motor velocities and sensor positions, offering precise control over the hardware.
- **Serialization and Deserialization**: Integrated with nanopb for efficient communication, allowing devices to send and receive structured data via serial communication.
- **Extensible Architecture**: Designed with extensibility in mind, making it easy to add support for new devices or functionalities as needed.
- **Unified Device Management**: Centralizes the management of different types of devices, facilitating easier tracking and control of hardware components.
- **Real-Time Updates**: Supports real-time updates of device states, ensuring responsive and synchronous operation of robotics components.
- **Error Handling**: Implements comprehensive error handling mechanisms, providing robustness and reliability in device operations.

## Requirements
- PROS library for VEX Robotics
Expand All @@ -24,7 +29,7 @@ The TerriBull Device Manager is a comprehensive system designed for managing var
2. cd into project

```bash
python python nanopb/generator/nanopb_generator.py --out=. ./include/protos/vex.proto
python nanopb/generator/nanopb_generator.py --out=. ./include/protos/vex.proto
```

- You should now have generated the `.pb.h` and `.pb.c` files.
Expand All @@ -42,11 +47,16 @@ python python nanopb/generator/nanopb_generator.py --out=. ./include/protos/vex.
#include <pb_common.h>
```
Use the following command to automatically do this:
```bash
sed -i '/#include <pb.h>/a #include <pb_encode.h>\n#include <pb_decode.h>\n#include <pb_common.h>' include/protos/vex.pb.h
```

### Creating the obj Files
- Ensure you have `arm-none-eabi` compiler for Cortex

```bash
mkdir ./obj/
mkdir ./obj/ 2>/dev/null || echo "Creating obj/ Directory..."
arm-none-eabi-g++ -c -o ./obj/vex.pb.o ./include/protos/vex.pb.c -I./nanopb/ -I.
arm-none-eabi-g++ -c -o ./obj/pb_encode.o ./nanopb/pb_encode.c -I./nanopb/ -I.
arm-none-eabi-g++ -c -o ./obj/pb_decode.o ./nanopb/pb_decode.c -I./nanopb/ -I.
Expand All @@ -70,25 +80,100 @@ pros build --verbose

## Usage

The DeviceManager class provides a high-level interface to manage and interact with various devices, such as motors and sensors, on a robotics platform. Below are examples of how to initialize a motor, set its velocity, and manage devices with the DeviceManager.

- **Note:** the following examples use placeholders to demonstrate actual values. Remember to replace placeholder values like port, GEAR_SET, BREAK_MODE, and velocity with actual values according to your application needs.

### Initializing a Motor

To initialize a motor with specific parameters, use the `motor_device_initialize` method from the `DeviceManager` class. Provide a `motor_initialize_callback_data` struct with the necessary configuration.

```cpp
#include "DeviceManager.hpp"
#include "TerriBullDevices.hpp"

DeviceManager deviceManager;
motor_initialize_callback_data motorData = {port, GEAR_SET, BREAK_MODE};
deviceManager.motor_device_initialize(motorData);
TerriBull::motor_initialize_callback_data motorData = {port, GEAR_SET, BREAK_MODE};
deviceManager.motor_device_initialize(&motorData);
```
### Setting Motor Velocity
To set the velocity of a motor, use the `motor_device_set_velocity` method with a `motor_set_velocity_callback_data` struct containing the desired velocity and port.
```cpp
motor_set_velocity_callback_data velocityData = {port, velocity};
deviceManager.motor_device_set_velocity(velocityData);
TerriBull::motor_set_velocity_callback_data velocityData = {port, velocity};
deviceManager.motor_device_set_velocity(&velocityData);
```

### Adding and Managing Devices
Devices are managed through the `DeviceManager`, which allows adding, retrieving, and configuring devices through a unified interface.

Devices are managed through the `DeviceManager`, which allows adding, retrieving, and updating devices through a unified interface.

#### Adding a Device

Devices, once initialized, can be added to the `DeviceManager` for easy access and management.

```cpp
MotorDevice motor;
motor.header.port = port;
// Set other motor attributes...

deviceManager.add_device(&motor.header);
```

#### Retrieving a Device

Retrieve a device by its port to update or read its properties.

```cpp
DeviceHeader* device = deviceManager.get_device(port);
if (device != nullptr) {
// Cast to specific device type as needed and interact with it
}
```

#### Updating Devices

The `DeviceManager` can iterate over all managed devices to perform updates, such as reading sensor values or updating motor velocities.

```cpp
deviceManager.update_devices(deltaTime);
```

This method should be called periodically, where `deltaTime` is the time elapsed since the last update, to ensure device states are current.

## DeviceManager.hpp and DeviceManager.cpp

The `DeviceManager` class is defined in `DeviceManager.hpp` and implemented in `DeviceManager.cpp`. It encapsulates the logic for device management, including adding devices, retrieving them by port, and processing messages for device configuration.

- **DeviceManager.hpp**: Declares the `DeviceManager` class, including its methods and internal data structures.
- **DeviceManager.cpp**: Implements the `DeviceManager` class methods, such as device initialization, serialization of messages, and device updates.

## Development

### Adding a New Device to the Library

- For `device.hpp` and `device.cpp`:

1. Define the Device Struct
2. Define the Device Message in proto (Device Struct, the callback data structs, the return value structs)
3. Define the Device functions (Update, Initialize, Set)
4. Define the Callbacks for the functions (port, additional parameters)
5. Recompile using the README instructions


- **Note:** this should be all you need for `device.hpp` and `device.cpp`. Also, some steps are dependent on prior steps, such as defining the callbacks, and defining the probuf Messages.

- For `DeviceManager.cpp`;

1. Add case handling for when new device functions are called in processMessage
2. Add case handling for when a instance of the device is update in update_devices


## Contributors
- Jonathan Koch: `jonathan.koch@caemilusa.com`
-
- Fagan ...: `something@usf.edu`

## License
TODO
Binary file modified firmware/libvex.a
Binary file not shown.
15 changes: 12 additions & 3 deletions include/TerriBull/DeviceManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "TerriBull.hpp"
#include <map>
#define DEVICE_MANAGER_INTERNAL_BUFFER_SIZE 1024

#ifdef __cplusplus

Expand All @@ -20,17 +21,25 @@ extern "C" {

class DeviceManager {
public:

DeviceManager() = default;
~DeviceManager(); // Implement cleanup in the CPP file

bool serializeMessage(const TerriBullDevices_FunctionCall* message, uint8_t* buffer, size_t buffer_size, size_t* message_length);
// bool serializeMessage(const TerriBullDevices_FunctionCall* message, uint8_t* buffer, size_t buffer_size, size_t* message_length);
void add_device(DeviceHeader* device);
void update_devices(float delta);
DeviceHeader* get_device(uint32_t port);
bool processMessage(const uint8_t* buffer, size_t size);

bool is_buffer_ready() const { return this->buffer_ready; }
uint8_t* get_buffer() { return this->buffer; }
private:
std::map<uint32_t, DeviceHeader*> devices;

uint8_t buffer[DEVICE_MANAGER_INTERNAL_BUFFER_SIZE];
bool buffer_ready;
void clear_buffer() {
for (int i = 0; i < DEVICE_MANAGER_INTERNAL_BUFFER_SIZE; i++) this->buffer[i] = 0;
this->buffer_ready = true;
}
};


Expand Down
60 changes: 58 additions & 2 deletions include/TerriBull/Devices/device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,22 @@ typedef struct {
// Other motor-specific members
} MotorDevice;

/**
* Updates the internal state of the motor
*/
void motor_device_update_internal(MotorDevice* motorDevice);

typedef struct {
DeviceHeader header; // First member is the DeviceHeader
double position;
} RotationSensorDevice;

/**
* Updates the internal state of the motor
*/
void rotation_sensor_update_internal(RotationSensorDevice* rotDevice);

// Motor Callbacks:

typedef struct {
uint8_t port; int GEAR_SET; int BREAK_MODE;
Expand All @@ -71,7 +87,21 @@ typedef struct {
int16_t velocity;
} motor_set_velocity_callback_data;

// TODO: Add Get Method

// Rotation Sensors:
typedef struct {
uint8_t port;
} rotation_sensor_initialize_callback_data;

typedef struct {
uint8_t port;
double position;
} rotation_sensor_set_position_callback_data;

typedef struct {
uint8_t port;
} rotation_sensor_reset_position_callback_data;

typedef struct {
DeviceHeader header;
Expand All @@ -97,7 +127,8 @@ typedef struct {
* @param data contains {uint8_t port, int GEAR_SET, int BREAK_MODE}
* @return device_callback_return_code
*/
device_callback_return_code motor_device_initalize(DeviceManager* _motherSys, motor_initialize_callback_data data);
device_callback_return_code motor_device_initalize(DeviceManager* _motherSys, motor_initialize_callback_data data, TerriBullDevices_ReturnData& r_data);

/**
* @brief Should set motors velocity to the proto data
*
Expand All @@ -106,7 +137,32 @@ device_callback_return_code motor_device_initalize(DeviceManager* _motherSys, mo
* @return device_callback_return_code
* This velocity corresponds to different actual speeds depending on the gearset used for the motor. This results in a range of +-100 for E_MOTOR_GEARSET_36, +-200 for E_MOTOR_GEARSET_18, and +-600 for blue. The velocity is held with PID to ensure consistent speed, as opposed to setting the motor’s voltage.
*/
device_callback_return_code motor_device_set_velocity(DeviceManager* _motherSys, motor_set_velocity_callback_data data);
device_callback_return_code motor_device_set_velocity(DeviceManager* _motherSys, motor_set_velocity_callback_data data, TerriBullDevices_ReturnData& r_data);

/**
* @brief Should Initialize rotational sensor device with Port and proto data
*
* @param data contains {uint8_t port}
* @return device_callback_return_code
*/
device_callback_return_code rotation_sensor_initialize(DeviceManager* _motherSys, rotation_sensor_initialize_callback_data data, TerriBullDevices_ReturnData& r_data);

/**
* @brief Set the Rotation Sensor position reading to a desired rotation value This function uses the following values of errno when an error state is reached: ENXIO - The given value is not within the range of V5 ports (1-21). ENODEV - The port cannot be configured as an Rotation Sensor
*
* @param port – The V5 Rotation Sensor port number from 1-21
* @param data – contains {uint8_t port, double position} position in terms of ticks
* @return device_callback_return_code
*/
device_callback_return_code rotation_sensor_set_position(DeviceManager* _motherSys, rotation_sensor_set_position_callback_data data, TerriBullDevices_ReturnData& r_data);

/**
* @brief Reset Rotation Sensor Reset the current absolute position to be the same as the Rotation Sensor angle. This function uses the following values of errno when an error state is reached: ENXIO - The given value is not within the range of V5 ports (1-21). ENODEV - The port cannot be configured as an Rotation Sensor
*
* @param port – The V5 Rotation Sensor port number from 1-21
* @param data – contains {uint8_t port}
* @return device_callback_return_code
*/
device_callback_return_code rotation_sensor_reset_position(DeviceManager* _motherSys, rotation_sensor_reset_position_callback_data data, TerriBullDevices_ReturnData& r_data);

#endif
2 changes: 2 additions & 0 deletions include/TerriBull/SerialController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <string>
#include <mutex>
#include <cstring>
#include <sstream>

using namespace std;

Expand All @@ -46,6 +47,7 @@ class SerialController {
DeviceManager* motherSys;

void copyStringToBuffer(const std::string& input, uint8_t* buffer, size_t buffer_size);
std::string CopyUInt8BufferToString(uint8_t* buffer, size_t b_size);

public:

Expand Down
1 change: 1 addition & 0 deletions include/pros/apix.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ typedef enum v5_device_e {
E_DEVICE_OPTICAL = 16,
E_DEVICE_GPS = 20,
E_DEVICE_SERIAL = 129,
E_DEVICE_CONTROLLER = 242,
E_DEVICE_GENERIC __attribute__((deprecated("use E_DEVICE_SERIAL instead"))) = E_DEVICE_SERIAL,
E_DEVICE_UNDEFINED = 255
} v5_device_e_t;
Expand Down
20 changes: 20 additions & 0 deletions include/protos/vex.pb.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ PB_BIND(TerriBullDevices_DeviceHeader, TerriBullDevices_DeviceHeader, AUTO)
PB_BIND(TerriBullDevices_MotorDevice, TerriBullDevices_MotorDevice, AUTO)


PB_BIND(TerriBullDevices_RotationSensorDevice, TerriBullDevices_RotationSensorDevice, AUTO)


PB_BIND(TerriBullDevices_IMUAccel, TerriBullDevices_IMUAccel, AUTO)


Expand All @@ -27,6 +30,15 @@ PB_BIND(TerriBullDevices_MotorInitializeCallbackData, TerriBullDevices_MotorInit
PB_BIND(TerriBullDevices_MotorSetVelocityCallbackData, TerriBullDevices_MotorSetVelocityCallbackData, AUTO)


PB_BIND(TerriBullDevices_RotationSensorInitializeCallbackData, TerriBullDevices_RotationSensorInitializeCallbackData, AUTO)


PB_BIND(TerriBullDevices_RotationSensorSetPositionCallbackData, TerriBullDevices_RotationSensorSetPositionCallbackData, AUTO)


PB_BIND(TerriBullDevices_RotationSensorResetPositionCallbackData, TerriBullDevices_RotationSensorResetPositionCallbackData, AUTO)


PB_BIND(TerriBullDevices_DeviceValue, TerriBullDevices_DeviceValue, AUTO)


Expand All @@ -41,3 +53,11 @@ PB_BIND(TerriBullDevices_ReturnData, TerriBullDevices_ReturnData, AUTO)



#ifndef PB_CONVERT_DOUBLE_FLOAT
/* On some platforms (such as AVR), double is really float.
* To be able to encode/decode double on these platforms, you need.
* to define PB_CONVERT_DOUBLE_FLOAT in pb.h or compiler command line.
*/
PB_STATIC_ASSERT(sizeof(double) == 8, DOUBLE_MUST_BE_8_BYTES)
#endif

Loading

0 comments on commit 57ac19b

Please sign in to comment.