diff --git a/.gitignore b/.gitignore index bc961ca..e303e2c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,6 @@ *.bin *.elf -# Template -template/ - # PROS bin/ .vscode/ diff --git a/Makefile b/Makefile index bb6f37d..d1ac8ba 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ EXCLUDE_COLD_LIBRARIES:= # Set this to 1 to add additional rules to compile your project as a PROS library template IS_LIBRARY:=1 LIBNAME:=liblvgl -VERSION:=8.3.8 +VERSION:=8.3.9 # EXCLUDE_SRC_FROM_LIB= $(SRCDIR)/unpublishedfile.c # this line excludes opcontrol.c and similar files EXCLUDE_SRC_FROM_LIB+=$(foreach file, $(SRCDIR)/main,$(foreach cext,$(CEXTS),$(file).$(cext)) $(foreach cxxext,$(CXXEXTS),$(file).$(cxxext))) @@ -43,9 +43,9 @@ TEMPLATE_FILES=$(INCDIR)/liblvgl/** ########## Nothing below this line should be edited by typical users ########### -include ./common.mk -TEMPLATE_KERNEL_SEMVER:=">=4.0.0" +TEMPLATE_KERNEL_SEMVER:=">=4.2.0" -template: clean-template library +template:: clean-template library $(VV)mkdir -p $(TEMPLATE_DIR) @echo "Moving template files to $(TEMPLATE_DIR)" $Dcp --parents -r $(TEMPLATE_FILES) $(TEMPLATE_DIR) diff --git a/common.mk b/common.mk index 33efe87..40da70c 100644 --- a/common.mk +++ b/common.mk @@ -1,7 +1,7 @@ ARCHTUPLE=arm-none-eabi- DEVICE=VEX EDR V5 -MFLAGS=-mcpu=cortex-a9 -mfpu=neon-fp16 -mfloat-abi=softfp -Os -g +MFLAGS=-mcpu=cortex-a9 -mfpu=neon-fp16 -mfloat-abi=hard -Os -g -mthumb CPPFLAGS=-D_POSIX_THREADS -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_TIMERS -D_POSIX_MONOTONIC_CLOCK GCCFLAGS=-ffunction-sections -fdata-sections -fdiagnostics-color -funwind-tables @@ -20,8 +20,8 @@ WARNFLAGS+=-Wno-psabi SPACE := $() $() COMMA := , -C_STANDARD?=gnu11 -CXX_STANDARD?=gnu++20 +C_STANDARD?=gnu2x +CXX_STANDARD?=gnu++23 DEPDIR := .d $(shell mkdir -p $(DEPDIR)) @@ -34,7 +34,7 @@ LIBRARIES+=$(wildcard $(FWDIR)/*.a) EXCLUDE_COLD_LIBRARIES+=$(FWDIR)/libc.a $(FWDIR)/libm.a COLD_LIBRARIES=$(filter-out $(EXCLUDE_COLD_LIBRARIES), $(LIBRARIES)) wlprefix=-Wl,$(subst $(SPACE),$(COMMA),$1) -LNK_FLAGS=--gc-sections --start-group $(strip $(LIBRARIES)) -lgcc -lstdc++ --end-group -T$(FWDIR)/v5-common.ld +LNK_FLAGS=--gc-sections --start-group $(strip $(LIBRARIES)) -lgcc -lstdc++ --end-group -T$(FWDIR)/v5-common.ld --no-warn-rwx-segments --sort-section=alignment --sort-common ASMFLAGS=$(MFLAGS) $(WARNFLAGS) CFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=$(C_STANDARD) @@ -188,14 +188,14 @@ quick: $(DEFAULT_BIN) all: clean $(DEFAULT_BIN) -clean: +clean:: @echo Cleaning project -$Drm -rf $(BINDIR) -$Drm -rf $(DEPDIR) ifeq ($(IS_LIBRARY),1) ifeq ($(LIBNAME),libbest) -$(errror "You should rename your library! libbest is the default library name and should be changed") +$(error "You should rename your library! libbest is the default library name and should be changed") endif LIBAR=$(BINDIR)/$(LIBNAME).a @@ -206,6 +206,7 @@ clean-template: -$Drm -rf $(TEMPLATE_DIR) $(LIBAR): $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)) $(EXTRA_LIB_DEPS) + -$Dmkdir $(BINDIR) -$Drm -f $@ $(call test_output_2,Creating $@ ,$(AR) rcs $@ $^, $(DONE_STRING)) @@ -213,7 +214,7 @@ $(LIBAR): $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)) $(EXTRA_LIB_DEPS) library: $(LIBAR) .PHONY: template -template: clean-template $(LIBAR) +template:: clean-template $(LIBAR) $Dpros c create-template . $(LIBNAME) $(VERSION) $(foreach file,$(TEMPLATE_FILES) $(LIBAR),--system "$(file)") --target v5 $(CREATE_TEMPLATE_FLAGS) endif @@ -262,7 +263,7 @@ $(foreach asmext,$(ASMEXTS),$(eval $(call asm_rule,$(asmext)))) define c_rule $(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 -$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 $(DEPDIR)/$(basename $1).d +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 $(DEPDIR)/$(basename %).d $(VV)mkdir -p $$(dir $$@) $(MAKEDEPFOLDER) $$(call test_output_2,Compiled $$< ,$(CC) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CFLAGS) $(EXTRA_CFLAGS) $(DEPFLAGS) -o $$@ $$<,$(OK_STRING)) @@ -305,4 +306,4 @@ cxx-sysroot: $(DEPDIR)/%.d: ; .PRECIOUS: $(DEPDIR)/%.d -include $(wildcard $(patsubst $(SRCDIR)/%,$(DEPDIR)/%.d,$(CSRC) $(CXXSRC))) +include $(wildcard $(patsubst $(SRCDIR)/%,$(DEPDIR)/%.d,$(CSRC) $(CXXSRC))) \ No newline at end of file diff --git a/firmware/libc.a b/firmware/libc.a index 51439b9..a2e1cdb 100644 Binary files a/firmware/libc.a and b/firmware/libc.a differ diff --git a/firmware/libm.a b/firmware/libm.a index 3d4066d..63c9951 100644 Binary files a/firmware/libm.a and b/firmware/libm.a differ diff --git a/firmware/libpros.a b/firmware/libpros.a index 37c0aa2..c6af4ed 100644 Binary files a/firmware/libpros.a and b/firmware/libpros.a differ diff --git a/firmware/v5-common.ld b/firmware/v5-common.ld index 762a905..7f262fc 100644 --- a/firmware/v5-common.ld +++ b/firmware/v5-common.ld @@ -132,12 +132,6 @@ SECTIONS *(.gcc_except_table) } > RAM -.mmu_tbl (ALIGN(16384)) : { - __mmu_tbl_start = .; - *(.mmu_tbl) - __mmu_tbl_end = .; -} > RAM - .ARM.exidx : { __exidx_start = .; *(.ARM.exidx*) @@ -166,11 +160,9 @@ SECTIONS __fini_array_end = .; } > RAM -.ARM.attributes : { - __ARM.attributes_start = .; - *(.ARM.attributes) - __ARM.attributes_end = .; -} > RAM +/DISCARD/ : { + *(.ARM.attributes*) +} .sdata : { __sdata_start = .; @@ -228,36 +220,7 @@ _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); _heap_end = .; HeapLimit = .; } > HEAP - -.stack (NOLOAD) : { - . = ALIGN(16); - _stack_end = .; - . += _STACK_SIZE; - . = ALIGN(16); - _stack = .; - __stack = _stack; - . = ALIGN(16); - _irq_stack_end = .; - . += _IRQ_STACK_SIZE; - . = ALIGN(16); - __irq_stack = .; - _supervisor_stack_end = .; - . += _SUPERVISOR_STACK_SIZE; - . = ALIGN(16); - __supervisor_stack = .; - _abort_stack_end = .; - . += _ABORT_STACK_SIZE; - . = ALIGN(16); - __abort_stack = .; - _fiq_stack_end = .; - . += _FIQ_STACK_SIZE; - . = ALIGN(16); - __fiq_stack = .; - _undef_stack_end = .; - . += _UNDEF_STACK_SIZE; - . = ALIGN(16); - __undef_stack = .; -} > COLD_MEMORY - +/* There are no sections for the stack. This is intentional, since VEXOs sets up a stack before + starting the program, and FreeRTOS task stacks are dynamically allocated. */ _end = .; } diff --git a/include/api.h b/include/api.h index 0d691bc..5ba908b 100644 --- a/include/api.h +++ b/include/api.h @@ -8,7 +8,7 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright Copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright Copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public @@ -39,12 +39,8 @@ #include #endif /* __cplusplus */ -#define PROS_VERSION_MAJOR 4 -#define PROS_VERSION_MINOR 0 -#define PROS_VERSION_PATCH 1 -#define PROS_VERSION_STRING "4.0.1" - #include "pros/adi.h" +#include "pros/ai_vision.h" #include "pros/colors.h" #include "pros/device.h" #include "pros/distance.h" @@ -64,6 +60,7 @@ #ifdef __cplusplus #include "pros/adi.hpp" +#include "pros/ai_vision.hpp" #include "pros/colors.hpp" #include "pros/device.hpp" #include "pros/distance.hpp" diff --git a/include/liblvgl/lv_version.h b/include/liblvgl/lv_version.h index 1e62e1e..266d60b 100644 --- a/include/liblvgl/lv_version.h +++ b/include/liblvgl/lv_version.h @@ -14,9 +14,9 @@ extern "C" { * INCLUDES *********************/ /*Current version of LittlevGL*/ -#define LVGL_VERSION_MAJOR 5 +#define LVGL_VERSION_MAJOR 8 #define LVGL_VERSION_MINOR 3 -#define LVGL_VERSION_PATCH 0 +#define LVGL_VERSION_PATCH 8 #define LVGL_VERSION_INFO "" diff --git a/include/pros/abstract_motor.hpp b/include/pros/abstract_motor.hpp index ca68f68..fd8e803 100644 --- a/include/pros/abstract_motor.hpp +++ b/include/pros/abstract_motor.hpp @@ -1,3 +1,22 @@ +/** + * \file abstract_motor.hpp + * \ingroup cpp-abstract-motor + * + * Contains prototypes for AbstractMotor, the abstract base class of both + * motors and motor groups. Abstract motors cannot be directly constructed, but + * you can use motors and motor groups as abstract motors. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * \copyright Copyright (c) 2017-2024, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + #ifndef _PROS_ABSTRACT_MOTORS_HPP_ #define _PROS_ABSTRACT_MOTORS_HPP_ @@ -12,69 +31,67 @@ namespace pros { inline namespace v5 { /** - * \enum motor_brake + * \enum MotorBrake * Indicates the current 'brake mode' of a motor. */ enum class MotorBrake { - /// Motor coasts when stopped, traditional behavior - coast = 0, - /// Motor brakes when stopped - brake = 1, - /// Motor actively holds position when stopped - hold = 2, - /// Invalid brake mode - invalid = INT32_MAX + coast = 0, ///< Motor coasts when stopped, traditional behavior + brake = 1, ///< Motor brakes when stopped + hold = 2, ///< Motor actively holds position when stopped + invalid = INT32_MAX ///< Invalid brake mode }; /** - * \enum Motor_Encoder_Units + * \enum MotorEncoderUnits * Indicates the units used by the motor encoders. */ enum class MotorEncoderUnits { - /// Position is recorded as angle in degrees as a floating point number - degrees = 0, - /// Position is recorded as angle in degrees as a floating point number - deg = 0, - /// Position is recorded as angle in rotations as a floating point number - rotations = 1, - /// Position is recorded as raw encoder ticks as a whole number - counts = 2, - /// Invalid motor encoder units - invalid = INT32_MAX + degrees = 0, ///< Position is recorded as angle in degrees as a floating point number + deg = 0, ///< Position is recorded as angle in degrees as a floating point number + rotations = 1, ///< Position is recorded as angle in rotations as a floating point number + counts = 2, ///< Position is recorded as raw encoder ticks as a whole number + invalid = INT32_MAX ///< Invalid motor encoder units }; -// Alias for Motor_Encoder_Units +// Alias for MotorEncoderUnits using MotorUnits = MotorEncoderUnits; enum class MotorGears { - /// 36:1, 100 RPM, Red gear set - ratio_36_to_1 = 0, - red = ratio_36_to_1, - rpm_100 = ratio_36_to_1, - /// 18:1, 200 RPM, Green gear set - ratio_18_to_1 = 1, - green = ratio_18_to_1, - rpm_200 = ratio_18_to_1, - /// 6:1, 600 RPM, Blue gear set - ratio_6_to_1 = 2, - blue = ratio_6_to_1, - rpm_600 = ratio_6_to_1, - /// Error return code - invalid = INT32_MAX + ratio_36_to_1 = 0, ///< 36:1, 100 RPM, Red gear set + red = ratio_36_to_1, ///< 36:1, 100 RPM, Red gear set + rpm_100 = ratio_36_to_1, ///< 36:1, 100 RPM, Red gear set + ratio_18_to_1 = 1, ///< 18:1, 200 RPM, Green gear set + green = ratio_18_to_1, ///< 18:1, 200 RPM, Green gear set + rpm_200 = ratio_18_to_1, ///< 18:1, 200 RPM, Green gear set + ratio_6_to_1 = 2, ///< 6:1, 600 RPM, Blue gear set + blue = ratio_6_to_1, ///< 6:1, 600 RPM, Blue gear set + rpm_600 = ratio_6_to_1, ///< 6:1, 600 RPM, Blue gear set + invalid = INT32_MAX ///< Error return code +}; + +/** + * \enum MotorType + * Indicates the type of a motor + */ +enum class MotorType { + v5 = 0, ///< 11w motor + exp = 1, ///< 5.5w motor + invalid = INT32_MAX ///< Error return code }; -// Provide Aliases for Motor_Gears + +// Provide Aliases for MotorGears using MotorGearset = MotorGears; using MotorCart = MotorGears; using MotorCartridge = MotorGears; using MotorGear = MotorGears; /** - * \ingroup cpp-motors + * \ingroup cpp-abstract-motor */ class AbstractMotor { /** - * \addtogroup cpp-motors + * \addtogroup cpp-abstract-motor * @{ */ public: @@ -82,37 +99,6 @@ class AbstractMotor { /// These functions allow programmers to make motors move ///@{ - /** - * Sets the voltage for the motor from -128 to 127. - * - * This is designed to map easily to the input from the controller's analog - * stick for simple opcontrol use. The actual behavior of the motor is - * analogous to use of pros::Motor::move(), or motorSet from the PROS 2 API. - * - * This function uses the following values of errno when an error state is - * reached: - * ENODEV - The port cannot be configured as a motor - * - * \param voltage - * The new motor voltage from -127 to 127 - * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::MotorGroup MotorGroup ({1}, E_MOTOR_GEARSET_18); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * pros::delay(2); - * } - * } - * \endcode - */ - virtual std::int32_t operator=(std::int32_t voltage) const = 0; - /** * Sets the voltage for the motor from -127 to 127. * @@ -129,18 +115,6 @@ class AbstractMotor { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::MotorGroup MotorGroup ({1}); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor.move(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t move(std::int32_t voltage) const = 0; @@ -165,27 +139,6 @@ class AbstractMotor { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); // Moves 100 units forward - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { - * // Continue running this loop as long as the motor is not within +-5 units of its goal - * pros::delay(2); - * } - * motor.move_absolute(100, 100); // This does not cause a movement - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { - * pros::delay(2); - * } - * motor.tare_position(); - * motor.move_absolute(100, 100); // Moves 100 units forward - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t move_absolute(const double position, const std::int32_t velocity) const = 0; @@ -211,22 +164,6 @@ class AbstractMotor { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * motor.move_relative(100, 100); // Moves 100 units forward - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { - * // Continue running this loop as long as the motor is not within +-5 units of its goal - * pros::delay(2); - * } - * motor.move_relative(100, 100); // Also moves 100 units forward - * while (!((motor.get_position() < 205) && (motor.get_position() > 195))) { - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t move_relative(const double position, const std::int32_t velocity) const = 0; @@ -249,16 +186,6 @@ class AbstractMotor { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * motor.move_velocity(100); - * pros::delay(1000); // Move at 100 RPM for 1 second - * motor.move_velocity(0); - * } - * \endcode */ virtual std::int32_t move_velocity(const std::int32_t velocity) const = 0; @@ -276,20 +203,41 @@ class AbstractMotor { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * motor.move_voltage(12000); - * pros::delay(1000); // Move at max voltage for 1 second - * motor.move_voltage(0); - * } - * \endcode */ virtual std::int32_t move_voltage(const std::int32_t voltage) const = 0; + /** + * Stops the motor using the currently configured brake mode. + * + * This function sets motor velocity to zero, which will cause it to act + * according to the set brake mode. If brake mode is set to MOTOR_BRAKE_HOLD, + * this function may behave differently than calling move_absolute(0) + * or motor_move_relative(0). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + */ virtual std::int32_t brake(void) const = 0; + + /** + * Changes the output velocity for a profiled movement (motor_move_absolute or + * motor_move_relative). This will have no effect if the motor is not following + * a profiled movement. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param velocity + * The new motor velocity from +-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ virtual std::int32_t modify_profiled_velocity(const std::int32_t velocity) const = 0; + /** * Gets the target position set for the motor by the user, with a parameter * for the motor index. @@ -298,22 +246,26 @@ class AbstractMotor { * reached: * ENODEV - The port cannot be configured as a motor * - * \param index The index of the motor to get the target position of. + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The target position in its encoder units or PROS_ERR_F if the * operation failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); - * std::cout << "Motor Target: " << motor.get_target_position(); - * // Prints 100 - * } - * \endcode */ virtual double get_target_position(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the target position(s) set for the motor(s) by the user + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing the target position(s) in its encoder units or PROS_ERR_F if the + * operation failed, setting errno. + */ virtual std::vector get_target_position_all(void) const = 0; /** @@ -322,30 +274,32 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The commanded motor velocity from +-100, +-200, or +-600, or * PROS_ERR if the operation failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor.move_velocity(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); - * std::cout << "Motor Velocity: " << motor.get_target_velocity(); - * // Prints the value of E_CONTROLLER_ANALOG_LEFT_Y - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t get_target_velocity(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the velocity/velocities commanded to the motor(s) by the user + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the commanded motor velocity/velocities from +-100, + * +-200, or +-600, or PROS_ERR if the operation failed, setting errno. + */ virtual std::vector get_target_velocity_all(void) const = 0; ///@} /// \name Motor telemetry functions + /// \addtogroup cpp-motor-telemetry /// These functions allow programmers to collect telemetry from motors ///@{ @@ -355,23 +309,26 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's actual velocity in RPM or PROS_ERR_F if the operation * failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * while (true) { - * motor = controller_get_analog(E_CONTROLLER_MASTER, E_CONTROLLER_ANALOG_LEFT_Y); - * printf("Actual velocity: %lf\n", motor.get_actual_velocity()); - * pros::delay(2); - * } - * } - * \endcode */ virtual double get_actual_velocity(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the actual velocity/velocities of the motor(s) + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's/motors' actual velocity/velocities in RPM or PROS_ERR_F + * if the operation failed, setting errno. + */ virtual std::vector get_actual_velocity_all(void) const = 0; /** @@ -381,23 +338,27 @@ class AbstractMotor { * reached: * ENODEV - The port cannot be configured as a motor * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * * \return The motor's current in mA or PROS_ERR if the operation failed, * setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Current Draw: " << motor.get_current_draw(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t get_current_draw(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the current(s) drawn by the motor(s) in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector conatining the motor's/motors' current(s) in mA or PROS_ERR if the operation failed, + * setting errno. + */ virtual std::vector get_current_draw_all(void) const = 0; /** @@ -406,24 +367,29 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 for moving in the positive direction, -1 for moving in the * negative direction, and PROS_ERR if the operation failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Direction: " << motor.get_direction(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t get_direction(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the direction(s) of movement for the motor(s). + * + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing 1 for moving in the positive direction, -1 for moving in the + * negative direction, and PROS_ERR if the operation failed, setting errno. + */ virtual std::vector get_direction_all(void) const = 0; /** @@ -436,24 +402,32 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's efficiency in percent or PROS_ERR_F if the operation * failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Efficiency: " << motor.get_efficiency(); - * pros::delay(2); - * } - * } - * \endcode */ virtual double get_efficiency(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the efficiency/efficiencies of the motor(s) in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing the motor's/motors' efficiency/efficiencies in percent or PROS_ERR_F if the operation + * failed, setting errno. + */ virtual std::vector get_efficiency_all(void) const = 0; /** @@ -465,24 +439,26 @@ class AbstractMotor { * reached: * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return A bitfield containing the motor's faults. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Faults: " << motor.get_faults();pros::delay(2); - * } - * } - * \endcode */ virtual std::uint32_t get_faults(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the faults experienced by the motor(s). + * + * Compare this bitfield to the bitmasks in pros::motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * \return A bitfield containing the motor's/motors' faults. + */ virtual std::vector get_faults_all(void) const = 0; /** * Gets the flags set by the motor's operation. @@ -493,25 +469,27 @@ class AbstractMotor { * reached: * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return A bitfield containing the motor's flags. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Faults: " << motor.get_faults(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::uint32_t get_flags(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the flags set by the motor's/motors' operation. + * + * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A bitfield containing the motor's/motors' flags. + */ virtual std::vector get_flags_all(void) const = 0; /** @@ -520,24 +498,28 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's absolute position in its encoder units or PROS_ERR_F * if the operation failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Position: " << motor.get_position(); - * pros::delay(2); - * } - * } - * \endcode */ virtual double get_position(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the absolute position(s) of the motor(s) in its encoder units. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + + * + * \return A vector containing the motor's/motors' absolute position(s) in its encoder units or PROS_ERR_F + * if the operation failed, setting errno. + */ virtual std::vector get_position_all(void) const = 0; /** @@ -546,25 +528,29 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's power draw in Watts or PROS_ERR_F if the operation * failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Power: " << motor.get_power(); - * pros::delay(2); - * } - * } - * \endcode */ virtual double get_power(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector containing the power(s) drawn by the motor(s) in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's/motors' power draw in Watts or PROS_ERR_F if the operation + * failed, setting errno. + */ virtual std::vector get_power_all(void) const = 0; + /** * Gets the raw encoder count of the motor at a given timestamp. * @@ -576,25 +562,33 @@ class AbstractMotor { * A pointer to a time in milliseconds for which the encoder count * will be returned. If NULL, the timestamp at which the encoder * count was read will not be supplied + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The raw encoder count at the given timestamp or PROS_ERR if the * operation failed. - * - * \b Example - * \code - * void opcontrol() { - * std::uint32_t now = pros::millis(); - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Position: " << motor.get_raw_position(&now); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t get_raw_position(std::uint32_t* const timestamp, const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the raw encoder count(s) of the motor(s) at a given timestamp. + * + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * \param timestamp + * A pointer to a time in milliseconds for which the encoder count + * will be returned. If NULL, the timestamp at which the encoder + * count was read will not be supplied + * + * \return A vector containing the raw encoder count(s) at the given timestamp or PROS_ERR if the + * operation failed. + */ virtual std::vector get_raw_position_all(std::uint32_t* const timestamp) const = 0; /** @@ -603,24 +597,30 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the * operation failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Temperature: " << motor.get_temperature(); - * pros::delay(2); - * } - * } - * \endcode */ virtual double get_temperature(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the temperature(s) of the motor(s) in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector containing the motor's/motors' temperature(s) in degrees Celsius or PROS_ERR_F if the + * operation failed, setting errno. + */ virtual std::vector get_temperature_all(void) const = 0; /** * Gets the torque generated by the motor in Newton Meters (Nm). @@ -628,24 +628,30 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, * setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Torque: " << motor.get_torque(); - * pros::delay(2); - * } - * } - * \endcode */ virtual double get_torque(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the torque(s) generated by the motor(s) in Newton Meters (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector containing the motor's/motors' torque(s) in Nm or PROS_ERR_F if the operation failed, + * setting errno. + */ virtual std::vector get_torque_all(void) const = 0; /** * Gets the voltage delivered to the motor in millivolts. @@ -653,24 +659,30 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, * setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Voltage: " << motor.get_voltage(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t get_voltage(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the voltage(s) delivered to the motor(s) in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector containing the motor's/motors' voltage(s) in mV or PROS_ERR_F if the operation failed, + * setting errno. + */ virtual std::vector get_voltage_all(void) const = 0; /** @@ -679,25 +691,32 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the motor's current limit is being exceeded and 0 if the * current limit is not exceeded, or PROS_ERR if the operation failed, setting * errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Is the motor over its current limit?: " << motor.is_over_current(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t is_over_current(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of whether each motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return 1 if the motor's current limit is being exceeded and 0 if the + * current limit is not exceeded, or PROS_ERR if the operation failed, setting + * errno. + */ virtual std::vector is_over_current_all(void) const = 0; /** @@ -706,29 +725,36 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the temperature limit is exceeded and 0 if the temperature is * below the limit, or PROS_ERR if the operation failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Is the motor over its temperature limit?: " << motor.is_over_temp(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t is_over_temp(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the temperature limit flag(s) for the motor(s). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return 1 if the temperature limit is exceeded and 0 if the temperature is + * below the limit, or PROS_ERR if the operation failed, setting errno. + */ virtual std::vector is_over_temp_all(void) const = 0; ///@} /// \name Motor configuration functions + /// \addtogroup cpp-motor-configuration /// These functions allow programmers to configure the behavior of motors ///@{ @@ -738,20 +764,30 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * - * \return One of Motor_Brake, according to what was set for the + * \return One of MotorBrake, according to what was set for the * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * motor.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); - * std::cout << "Brake Mode: " << motor.get_brake_mode(); - * } - * \endcode */ virtual MotorBrake get_brake_mode(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the brake mode(s) that was set for the motor(s). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector containing MotorBrake(s), according to what was set for the + * motor(s), or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + */ virtual std::vector get_brake_mode_all(void) const = 0; /** @@ -762,22 +798,32 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's current limit in mA or PROS_ERR if the operation failed, * setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * while (true) { - * std::cout << "Motor Current Limit: " << motor.get_current_limit(); - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t get_current_limit(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the current limit(s) for the motor(s) in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector containing the motor's/motors' current limit(s) in mA or PROS_ERR if the operation failed, + * setting errno. + */ virtual std::vector get_current_limit_all(void) const = 0; /** @@ -786,19 +832,30 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * - * \return One of Motor_Units according to what is set for the + * \return One of MotorUnits according to what is set for the * motor or E_MOTOR_ENCODER_INVALID if the operation failed. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); - * std::cout << "Motor Encoder Units: " << motor.get_encoder_units(); - * } - * \endcode */ virtual MotorUnits get_encoder_units(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the encoder units that were set for the motor(s). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector of MotorUnits according to what is set for the + * motor(s) or E_MOTOR_ENCODER_INVALID if the operation failed. + */ virtual std::vector get_encoder_units_all(void) const = 0; /** @@ -807,19 +864,30 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * - * \return One of Motor_Gears according to what is set for the motor, - * or pros::Motor_Gears::invalid if the operation failed. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); - * std::cout << "Motor Gearing: " << motor.get_gearing(); - * } - * \endcode + * \return One of MotorGears according to what is set for the motor, + * or pros::MotorGears::invalid if the operation failed. */ virtual MotorGears get_gearing(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the gearset(s) that was/were set for the motor(s). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector of MotorGears according to what is set for the motor(s), + * or pros::MotorGears::invalid if the operation failed. + */ virtual std::vector get_gearing_all(void) const = 0; /** @@ -838,19 +906,33 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return The motor's voltage limit in V or PROS_ERR if the operation failed, * setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * std::cout << "Motor Voltage Limit: " << motor.get_voltage_limit(); - * } - * \endcode */ virtual std::int32_t get_voltage_limit(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the voltage limit(s) set by the user. + * + * Default value is 0V, which means that there is no software limitation + * imposed on the voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return A vector containing the motor's/motors' voltage limit(s) in V or PROS_ERR if the operation failed, + * setting errno. + */ virtual std::vector get_voltage_limit_all(void) const = 0; /** @@ -859,24 +941,62 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the motor has been reversed and 0 if the motor was not * reversed, or PROS_ERR if the operation failed, setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * std::cout << "Is the motor reversed? " << motor.is_reversed(); - * // Prints "0" - * } - * \endcode */ virtual std::int32_t is_reversed(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the operation direction(s) of the motor(s) as set by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return 1 if the motor has been reversed and 0 if the motor was not + * reversed, or PROS_ERR if the operation failed, setting errno. + */ virtual std::vector is_reversed_all(void) const = 0; /** - * Sets one of Motor_Brake to the motor. Works with the C enum + * Gets the type of the motor + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index + * + * \return One of MotorType according to the type of the motor, + * or pros::MotorType::invalid if the operation failed + */ + virtual MotorType get_type(const std::uint8_t index = 0) const = 0; + + /** + * Gets a vector of the type(s) of the motor(s). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector of MotorType according to the type(s) of the motor(s), + * or pros::MotorType::invalid if the operation failed. + */ + virtual std::vector get_type_all(void) const = 0; + + /** + * Sets one of MotorBrake to the motor. Works with the C enum * and the C++ enum class. * * This function uses the following values of errno when an error state is @@ -884,19 +1004,14 @@ class AbstractMotor { * ENODEV - The port cannot be configured as a motor * * \param mode - * The Motor_Brake to set for the motor + * The MotorBrake to set for the motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * motor.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); - * std::cout << "Brake Mode: " << motor.get_brake_mode(); - * } - * \endcode */ virtual std::int32_t set_brake_mode(const MotorBrake mode, const std::uint8_t index = 0) const = 0; virtual std::int32_t set_brake_mode(const pros::motor_brake_mode_e_t mode, const std::uint8_t index = 0) const = 0; @@ -911,29 +1026,18 @@ class AbstractMotor { * * \param limit * The new current limit in mA + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * - * motor.set_current_limit(1000); - * while (true) { - * motor = controller_get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * // The motor will reduce its output at 1000 mA instead of the default 2500 mA - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t set_current_limit(const std::int32_t limit, const std::uint8_t index = 0) const = 0; virtual std::int32_t set_current_limit_all(const std::int32_t limit) const = 0; /** - * Sets one of Motor_Units for the motor encoder. Works with the C + * Sets one of MotorUnits for the motor encoder. Works with the C * enum and the C++ enum class. * * This function uses the following values of errno when an error state is @@ -942,18 +1046,13 @@ class AbstractMotor { * * \param units * The new motor encoder units + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * motor.set_encoder_units(E_MOTOR_ENCODER_DEGREES); - * std::cout << "Encoder Units: " << motor.get_encoder_units(); - * } - * \endcode */ virtual std::int32_t set_encoder_units(const MotorUnits units, const std::uint8_t index = 0) const = 0; virtual std::int32_t set_encoder_units(const pros::motor_encoder_units_e_t units, const std::uint8_t index = 0) const = 0; @@ -969,18 +1068,13 @@ class AbstractMotor { * * \param gearset * The new motor gearset + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * motor.set_gearing(E_MOTOR_GEARSET_06); - * std::cout << "Gearset: " << motor.get_gearing(); - * } - * \endcode */ virtual std::int32_t set_gearing(const MotorGears gearset, const std::uint8_t index = 0) const = 0; virtual std::int32_t set_gearing(const pros::motor_gearset_e_t gearset, const std::uint8_t index = 0) const = 0; @@ -998,18 +1092,13 @@ class AbstractMotor { * * \param reverse * True reverses the motor, false is default + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void initialize() { - * pros::Motor motor (1); - * motor.set_reversed(true); - * std::cout << "Is this motor reversed? " << motor.is_reversed(); - * } - * \endcode */ virtual std::int32_t set_reversed(const bool reverse, const std::uint8_t index = 0) = 0; virtual std::int32_t set_reversed_all(const bool reverse) = 0; @@ -1023,24 +1112,13 @@ class AbstractMotor { * * \param limit * The new voltage limit in Volts + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * - * motor.set_voltage_limit(10000); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * // The motor will not output more than 10 V - * pros::delay(2); - * } - * } - * \endcode */ virtual std::int32_t set_voltage_limit(const std::int32_t limit, const std::uint8_t index = 0) const = 0; virtual std::int32_t set_voltage_limit_all(const std::int32_t limit) const = 0; @@ -1057,22 +1135,13 @@ class AbstractMotor { * * \param position * The new reference position in its encoder units + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); // Moves 100 units forward - * motor.move_absolute(100, 100); // This does not cause a movement - * - * motor.set_zero_position(80); - * motor.move_absolute(100, 100); // Moves 80 units forward - * } - * \endcode - * */ virtual std::int32_t set_zero_position(const double position, const std::uint8_t index = 0) const = 0; virtual std::int32_t set_zero_position_all(const double position) const = 0; @@ -1083,21 +1152,13 @@ class AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * + * \param index Optional parameter. + * The index of the motor to get the target position of. + * By default index is 0, and will return an error for an out of bounds index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * - * \b Example - * \code - * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); // Moves 100 units forward - * motor.move_absolute(100, 100); // This does not cause a movement - * - * motor.tare_position(); - * motor.move_absolute(100, 100); // Moves 100 units forward - * } - * \endcode */ virtual std::int32_t tare_position(const std::uint8_t index = 0) const = 0; virtual std::int32_t tare_position_all(void) const = 0; @@ -1113,9 +1174,9 @@ class AbstractMotor { private: }; -///@} - } // namespace v5 } // namespace pros -#endif \ No newline at end of file +///@} + +#endif diff --git a/include/pros/adi.h b/include/pros/adi.h index 049bb49..0b45e57 100644 --- a/include/pros/adi.h +++ b/include/pros/adi.h @@ -4,12 +4,10 @@ * * Contains prototypes for interfacing with the ADI. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -142,6 +140,8 @@ typedef enum adi_potentiometer_type_e { namespace c { #endif +/** @} Add to group c-adi*/ + /** * \ingroup c-adi */ @@ -150,9 +150,6 @@ namespace c { * \addtogroup c-adi * @{ */ -/// \name General ADI Use Functions -/// These functions allow for interaction with any ADI port type -///@{ /** * Gets the configuration for the given ADI port. @@ -262,44 +259,6 @@ int32_t adi_port_set_config(uint8_t port, adi_port_config_e_t type); */ int32_t adi_port_set_value(uint8_t port, int32_t value); -///@} - -/// \name PROS 2 Compatibility Functions -/// These functions provide similar functionality to the PROS 2 API -///@{ - -/** - * Used for adi_digital_write() to specify a logic HIGH state to output. - * - * In reality, using any non-zero expression or "true" will work to set a pin to - * HIGH. - */ -#define HIGH 1 -/** - * Used for adi_digital_write() to specify a logic LOW state to output. - * - * In reality, using a zero expression or "false" will work to set a pin to LOW. - */ -#define LOW 0 - -/** - * adi_pin_mode() state for a digital input. - */ -#define INPUT 0x00 -/** - * adi_pin_mode() state for a digital output. - */ -#define OUTPUT 0x01 -/** - * adi_pin_mode() state for an analog input. - */ -#define INPUT_ANALOG 0x02 - -/** - * adi_pin_mode() state for an analog output. - */ -#define OUTPUT_ANALOG 0x03 - /** * Calibrates the analog sensor on the specified port and returns the new * calibration value. @@ -315,9 +274,7 @@ int32_t adi_port_set_value(uint8_t port, int32_t value); * (gyro rotation, accelerometer movement). * * \note The ADI currently returns data at 10ms intervals, in constrast to the - * calibrate function’s 1ms sample rate. This sample rate was kept for the sake - * of being similar to PROS 2, and increasing the sample rate would not have a - * tangible difference in the function’s performance. + * calibrate function’s 1ms sample rate. * * This function uses the following values of errno when an error state is * reached: @@ -666,8 +623,7 @@ int32_t adi_motor_stop(uint8_t port); /** * Reference type for an initialized encoder. * - * This merely contains the port number for the encoder, unlike its use as an - * object to store encoder data in PROS 2. + * This merely contains the port number for the encoder. */ typedef int32_t adi_encoder_t; @@ -802,8 +758,7 @@ int32_t adi_encoder_shutdown(adi_encoder_t enc); /** * Reference type for an initialized ultrasonic. * - * This merely contains the port number for the ultrasonic, unlike its use as an - * object to store ultrasonic data in PROS 2. + * This merely contains the port number for the ultrasonic. */ typedef int32_t adi_ultrasonic_t; @@ -912,8 +867,7 @@ int32_t adi_ultrasonic_shutdown(adi_ultrasonic_t ult); /** * Reference type for an initialized gyroscope. * - * This merely contains the port number for the gyroscope, unlike its use as an - * object to store gyro data in PROS 2. + * This merely contains the port number for the gyroscope. */ typedef int32_t adi_gyro_t; @@ -1072,8 +1026,7 @@ int32_t adi_gyro_shutdown(adi_gyro_t gyro); /** * Reference type for an initialized potentiometer. * - * This merely contains the port number for the potentiometer, unlike its use as an - * object to store gyro data in PROS 2. + * This merely contains the port number for the potentiometer. */ typedef int32_t adi_potentiometer_t; @@ -1379,9 +1332,47 @@ int32_t adi_led_set_pixel(adi_led_t led, uint32_t* buffer, uint32_t buffer_lengt */ int32_t adi_led_clear_pixel(adi_led_t led, uint32_t* buffer, uint32_t buffer_length, uint32_t pixel_position); -///@} +/** + * \name Ease of use macro definitions + * These functions provide ease of use definitions for the ADI functions. + * @{ + */ + +/** + * Used for adi_digital_write() to specify a logic HIGH state to output. + * + * In reality, using any non-zero expression or "true" will work to set a pin to + * HIGH. + */ +#define HIGH 1 +/** + * Used for adi_digital_write() to specify a logic LOW state to output. + * + * In reality, using a zero expression or "false" will work to set a pin to LOW. + */ +#define LOW 0 + +/** + * adi_pin_mode() state for a digital input. + */ +#define INPUT 0x00 +/** + * adi_pin_mode() state for a digital output. + */ +#define OUTPUT 0x01 +/** + * adi_pin_mode() state for an analog input. + */ +#define INPUT_ANALOG 0x02 + +/** + * adi_pin_mode() state for an analog output. + */ +#define OUTPUT_ANALOG 0x03 + +/** @} Name: Ease of use macro definitions*/ -///@} +/** @} Add to group: c-adi*/ #ifdef __cplusplus } // namespace c diff --git a/include/pros/adi.hpp b/include/pros/adi.hpp index a24e55a..f01615d 100644 --- a/include/pros/adi.hpp +++ b/include/pros/adi.hpp @@ -4,17 +4,15 @@ * * Contains prototypes for interfacing with the ADI. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-adi ADI (TriPort) C++ API * \note The external ADI API can be found [here.](@ref ext-adi) * \note Additional example code for this module can be found in its [Tutorial.](@ref adi) @@ -24,25 +22,24 @@ #define _PROS_ADI_HPP_ #include -#include +#include #include #include -#include +#include #include "pros/adi.h" -#define LEGACY_TYPEDEF(old_name, new_name) \ - using old_name [[deprecated("use " #new_name " instead")]] = new_name +#define LEGACY_TYPEDEF(old_name, new_name) using old_name [[deprecated("use " #new_name " instead")]] = new_name namespace pros { namespace adi { - + /** type definition for the pair of smart port and adi port for the basic adi devices */ using ext_adi_port_pair_t = std::pair; /** type definition for the triplet of smart port and two adi ports for the two wire adi devices*/ using ext_adi_port_tuple_t = std::tuple; - + /** * \ingroup cpp-adi */ @@ -65,12 +62,12 @@ class Port { * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param type * The configuration type for the port - * + * * \b Example * \code * #define POTENTIOMETER_PORT 1 * #define POTENTIOMETER_TYPE pros::E_ADI_POT_EDR - * + * * void opcontrol() { * pros::ADIPotentiometer potentiometer (POTENTIOMETER_PORT, POTENTIOMETER_TYPE); * while (true) { @@ -96,14 +93,14 @@ class Port { * (from 1-8, 'a'-'h', 'A'-'H') to configure * \param type * The configuration type for the port - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 'a' * #define EXT_ADI_SMART_PORT 1 - * + * * void initialize() { - * pros::adi::Port sensor ({{ EXT_ADI_SMART_PORT , ANALOG_SENSOR_PORT }}, E_ADI_ANALOG_IN); + * pros::adi::Port sensor ({EXT_ADI_SMART_PORT, ANALOG_SENSOR_PORT}, E_ADI_ANALOG_IN); * // Displays the value of E_ADI_ANALOG_IN * std::cout << "Port Type: " << sensor.get_config(); * } @@ -115,7 +112,7 @@ class Port { * Gets the configuration for the given ADI port. * * \return The ADI configuration for the given port - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 @@ -132,11 +129,11 @@ class Port { * Gets the value for the given ADI port. * * \return The value stored for the given port - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::adi::Port sensor (ANALOG_SENSOR_PORT, E_ADI_ANALOG_IN); * std::cout << "Port Value: " << sensor.get_value(); @@ -153,11 +150,11 @@ class Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void initialize() { * pros::adi::Port sensor (ANALOG_SENSOR_PORT, E_ADI_DIGITAL_IN); * // Do things as a digital sensor @@ -179,11 +176,11 @@ class Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define DIGITAL_SENSOR_PORT 1 - * + * * void initialize() { * pros::adi::Port sensor (DIGITAL_SENSOR_PORT, E_ADI_DIGITAL_OUT); * sensor.set_value(DIGITAL_SENSOR_PORT, HIGH); @@ -192,6 +189,33 @@ class Port { */ std::int32_t set_value(std::int32_t value) const; + /** + * Gets the port of the sensor. + * + * \return returns a tuple of integer ports. + * + * \note The parts of the tuple are {smart port, adi port, second adi port (when applicable)}. + * + * + * \b Example + * \code + * #define DIGITAL_SENSOR_PORT 1 // 'A' + * + * void initialize() { + * pros::adi::AnalogIn sensor (DIGITAL_SENSOR_PORT); + * + * // Getting values from the tuple using std::get + * int sensorSmartPort = std::get<0>(sensor.get_port()); // First value + * int sensorAdiPort = std::get<1>(sensor.get_port()); // Second value + * + * // Prints the first and second value from the port tuple (The Adi Port. The first value is the Smart Port) + * printf("Sensor Smart Port: %d\n", sensorSmartPort); + * printf("Sensor Adi Port: %d\n", sensorAdiPort); + * } + * \endcode + */ + virtual ext_adi_port_tuple_t get_port() const; + protected: std::uint8_t _smart_port; std::uint8_t _adi_port; @@ -217,11 +241,11 @@ class AnalogIn : protected Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::ADIAnalogIn sensor (ANALOG_SENSOR_PORT); * while (true) { @@ -245,14 +269,14 @@ class AnalogIn : protected Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define EXT_ADI_SENSOR_PORT 1 * #define ADI_PORT 'a' - * + * * void opcontrol() { - * pros::ADIAnalogIn sensor ({{EXT_ADI_SMART_PORT, ADI_PORT}}); + * pros::ADIAnalogIn sensor ({EXT_ADI_SMART_PORT, ADI_PORT}); * while (true) { * // Use the sensor * } @@ -276,22 +300,20 @@ class AnalogIn : protected Port { * * Do not use this function when the sensor value might be unstable (gyro * rotation, accelerometer movement). - * + * * \note The ADI currently returns data at 10ms intervals, in contrast to the - * calibrate function’s 1ms sample rate. This sample rate was kept for the sake - * of being similar to PROS 2, and increasing the sample rate would not have a - * tangible difference in the function’s performance. + * calibrate function’s 1ms sample rate. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port is not configured as an analog input * * \return The average sensor value computed by this function - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void initialize() { * pros::adi::AnalogIn sensor (ANALOG_SENSOR_PORT); * sensor.calibrate(ANALOG_SENSOR_PORT); @@ -316,11 +338,11 @@ class AnalogIn : protected Port { * * \return The difference of the sensor value from its calibrated default from * -4095 to 4095 - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void initialize() { * pros::adi::AnalogIn sensor (ANALOG_SENSOR_PORT); * sensor.calibrate(ANALOG_SENSOR_PORT); @@ -349,12 +371,12 @@ class AnalogIn : protected Port { * ENODEV - The port is not configured as an analog input * * \return The difference of the sensor value from its calibrated default from - * -16384 to - * + * -16384 to 16384 + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void initialize() { * pros::adi::AnalogIn sensor (ANALOG_SENSOR_PORT); * sensor.calibrate(ANALOG_SENSOR_PORT); @@ -367,22 +389,23 @@ class AnalogIn : protected Port { /** * Reads an analog input channel and returns the 12-bit value. - * - * The value returned is undefined if the analog pin has been switched to a different mode. The meaning of the returned value varies depending on the sensor attached. - * + * + * The value returned is undefined if the analog pin has been switched to a different mode. The meaning of the + * returned value varies depending on the sensor attached. + * * Inherited from ADIPort::get_value. - * + * * This function uses the following values of errno when an error state is reached: * EADDRINUSE - The port is not configured as an analog input (e.g. the port has been reconfigured) - * + * * \return The analog sensor value, where a value of 0 reflects an input * voltage of nearly 0 V and a value of 4095 reflects an input voltage of * nearly 5 V - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void initialize() { * pros::adi::AnalogIn sensor (ANALOG_SENSOR_PORT); * std::cout << "Sensor Reading:" << sensor.get_value(); @@ -392,14 +415,16 @@ class AnalogIn : protected Port { using Port::get_value; /** - * This is the overload for the << operator for printing to streams - * - * Prints in format(this below is all in one line with no new line): + * This is the overload for the << operator for printing to streams + * + * Prints in format(this below is all in one line with no new line): * AnalogIn [smart_port: analog_in._smart_port, adi_port: analog_in._adi_port, - * value calibrated: (12 bit calibrated value), + * value calibrated: (12 bit calibrated value), * value calibrated HR: (16 bit calibrated value), value: (12 bit value)] */ friend std::ostream& operator<<(std::ostream& os, pros::adi::AnalogIn& analog_in); + + using Port::get_port; }; ///@} @@ -425,11 +450,11 @@ class AnalogOut : private Port { * * \param adi_port * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::AnalogOut sensor (ANALOG_SENSOR_PORT); * // Use the sensor @@ -449,14 +474,14 @@ class AnalogOut : private Port { * \param port_pair * The pair of the smart port number (from 1-22) and the * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure - * + * * \b Example * \code * #define EXT_ADI_SMART_PORT 1 * #define ADI_PORT 'a' - * + * * void opcontrol() { - * pros::AnalogOut sensor ({{EXT_ADI_SMART_PORT, ADI_PORT}}); + * pros::AnalogOut sensor ({EXT_ADI_SMART_PORT, ADI_PORT}); * // Use the sensor * } * \endcode @@ -467,7 +492,7 @@ class AnalogOut : private Port { * Sets the output for the Analog Output from 0 (0V) to 4095 (5V). * * Inherited from ADIPort::set_value. - * + * * This function uses the following values of errno when an error state is reached: * EACCES - Another resource is currently trying to access the ADI. * @@ -476,11 +501,11 @@ class AnalogOut : private Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define ANALOG_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::AnalogOut sensor (ANALOG_SENSOR_PORT); * sensor.set_value(4095); // Set the port to 5V @@ -489,16 +514,17 @@ class AnalogOut : private Port { */ using Port::set_value; + using Port::get_port; + /** * This is the overload for the << operator for printing to streams - * - * Prints in format(this below is all in one line with no new line): + * + * Prints in format(this below is all in one line with no new line): * AnalogOut [smart_port: analog_out._smart_port, adi_port: analog_out._adi_port, * value: (value)] */ friend std::ostream& operator<<(std::ostream& os, pros::adi::AnalogOut& analog_out); }; - ///@} class DigitalOut : private Port { @@ -519,11 +545,11 @@ class DigitalOut : private Port { * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param init_state * The initial state for the port - * + * * \b Example * \code * #define DIGITAL_SENSOR_PORT 1 - * + * * void opcontrol() { * bool state = LOW; * pros::adi::DigitalOut sensor (DIGITAL_SENSOR_PORT, state); @@ -550,15 +576,15 @@ class DigitalOut : private Port { * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param init_state * The initial state for the port - * + * * \b Example * \code * #define EXT_ADI_SMART_PORT 1 * #define ADI_PORT 'a' - * + * * void opcontrol() { * bool state = LOW; - * pros::adi::DigitalOut sensor ( {{ EXT_ADI_SMART_PORT , ADI_PORT }}); + * pros::adi::DigitalOut sensor ({EXT_ADI_SMART_PORT , ADI_PORT}); * while (true) { * state != state; * sensor.set_value(state); @@ -573,7 +599,7 @@ class DigitalOut : private Port { * Sets the digital value (1 or 0) of a pin. * * Inherited from ADIPort::set_value. - * + * * This function uses the following values of errno when an error state is * reached: * EADDRINUSE - The port is not configured as a digital output (e.g. the port has been reconfigured) @@ -582,11 +608,11 @@ class DigitalOut : private Port { * The value to set the ADI port to * * \return if the operation was successful or PROS_ERR if the operation failed, setting errno. - * + * * \b Example * \code * #define DIGITAL_SENSOR_PORT 1 - * + * * void opcontrol() { * bool state = LOW; * pros::adi::DigitalOut sensor (DIGITAL_SENSOR_PORT); @@ -600,13 +626,15 @@ class DigitalOut : private Port { */ using Port::set_value; + using Port::get_port; + /** * This is the overload for the << operator for printing to streams * * Prints in format(this below is all in one line with no new line): * DigitalOut [smart_port: digital_out._smart_port, adi_port: digital_out._adi_port, * value: (value)] - */ + */ friend std::ostream& operator<<(std::ostream& os, pros::adi::DigitalOut& digital_out); }; ///@} @@ -615,7 +643,7 @@ class DigitalIn : private Port { /** * \addtogroup cpp-adi * @{ - */ + */ public: /** * Configures an ADI port to act as a Digital Input. @@ -627,11 +655,11 @@ class DigitalIn : private Port { * * \param adi_port * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure - * + * * \b Example * \code * #define DIGITAL_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::adi::DigitalIn sensor (ANALOG_SENSOR_PORT); * // Use the sensor @@ -651,14 +679,14 @@ class DigitalIn : private Port { * \param port_pair * The pair of the smart port number (from 1-22) and the * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure - * + * * \b Example * \code * #define EXT_ADI_SMART_PORT 1 * #define ADI_PORT 'a' - * + * * void opcontrol() { - * pros::adi::DigitalIn sensor ({{EXT_ADI_SMART_PORT, ADI_PORT}}); + * pros::adi::DigitalIn sensor ({EXT_ADI_SMART_PORT, ADI_PORT}); * // Use the sensor * } * \endcode @@ -682,11 +710,11 @@ class DigitalIn : private Port { * * \return 1 if the button is pressed and had not been pressed the last time * this function was called, 0 otherwise. - * + * * \b Example * \code * #define DIGITAL_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::adi::DigitalIn sensor (DIGITAL_SENSOR_PORT); * while (true) { @@ -702,21 +730,21 @@ class DigitalIn : private Port { /** * Gets the digital value (1 or 0) of a pin. - * + * * Inherited from ADIPort::get_value. - * + * * This function uses the following values of errno when an error state is reached: - * + * * EADDRINUSE - The port is not configured as a digital input (e.g. the port has been reconfigured) - * + * * Analogous to adi_digital_read. * * \return The value stored for the given port - * + * * \b Example * \code * #define DIGITAL_SENSOR_PORT 1 - * + * * void opcontrol() { * pros::adi::DigitalIn sensor (DIGITAL_SENSOR_PORT); * while (true) { @@ -736,18 +764,20 @@ class DigitalIn : private Port { * value: (value)] */ friend std::ostream& operator<<(std::ostream& os, pros::adi::DigitalIn& digital_in); + + using Port::get_port; }; ///@} -//Derived Class(es) from DigitalIn +// Derived Class(es) from DigitalIn using Button = DigitalIn; class Motor : private Port { /** * \addtogroup cpp-adi * @{ - */ + */ public: /** * Configures an ADI port to act as a Motor. @@ -759,11 +789,11 @@ class Motor : private Port { * * \param adi_port * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure - * + * * \b Example * \code * #define MOTOR_PORT 1 - * + * * void opcontrol() { * pros::adi::Motor motor (MOTOR_PORT); * motor.set_value(127); // Go full speed forward @@ -786,14 +816,14 @@ class Motor : private Port { * \param port_pair * The pair of the smart port number (from 1-22) and the * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure - * + * * \b Example * \code * #define EXT_ADI_SMART_PORT 1 * #define ADI_MOTOR_PORT 'a' - * + * * void opcontrol() { - * pros::adi::Motor motor ( {{ EXT_ADI_SMART_PORT , ADI_MOTOR_PORT}} ); + * pros::adi::Motor motor ({EXT_ADI_SMART_PORT, ADI_MOTOR_PORT}); * motor.set_value(127); // Go full speed forward * std::cout << "Commanded Motor Power: " << motor.get_value(); // Will display 127 * delay(1000); @@ -812,11 +842,11 @@ class Motor : private Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define MOTOR_PORT 1 - * + * * void opcontrol() { * pros::adi::Motor motor (MOTOR_PORT); * motor.set_value(127); // Go full speed forward @@ -841,11 +871,11 @@ class Motor : private Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define MOTOR_PORT 1 - * + * * void opcontrol() { * pros::adi::Motor motor (MOTOR_PORT); * motor.set_value(127); // Go full speed forward @@ -864,13 +894,13 @@ class Motor : private Port { * reached: * ENODEV - The port is not configured as a motor * - * \return The last set speed of the motor on the given - * + * \return The last set speed of the motor on the given + * * \b Example * \code * #define MOTOR_PORT 1 - * - * void opcontrol() { + * + * void opcontrol() { * pros::adi::Motor motor (MOTOR_PORT); * motor.set_value(127); // Go full speed forward * std::cout << "Commanded Motor Power: " << motor.get_value(); // Will display 127 @@ -880,6 +910,8 @@ class Motor : private Port { * \endcode */ using Port::get_value; + + using Port::get_port; }; ///@} @@ -888,7 +920,7 @@ class Encoder : private Port { /** * \addtogroup cpp-adi * @{ - */ + */ public: /** * Configures a set of ADI ports to act as an Encoder. @@ -904,12 +936,12 @@ class Encoder : private Port { * The "bottom" wire from the encoder sensor * \param reverse * If "true", the sensor will count in the opposite direction - * + * * \b Example * \code * #define PORT_TOP 1 * #define PORT_BOTTOM 2 - * + * * void opcontrol() { * pros::adi::Encoder sensor (PORT_TOP, PORT_BOTTOM, false); * // Use the sensor @@ -932,13 +964,13 @@ class Encoder : private Port { * the encoder sensor * \param reverse * If "true", the sensor will count in theopposite direction - * + * * \b Example * \code * #define PORT_TOP 'A' * #define PORT_BOTTOM 'B' * #define SMART_PORT 1 - * + * * void opcontrol() { * pros::adi::Encoder sensor ({ SMART_PORT, PORT_TOP, PORT_BOTTOM }, false); * // Use the sensor @@ -959,12 +991,12 @@ class Encoder : private Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define PORT_TOP 1 * #define PORT_BOTTOM 2 - * + * * void opcontrol() { * pros::adi::Encoder sensor (PORT_TOP, PORT_BOTTOM, false); * delay(1000); // Move the encoder around in this time @@ -984,12 +1016,12 @@ class Encoder : private Port { * ENODEV - The port is not configured as a motor * * \return The signed and cumulative number of counts since the last start or - * + * * \b Example * \code * #define PORT_TOP 1 * #define PORT_BOTTOM 2 - * + * * void opcontrol() { * pros::adi::Encoder sensor (PORT_TOP, PORT_BOTTOM, false); * while (true) { @@ -1007,8 +1039,12 @@ class Encoder : private Port { * Prints in format(this below is all in one line with no new line): * Encoder [smart_port: encoder._smart_port, adi_port: encoder._adi_port, * value: (value)] - */ + */ friend std::ostream& operator<<(std::ostream& os, pros::adi::Encoder& encoder); + ext_adi_port_tuple_t get_port() const override; + + private: + ext_adi_port_pair_t _port_pair; }; ///@} @@ -1017,7 +1053,7 @@ class Ultrasonic : private Port { /** * \addtogroup cpp-adi * @{ - */ + */ public: /** * Configures a set of ADI ports to act as an Ultrasonic sensor. @@ -1033,12 +1069,12 @@ class Ultrasonic : private Port { * \param port_echo * The port connected to the yellow INPUT cable. This should be in the * next highest port following port_ping. - * + * * \b Example * \code * #define PORT_PING 1 * #define PORT_ECHO 2 - * + * * void opcontrol() { * pros::adi::Ultrasonic sensor (PORT_PING, PORT_ECHO); * while (true) { @@ -1064,13 +1100,13 @@ class Ultrasonic : private Port { * OUTPUT cable (1, 3, 5, 7 or 'A', 'C', 'E', 'G'), and the port * connected to the yellow INPUT cable (the next) highest port * following port_ping). - * + * * \b Example * \code * #define PORT_PING 'A' * #define PORT_ECHO 'B' * #define SMART_PORT 1 - * + * * void opcontrol() { * pros::adi::Ultrasonic sensor ( {{ SMART_PORT, PORT_PING, PORT_ECHO }} ); * while (true) { @@ -1096,12 +1132,12 @@ class Ultrasonic : private Port { * * \return The distance to the nearest object in m^-4 (10000 indicates 1 * meter), measured from the sensor's mounting points. - * + * * \b Example * \code * #define PORT_PING 1 * #define PORT_ECHO 2 - * + * * void opcontrol() { * pros::adi::Ultrasonic sensor (PORT_PING, PORT_ECHO); * while (true) { @@ -1113,6 +1149,8 @@ class Ultrasonic : private Port { * \endcode */ std::int32_t get_value() const; + + using Port::get_port; }; ///@} @@ -1121,7 +1159,7 @@ class Gyro : private Port { /** * \addtogroup cpp-adi * @{ - */ + */ public: /** * Initializes a gyroscope on the given port. If the given port has not @@ -1143,12 +1181,12 @@ class Gyro : private Port { * The ADI port to initialize as a gyro (from 1-8, 'a'-'h', 'A'-'H') * \param multiplier * A scalar value that will be multiplied by the gyro heading value - * supplied by the - * + * supplied by the + * * \b Example * \code * #define GYRO_PORT 1 - * + * * void opcontrol() { * pros::adi::Gyro gyro (GYRO_PORT); * while (true) { @@ -1182,15 +1220,15 @@ class Gyro : private Port { * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param multiplier * A scalar value that will be multiplied by the gyro heading value - * supplied by the - * + * supplied by the + * * \b Example * \code * #define ADI_GYRO_PORT 'a' * #define SMART_PORT 1 - * + * * void opcontrol() { - * pros::adi::Gyro gyro ({{ SMART_PORT , ADI_GYRO_PORT }}); + * pros::adi::Gyro gyro ({SMART_PORT ,ADI_GYRO_PORT}); * while (true) { * // Get the gyro heading * std::cout << "Distance: " << gyro.get_value(); @@ -1200,7 +1238,7 @@ class Gyro : private Port { * \endcode */ explicit Gyro(ext_adi_port_pair_t port_pair, double multiplier = 1); - + /** * Gets the current gyro angle in tenths of a degree. Unless a multiplier is * applied to the gyro, the return value will be a whole number representing @@ -1214,11 +1252,11 @@ class Gyro : private Port { * ENODEV - The port is not configured as a gyro * * \return The gyro angle in degrees. - * + * * \b Example * \code * #define GYRO_PORT 1 - * + * * void opcontrol() { * pros::adi::Gyro gyro (GYRO_PORT); * while (true) { @@ -1240,30 +1278,32 @@ class Gyro : private Port { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * #define GYRO_PORT 1 - * + * * void opcontrol() { * pros::adi::Gyro gyro (GYRO_PORT); * std::uint32_t now = pros::millis(); * while (true) { * // Get the gyro heading * std::cout << "Distance: " << gyro.get_value(); - * + * * if (pros::millis() - now > 2000) { * // Reset the gyro every 2 seconds * gyro.reset(); * now = pros::millis(); * } - * + * * pros::delay(10); * } * } * \endcode */ std::int32_t reset() const; + + using Port::get_port; }; ///@} @@ -1272,7 +1312,7 @@ class Potentiometer : public AnalogIn { /** * \addtogroup cpp-adi * @{ - */ + */ public: /** * Configures an ADI port to act as a Potentiometer. @@ -1285,22 +1325,22 @@ class Potentiometer : public AnalogIn { * \param adi_port * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param potentiometer_type - * An adi_potentiometer_type_e_t enum value specifying the potentiometer version type - * - * \b Example - * \code - * #define POTENTIOMETER_PORT 1 - * #define POTENTIOMETER_TYPE pros::E_ADI_POT_EDR - * - * void opcontrol() { - * pros::adi::Potentiometer potentiometer (POTENTIOMETER_PORT, POTENTIOMETER_TYPE); - * while (true) { - * // Get the potentiometer angle - * std::cout << "Angle: " << potentiometer.get_angle(); - * pros::delay(10); - * } - * } - * \endcode + * An adi_potentiometer_type_e_t enum value specifying the potentiometer version type + * + * \b Example + * \code + * #define POTENTIOMETER_PORT 1 + * #define POTENTIOMETER_TYPE pros::E_ADI_POT_EDR + * + * void opcontrol() { + * pros::adi::Potentiometer potentiometer (POTENTIOMETER_PORT, POTENTIOMETER_TYPE); + * while (true) { + * // Get the potentiometer angle + * std::cout << "Angle: " << potentiometer.get_angle(); + * pros::delay(10); + * } + * } + * \endcode */ explicit Potentiometer(std::uint8_t adi_port, adi_potentiometer_type_e_t potentiometer_type = E_ADI_POT_EDR); @@ -1316,15 +1356,15 @@ class Potentiometer : public AnalogIn { * The pair of the smart port number (from 1-22) and the * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param potentiometer_type - * An adi_potentiometer_type_e_t enum value specifying the potentiometer version type - * + * An adi_potentiometer_type_e_t enum value specifying the potentiometer version type + * * \b Example * \code * #define ADI_POTENTIOMETER_PORT 'a' * #define SMART_PORT 1 - * + * * void opcontrol() { - * pros::adi::Potentiometer potentiometer ({{ SMART_PORT , ADI_POTENTIOMETER_PORT }}); + * pros::adi::Potentiometer potentiometer ({SMART_PORT, ADI_POTENTIOMETER_PORT}); * while (true) { * // Get the potentiometer angle * std::cout << "Angle: " << potentiometer.get_angle(); @@ -1345,14 +1385,14 @@ class Potentiometer : public AnalogIn { * reached: * ENXIO - The given value is not within the range of ADI Ports * EADDRINUSE - The port is not configured as a potentiometer - * + * * \return The potentiometer angle in degrees. - * + * * \b Example * \code * #define ADI_POTENTIOMETER_PORT 'a' * #define SMART_PORT 1 - * + * * void opcontrol() { * pros::adi::Potentiometer potentiometer ({{ SMART_PORT , ADI_POTENTIOMETER_PORT }}); * while (true) { @@ -1419,20 +1459,26 @@ class Potentiometer : public AnalogIn { /** * This is the overload for the << operator for printing to streams - * Potentiometer [value: (value), value calibrated: (calibrated value), + * Potentiometer [value: (value), value calibrated: (calibrated value), * angle: (angle)] * Prints in format(this below is all in one line with no new line): - */ + */ friend std::ostream& operator<<(std::ostream& os, pros::adi::Potentiometer& potentiometer); + + using Port::get_port; }; ///@} class Led : protected Port { + /** + * \addtogroup cpp-adi + * @{ + */ public: /** * @brief Configures an ADI port to act as a LED. - * + * * This function uses the following values of errno when an error state is * reached: * ENXIO - Either the ADI port value or the smart port value is not within its @@ -1442,12 +1488,12 @@ class Led : protected Port { * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param length * The number of LEDs in the chain - * - * \b Example: + * + * \b Example: * \code * #define LED_PORT 'a' * #define LED_LENGTH 3 - * + * * void opcontrol() { * pros::Led led (LED_PORT, LED_LENGTH); * while (true) { @@ -1456,14 +1502,14 @@ class Led : protected Port { * pros::delay(20); * } * } - * \endcode - * + * \endcode + * */ explicit Led(std::uint8_t adi_port, std::uint32_t length); /** * @brief Configures an ADI port on a adi_expander to act as a LED. - * + * * This function uses the following values of errno when an error state is * reached: * ENXIO - Either the ADI port value or the smart port value is not within its @@ -1474,15 +1520,15 @@ class Led : protected Port { * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param length * The number of LEDs in the chain - * - * \b Example: + * + * \b Example: * \code * #define LED_PORT 'a' * #define SMART_PORT 1 * #define LED_LENGTH 3 - * + * * void opcontrol() { - * pros::Led led ({{ SMART_PORT , LED_PORT }}, LED_LENGTH); + * pros::Led led ({SMART_PORT, LED_PORT}, LED_LENGTH); * while (true) { * // Set entire LED strip to red * led.set_all(0xFF0000); @@ -1494,17 +1540,17 @@ class Led : protected Port { explicit Led(ext_adi_port_pair_t port_pair, std::uint32_t length); /** - * @brief Operator overload to access the buffer in the ADILed class, it is + * @brief Operator overload to access the buffer in the ADILed class, it is * recommended that you call .update(); after doing any operations with this. - * + * * @param i 0 indexed pixel of the lED * @return uint32_t& the address of the buffer at i to modify - * - * \b Example: + * + * \b Example: * \code * #define LED_PORT 'a' * #define LED_LENGTH 3 - * + * * void opcontrol() { * pros::Led led (LED_PORT, LED_LENGTH); * while (true) { @@ -1513,7 +1559,7 @@ class Led : protected Port { * led.set_pixel(0x00FF00, 1); * led.set_pixel(0x0000FF, 2); * pros::delay(20); - * + * * // Use the [] operator to set the first pixel to black * led.operator[](0) = 0x000000; * led.update(); @@ -1521,205 +1567,211 @@ class Led : protected Port { * } * } */ - std::uint32_t& operator[] (size_t i); - - /** - * @brief Clear the entire led strip of color - * - * This function uses the following values of errno when an error state is - * reached: - * ENXIO - The given value is not within the range of ADI Ports - * EINVAL - A parameter is out of bounds/incorrect - * EADDRINUSE - The port is not configured for ADI output - * - * @return PROS_SUCCESS if successful, PROS_ERR if not - * - * \b Example: - * \code - * #define LED_PORT 'a' - * #define LED_LENGTH 3 - * - * void opcontrol() { - * pros::Led led (LED_PORT, LED_LENGTH); - * while (true) { - * // Set the first 3 pixels to red, green, and blue - * led.set_pixel(0xFF0000, 0); - * led.set_pixel(0x00FF00, 1); - * led.set_pixel(0x0000FF, 2); - * pros::delay(20); - * - * // Clear the led strip of color - * led.clear(); - * pros::delay(20); - * } - * } - * \endcode - */ + std::uint32_t& operator[](size_t i); + + /** + * @brief Clear the entire led strip of color + * + * This function uses the following values of errno when an error state is + * reached: + * ENXIO - The given value is not within the range of ADI Ports + * EINVAL - A parameter is out of bounds/incorrect + * EADDRINUSE - The port is not configured for ADI output + * + * @return PROS_SUCCESS if successful, PROS_ERR if not + * + * \b Example: + * \code + * #define LED_PORT 'a' + * #define LED_LENGTH 3 + * + * void opcontrol() { + * pros::Led led (LED_PORT, LED_LENGTH); + * while (true) { + * // Set the first 3 pixels to red, green, and blue + * led.set_pixel(0xFF0000, 0); + * led.set_pixel(0x00FF00, 1); + * led.set_pixel(0x0000FF, 2); + * pros::delay(20); + * + * // Clear the led strip of color + * led.clear(); + * pros::delay(20); + * } + * } + * \endcode + */ std::int32_t clear_all(); std::int32_t clear(); - - /** - * @brief Force the LED strip to update with the current buffered values, this - * should be called after any changes to the buffer using the [] operator. - * - * This function uses the following values of errno when an error state is - * reached: - * EINVAL - A parameter is out of bounds/incorrect - * EADDRINUSE - The port is not configured for ADI output - * - * @return PROS_SUCCESS if successful, PROS_ERR if not - * - * \b Example: - * \code - * #define LED_PORT 'a' - * #define LED_LENGTH 3 - * - * void opcontrol() { - * pros::Led led (LED_PORT, LED_LENGTH); - * while (true) { - * // Set the first 3 pixels to red, green, and blue - * led.set_pixel(0xFF0000, 0); - * led.set_pixel(0x00FF00, 1); - * led.set_pixel(0x0000FF, 2); - * pros::delay(20); - * - * // Use the [] operator to set the first pixel to black - * led.operator[](0) = 0x000000; - * // Update the led strip with the new values - * led.update(); - * pros::delay(20); - * } - * } - * \endcode - */ + + /** + * @brief Force the LED strip to update with the current buffered values, this + * should be called after any changes to the buffer using the [] operator. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A parameter is out of bounds/incorrect + * EADDRINUSE - The port is not configured for ADI output + * + * @return PROS_SUCCESS if successful, PROS_ERR if not + * + * \b Example: + * \code + * #define LED_PORT 'a' + * #define LED_LENGTH 3 + * + * void opcontrol() { + * pros::Led led (LED_PORT, LED_LENGTH); + * while (true) { + * // Set the first 3 pixels to red, green, and blue + * led.set_pixel(0xFF0000, 0); + * led.set_pixel(0x00FF00, 1); + * led.set_pixel(0x0000FF, 2); + * pros::delay(20); + * + * // Use the [] operator to set the first pixel to black + * led.operator[](0) = 0x000000; + * // Update the led strip with the new values + * led.update(); + * pros::delay(20); + * } + * } + * \endcode + */ std::int32_t update() const; /** - * @brief Set the entire led strip to one color - * - * This function uses the following values of errno when an error state is - * reached: - * EINVAL - A parameter is out of bounds/incorrect - * EADDRINUSE - The port is not configured for ADI output - * - * @param color color to set all the led strip value to - * @return PROS_SUCCESS if successful, PROS_ERR if not - * - * \b Example: - * \code - * #define LED_PORT 'a' - * #define LED_LENGTH 3 - * - * void opcontrol() { - * pros::Led led (LED_PORT, LED_LENGTH); - * while (true) { - * // Set the entire led strip to blue - * led.set_all(0x0000FF); - * pros::delay(20); - * } - * } - * \endcode - */ + * @brief Set the entire led strip to one color + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A parameter is out of bounds/incorrect + * EADDRINUSE - The port is not configured for ADI output + * + * @param color color to set all the led strip value to + * @return PROS_SUCCESS if successful, PROS_ERR if not + * + * \b Example: + * \code + * #define LED_PORT 'a' + * #define LED_LENGTH 3 + * + * void opcontrol() { + * pros::Led led (LED_PORT, LED_LENGTH); + * while (true) { + * // Set the entire led strip to blue + * led.set_all(0x0000FF); + * pros::delay(20); + * } + * } + * \endcode + */ std::int32_t set_all(uint32_t color); /** - * @brief Set one pixel on the led strip - * - * This function uses the following values of errno when an error state is - * reached: - * EINVAL - A parameter is out of bounds/incorrect - * EADDRINUSE - The port is not configured for ADI output - * - * @param color color to clear all the led strip to - * @param pixel_position position of the pixel to clear - * @return PROS_SUCCESS if successful, PROS_ERR if not - * - * \b Example: - * \code - * #define LED_PORT 'a' - * #define LED_LENGTH 3 - * - * void opcontrol() { - * pros::Led led (LED_PORT, LED_LENGTH); - * while (true) { - * // Set the first pixel to blue - * led.set_pixel(0x0000FF, 0); - * pros::delay(20); - * } - * } - * \endcode - */ + * @brief Set one pixel on the led strip + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A parameter is out of bounds/incorrect + * EADDRINUSE - The port is not configured for ADI output + * + * @param color color to clear all the led strip to + * @param pixel_position position of the pixel to clear + * @return PROS_SUCCESS if successful, PROS_ERR if not + * + * \b Example: + * \code + * #define LED_PORT 'a' + * #define LED_LENGTH 3 + * + * void opcontrol() { + * pros::Led led (LED_PORT, LED_LENGTH); + * while (true) { + * // Set the first pixel to blue + * led.set_pixel(0x0000FF, 0); + * pros::delay(20); + * } + * } + * \endcode + */ std::int32_t set_pixel(uint32_t color, uint32_t pixel_position); /** - * @brief Clear one pixel on the led strip - * - * This function uses the following values of errno when an error state is - * reached: - * EINVAL - A parameter is out of bounds/incorrect - * EADDRINUSE - The port is not configured for ADI output - * - * @param pixel_position position of the pixel to clear - * @return PROS_SUCCESS if successful, PROS_ERR if not - * - * \b Example: - * \code - * #define LED_PORT 'a' - * #define LED_LENGTH 3 - * - * void opcontrol() { - * pros::Led led (LED_PORT, LED_LENGTH); - * while (true) { - * // Set the first pixel to blue - * led.set_pixel(0x0000FF, 0); - * pros::delay(20); - * - * // Clear the first pixel - * led.clear_pixel(0); - * pros::delay(20); - * } - * } - * \endcode - */ + * @brief Clear one pixel on the led strip + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A parameter is out of bounds/incorrect + * EADDRINUSE - The port is not configured for ADI output + * + * @param pixel_position position of the pixel to clear + * @return PROS_SUCCESS if successful, PROS_ERR if not + * + * \b Example: + * \code + * #define LED_PORT 'a' + * #define LED_LENGTH 3 + * + * void opcontrol() { + * pros::Led led (LED_PORT, LED_LENGTH); + * while (true) { + * // Set the first pixel to blue + * led.set_pixel(0x0000FF, 0); + * pros::delay(20); + * + * // Clear the first pixel + * led.clear_pixel(0); + * pros::delay(20); + * } + * } + * \endcode + */ std::int32_t clear_pixel(uint32_t pixel_position); /** - * @brief Get the length of the led strip - * - * This function uses the following values of errno when an error state is - * reached: - * EINVAL - A parameter is out of bounds/incorrect - * EADDRINUSE - The port is not configured for ADI output - * - * @return The length (in pixels) of the LED strip - * - * \b Example: - * \code - * #define LED_PORT 'a' - * #define LED_LENGTH 3 - * - * void opcontrol() { - * pros::Led led (LED_PORT, LED_LENGTH); - * while (true) { - * // Get the length of the led strip - * int length = led.length(); - * pros::lcd::print(1, "Length: %d", length); - * pros::delay(20); - * } - * } - * \endcode - */ + * @brief Get the length of the led strip + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - A parameter is out of bounds/incorrect + * EADDRINUSE - The port is not configured for ADI output + * + * @return The length (in pixels) of the LED strip + * + * \b Example: + * \code + * #define LED_PORT 'a' + * #define LED_LENGTH 3 + * + * void opcontrol() { + * pros::Led led (LED_PORT, LED_LENGTH); + * while (true) { + * // Get the length of the led strip + * int length = led.length(); + * pros::lcd::print(1, "Length: %d", length); + * pros::delay(20); + * } + * } + * \endcode + */ std::int32_t length(); + using Port::get_port; + protected: std::vector _buffer; }; +///@} -// Alias for ADILed +/// @brief Alias for ADILed using LED = Led; - class Pneumatics : public DigitalOut { + /** + * \addtogroup cpp-adi + * @{ + */ public: /** * Creates a Pneumatics object for the given port. @@ -1731,29 +1783,46 @@ class Pneumatics : public DigitalOut { * \param adi_port * The ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param start_extended - * If true, the pneumatic will start the match extended - * \param active_low - * If set to true, a value of false corresponds to the pneumatic's - * wire being set to high. - * - * \b Example + * If true, the pneumatic will start extended when the program starts. + * By default, the piston starts retracted when the program starts. + * \param extended_is_low + * A flag to set whether the the pneumatic is extended when the ADI + * it receives a high or a low value. When true, the extended state + * corresponds to a output low on the ADI port. This allows the user + * to reverse the behavior of the pneumatics if needed. + * + * /b Example: * \code - * #define ADI_PNEUMATICS_PORT 'a' - * * void opcontrol() { - * pros::adi::Pneumatics pneumatics (ADI_PNEUMATICS_PORT); + * pros::adi::Pneumatics left_piston('a', false); // Starts retracted, extends when the ADI port is high + * pros::adi::Pneumatics right_piston('b', false, true); // Starts retracted, extends when the ADI port is low + * + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * * while (true) { - * // Set the pneumatic solenoid to true - * pneumatics.set_value(true); + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_L1)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_L2)) { + * left_piston.retract(); + * } + * + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_R1)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_2)) { + * left_piston.retract(); + * } + * * pros::delay(10); * } - * } + * * \endcode */ - explicit Pneumatics(std::uint8_t adi_port, bool start_extended, bool active_low = false); + explicit Pneumatics(std::uint8_t adi_port, bool start_extended, bool extended_is_low = false); /** - * Creates a Pneumatics object for the given port. + * Creates a Pneumatics object for the given port pair. * * This function uses the following values of errno when an error state is * reached: @@ -1763,129 +1832,182 @@ class Pneumatics : public DigitalOut { * The pair of the smart port number (from 1-22) and the * ADI port number (from 1-8, 'a'-'h', 'A'-'H') to configure * \param start_extended - * If true, the pneumatic will start the match extended - * \param active_low - * If set to true, a value of false corresponds to the pneumatic's - * wire being set to high. - * - * \b Example + * If true, the pneumatic will start extended when the program starts. + * By default, the piston starts retracted when the program starts. + * \param extended_is_low + * A flag to set whether the the pneumatic is extended when the ADI + * it receives a high or a low value. When true, the extended state + * corresponds to a output low on the ADI port. This allows the user + * to reverse the behavior of the pneumatics if needed. + * + * /b Example: * \code - * #define ADI_PNEUMATICS_PORT 'a' - * #define SMART_PORT 1 + * void opcontrol() { + * pros::adi::Pneumatics left_piston({1, 'a'}, false); // Starts retracted, extends when the ADI port is high + * pros::adi::Pneumatics right_piston({1, 'b'}, false, true); // Starts retracted, extends when the ADI port is + *low * + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * + * while (true) { + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_L1)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_L2)) { + * left_piston.retract(); + * } + * + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_R1)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_R2)) { + * left_piston.retract(); + * } + * + * pros::delay(10); + * } + * } + * \endcode + */ + explicit Pneumatics(ext_adi_port_pair_t port_pair, bool start_extended, bool extended_is_low = false); + + /** + * Extends the piston, if not already extended. + * + * \return 1 if the piston newly extended, 0 if the piston was already + * extended, or PROS_ERR is the operation failed, setting errno. + * + * \b Example: + * \code * void opcontrol() { - * pros::adi::Pneumatics pneumatics ({{ SMART_PORT , ADI_PNEUMATICS_PORT }}); + * pros::adi::Pneumatics piston({1, 'a'}, false); // Starts retracted, extends when the ADI port is high + * + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * * while (true) { - * // Set the pneumatic solenoid to true - * pneumatics.set_value(true); + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_X)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_B)) { + * left_piston.retract(); + * } + * if(mastetr.get_digital(pros::E_CONTROLLER_DIGITAL_A)) { + * left_piston.toggle(); + * } + * * pros::delay(10); * } * } * \endcode */ - explicit Pneumatics(ext_adi_port_pair_t port_pair, bool start_extended, bool active_low = false); - - /* - * Extends the piston, if not already extended. - * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. - * - * \b Example - * \code - * #define ADI_PNEUMATICS_PORT 'a' - * - * void opcontrol() { - * pros::adi::Pneumatics pneumatics (ADI_PNEUMATICS_PORT); - * while (true) { - * // Extend the piston - * pneumatics.extend(); - * pros::delay(10); - * } - * } - * \endcode - */ std::int32_t extend(); - /* - * Retracts the piston, if not already retracted. - * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. - * - * \b Example - * \code - * #define ADI_PNEUMATICS_PORT 'a' - * - * void opcontrol() { - * pros::adi::Pneumatics pneumatics (ADI_PNEUMATICS_PORT); - * while (true) { - * // Retract the piston - * pneumatics.retract(); - * pros::delay(10); - * } - * } - * \endcode - */ + /** + * Retracts the piston, if not already retracted. + * + * \return 1 if the piston newly retracted, 0 if the piston was already + * retracted, or PROS_ERR is the operation failed, setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::adi::Pneumatics piston({1, 'a'}, false); // Starts retracted, extends when the ADI port is high + * + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * + * while (true) { + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_X)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_B)) { + * left_piston.retract(); + * } + * if(mastetr.get_digital(pros::E_CONTROLLER_DIGITAL_A)) { + * left_piston.toggle(); + * } + * + * pros::delay(10); + * } + * } + * \endcode + */ std::int32_t retract(); - /* - * Puts the piston into the opposite state of its current state. - * If it is retracted, it will extend. If it is extended, it will retract. - * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. - * - * \b Example - * \code - * #define ADI_PNEUMATICS_PORT 'a' - * - * void opcontrol() { - * pros::adi::Pneumatics pneumatics (ADI_PNEUMATICS_PORT); - * while (true) { - * // Toggle the piston - * pneumatics.toggle(); - * pros::delay(10); - * } - * } - * \endcode - */ + /** + * Puts the piston into the opposite state of its current state. + * If it is retracted, it will extend. If it is extended, it will retract. + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \return 1 if the piston successfully toggled, or PROS_ERR if the + * operation failed, setting errno. + * + *\b Example: + * \code + * void opcontrol() { + * pros::adi::Pneumatics piston({1, 'a'}, false); // Starts retracted, extends when the ADI port is high + * + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * + * while (true) { + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_X)) { + * left_piston.extend(); + * } + * if(master.get_digital(pros::E_CONTROLLER_DIGITAL_B)) { + * left_piston.retract(); + * } + * if(mastetr.get_digital(pros::E_CONTROLLER_DIGITAL_A)) { + * left_piston.toggle(); + * } + * + * pros::delay(10); + * } + * } + * \endcode + */ std::int32_t toggle(); - /* - * Returns the current state of the piston. - * - * \return true if the piston is extended, false if it is retracted. - * - * \b Example - * \code - * #define ADI_PNEUMATICS_PORT 'a' - * - * void opcontrol() { - * pros::adi::Pneumatics pneumatics (ADI_PNEUMATICS_PORT); - * while (true) { - * // Check if the piston is extended - * if (pneumatics.get_state()) { - * // Do something - * } - * pros::delay(10); - * } - * } - * \endcode - */ - bool get_state() const; - -private: - bool active_low; - bool state; + /** + * Returns whether the piston is extended or not. + * + * \return true if the piston is extended, false if it is retracted. + * + * \b Example + * \code + * #define ADI_PNEUMATICS_PORT 'a' + * + * void opcontrol() { + * pros::adi::Pneumatics pneumatics (ADI_PNEUMATICS_PORT); + * while (true) { + * // Check if the piston is extended + * if (pneumatics.is_extended()) { + * printf("The pneumatic is extended\n"); + * } + * else { + * printf("The pneumatic is not extended\n"); + * } + * + * pros::delay(10); + * } + * } + * \endcode + */ + bool is_extended() const; + + private: + bool state; // Holds the physical state of the ADI port + bool extended_is_low; // A flag that sets whether extended corresponds to + // a low signal }; +///@} } // namespace adi /* Pros4 upgrade backwards compatibility for ADI api. -Prints a deprecated warning when user uses old pros::ADIDevice style API. +Prints a deprecated warning when user uses old pros::ADIDevice style API. Remove when and if fully removing old API. */ LEGACY_TYPEDEF(ADIPort, pros::adi::Port); @@ -1900,16 +2022,15 @@ LEGACY_TYPEDEF(ADIUltrasonic, pros::adi::Ultrasonic); LEGACY_TYPEDEF(LED, pros::adi::Led); // Backwards Compatibility for Derived Classes -LEGACY_TYPEDEF(ADIPotentiometer,pros::adi::Potentiometer); -LEGACY_TYPEDEF(ADILineSensor,pros::adi::LineSensor); -LEGACY_TYPEDEF(ADILightSensor,pros::adi::LightSensor); -LEGACY_TYPEDEF(ADIAccelerometer,pros::adi::Accelerometer); -LEGACY_TYPEDEF(ADIButton,pros::adi::Button); - -///@} - -///@} +LEGACY_TYPEDEF(ADIPotentiometer, pros::adi::Potentiometer); +LEGACY_TYPEDEF(ADILineSensor, pros::adi::LineSensor); +LEGACY_TYPEDEF(ADILightSensor, pros::adi::LightSensor); +LEGACY_TYPEDEF(ADIAccelerometer, pros::adi::Accelerometer); +LEGACY_TYPEDEF(ADIButton, pros::adi::Button); +LEGACY_TYPEDEF(ADIPneumatics, pros::adi::Pneumatics); +LEGACY_TYPEDEF(ADILED, pros::adi::Led); +LEGACY_TYPEDEF(ADILed, pros::adi::Led); } // namespace pros -#endif // _PROS_ADI_HPP_ +#endif // _PROS_ADI_HPP_ \ No newline at end of file diff --git a/include/pros/ai_vision.h b/include/pros/ai_vision.h new file mode 100644 index 0000000..5deea41 --- /dev/null +++ b/include/pros/ai_vision.h @@ -0,0 +1,502 @@ +/** + * \file pros/aivision.h + * \ingroup c-aivision + * + * Contains prototypes for the VEX AI Vision Sensor-related functions. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \defgroup c-aivision AI Vision Sensor C API + * \note Additional example code for this module can be found in its [Tutorial.](@ref aivision) + */ + +#ifndef _PROS_AIVISION_H_ +#define _PROS_AIVISION_H_ + +/** + * \addtogroup c-aivision + * @{ + */ + +/// \name Macros +/// Parameters given by VEX +///@{ + +#define AIVISION_MAX_OBJECT_COUNT 24 +#define AIVISION_MAX_CLASSNAME_COUNT 20 +#define AIVISION_MODE_TAG_SET_BIT (1 << 29) + +///@} + +///@} + +#include + +#ifdef __cplusplus +extern "C" { +namespace pros { +#endif + +/** + * \addtogroup c-aivision + * @{ + */ + +/** + * \enum aivision_detected_type_e_t + * This enumeration defines what kind of object is stored inside the union in aivision_object_s + */ +typedef enum aivision_detected_type { + E_AIVISION_DETECTED_COLOR = (1 << 0), + E_AIVISION_DETECTED_CODE = (1 << 1), + E_AIVISION_DETECTED_OBJECT = (1 << 2), + E_AIVISION_DETECTED_TAG = (1 << 3) +} aivision_detected_type_e_t; + +/** + * \enum aivision_mode_type_e_t + * This enumeration defines what kinds of objects the ai vision sensor will scan for: + * tags (april tags), colors (user defined colors), and objects (game elements), and all (all objects) + */ + +typedef enum aivision_mode_type { + E_AIVISION_MODE_TAGS = (1 << 0), + E_AIVISION_MODE_COLORS = (1 << 1), + E_AIVISION_MODE_OBJECTS = (1 << 2), + E_AIVISION_MODE_COLOR_MERGE = (1 << 4), + E_AIVISION_MODE_ALL = (1 << 0) | (1 << 1) | (1 << 2), +} aivision_mode_type_e_t; + +/** + * \struct aivision_color_s_t + * This structure contains the parameters used by the AI Vision Sensor to define a color. hue_range and saturation_range + * are ranges for hue and saturation that are acceptable. + * For example, if a large hue range is specified for a blue color, colors that are more magenta or teal may be detected + * as "blue". + */ +typedef struct aivision_color_s { + uint8_t id; /**< id of color descriptor, can range from 1-7 */ + uint8_t red; /**< red value of color */ + uint8_t green; /**< green value of color */ + uint8_t blue; /**< blue value of color */ + float hue_range; /**< range by which detected color's hue can vary from the base color, can range from 1-40 */ + float saturation_range; /**< range by which detected color's saturation can vary from base color, can range from 0.1-1 */ +} aivision_color_s_t; + +/** + * \struct aivision_code_s_t + * This structure contains the parameters used by the AI Vision sensor to define a code. + * Codes are a combination of color descriptors, and tells the AI Vision sensor to merge objects + * close to each other that belong to the given color descriptors into a single object that matches + * the code descriptor. + * Codes must use at least 2, and no greater than 5, color descriptors. + */ +typedef struct aivision_code_s { + uint8_t id; /**< id of code descriptor, can range from 1-5 */ + uint8_t length; /**< number of color descriptors used by this code. */ + int16_t c1; /**< id of first color descriptor */ + int16_t c2; /**< id of second color descriptor */ + int16_t c3; /**< id of third color descriptor */ + int16_t c4; /**< id of fourth color descriptor */ + int16_t c5; /**< id of fifth color descriptor */ +} aivision_code_s_t; + +/** + * \enum aivision_tag_family_e_t + * This enumeration corresponds to a family of AprilTags. + * \see https://april.eecs.umich.edu/software/apriltag + */ +typedef enum aivision_tag_family_e { + TAG_CIRCLE_21H7 = 0, + TAG_16H5 = 1, + TAG_25H9 = 2, + TAG_61H11 = 3 +} aivision_tag_family_e_t; + +/** + * \struct aivision_object_color_s_t + * This structure contains a detected color. + */ +typedef struct __attribute__((packed)) aivision_object_color_s { + uint16_t xoffset; // left edge (from camera's view) + uint16_t yoffset; // top edge + uint16_t width; + uint16_t height; + uint16_t angle; // angle, in tenths of a degree +} aivision_object_color_s_t; + +/** + * \struct aivision_object_tag_s_t + * This structure contains a detected tag. + */ +typedef struct __attribute__((packed)) aivision_object_tag_s { + int16_t x0; + int16_t y0; + int16_t x1; + int16_t y1; + int16_t x2; + int16_t y2; + int16_t x3; + int16_t y3; +} aivision_object_tag_s_t; + +typedef struct __attribute__((packed)) aivision_object_element_s { + uint16_t xoffset; // left + uint16_t yoffset; // top + uint16_t width; + uint16_t height; + uint16_t score; // confidence that this struct is +} aivision_object_element_s_t; +/** + * \struct aivision_object_s_t + * This structure contains one of aivision_detected_type_e_t, stored in type + * + * If the object is a color, id stores the color's id + * If the object is an April Tag, id stores the tag's id + * If the object is an AI model element, id stores the element id as per + * https://api.vex.com/v5/home/cpp/AiVision/AiObjdesc.html + */ +typedef struct __attribute__((packed)) aivision_object_s { + uint8_t id; // object id + uint8_t type; // object type + union { + aivision_object_color_s_t color; + aivision_object_tag_s_t tag; + aivision_object_element_s_t element; + } object; +} aivision_object_s_t; +/// @} + +#ifdef __cplusplus +namespace c { +#endif + +/** + * \addtogroup c-aivision + * @{ + */ +/// \name Functions + +/** + * Resets the AI Vision sensor to the initial state. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * aivision_reset(AIVISION_PORT); + * } + * \endcode + */ +int32_t aivision_reset(uint8_t port); + +/** + * Returns a bitfield of the types of objects the AI vision sensor is currently searching for, + * as per aivision_mode_type_e_t. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \return the bitfield if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * aivision_get_enabled_detection_types(AIVISION_PORT); + * } + * \endcode + */ +int32_t aivision_get_enabled_detection_types(uint8_t port); + +/** + * Modifies the types of objects the AI vision sensor is currently searching for, as per aivision_mode_type_e_t. + * + * 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 a vision sensor + * + * \b Example + * aivision_set_enabled_detection_types(1, 0b010, 0b101) would disable the detection of tags and objects, + * and leave the setting of colors alone. + * + * \param port The V5 port number from 1-21 + * \param bits the bits to set + * \param bitmask the bitmask to apply + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t aivision_set_enabled_detection_types(uint8_t port, uint8_t bits, uint8_t bitmask); + +/** + * Enable detecting these types of objects, a bitmask as per aivision_mode_type_e_t. + * Enabling any given type of object will not disable the detection of other objects. + * This must be done explicitly. + * + * 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 a vision sensor + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * // start or continue looking for AI model objects + * aivision_enable_detection_types(AIVISION_PORT, aivision_mode_type_e_t::E_AIVISION_MODE_OBJECTS); + * } + * \endcode + * + * \param port The V5 port number from 1-21 + * \param types_mask The types to enable + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t aivision_enable_detection_types(uint8_t port, uint8_t types_mask); + +/** + * Disable detecting these types of objects, a bitmask as per aivision_mode_type_e_t. + * Disabling any given type of object will not affect the detection of other objects. + * + * 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 a vision sensor + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * // stop looking for AI model objects (competition elements, for example) + * aivision_disable_detection_types(AIVISION_PORT, aivision_mode_type_e_t::E_AIVISION_MODE_OBJECTS); + * } + * \endcode + * + * \param port The V5 port number from 1-21 + * \param types_mask The types to enable + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t aivision_disable_detection_types(uint8_t port, uint8_t types_mask); + +/** + * Sets the april tag family to detect. Use this function will override the enabled apriltag + * detection family. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param family the tag family to configure the AI Vision sensor to detect + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t aivision_set_tag_family_override(uint8_t port, aivision_tag_family_e_t family); + +/** + * Sets the april tag family to detect. Use this function will allow multiple apriltags + * to be detected. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param family the tag family to configure the AI Vision sensor to detect + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ +int32_t aivision_set_tag_family(uint8_t port, aivision_tag_family_e_t family); + +/** + * Set a color configuration that the AI vision sensor will detect. + * The color detection type must be separately enabled. + * If a color with the same ID already is stored in the sensor, it will be overwritten. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param color the color to configure the AI Vision sensor to detect + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ +int32_t aivision_set_color(uint8_t port, const aivision_color_s_t* color); + +/** + * Get a color configuration that the AI vision sensor has stored. + * If you attempt to get a color configuration that has not been previously used, the + * behavior is not defined. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param id the id of color from 1-7 + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ +aivision_color_s_t aivision_get_color(uint8_t port, uint32_t id); + +/** + * Get a class name that the AI vision sensor has stored. + * The AI Vision sensor may not correctly report classnames for the first several hundred milliseconds + * of being plugged in. + * By passing in -1 for the id, the function will return the number of class names the AI vision sensor reports. + * For other values of id, the function return value is undefined + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param id the id of the class name from 0-(AIVISION_MAX_CLASSNAME_COUNT - 1) + * \param class_name a string of length >=20 to store the classname. + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ +int32_t aivision_get_class_name(uint8_t port, int32_t id, uint8_t* class_name); + +/** + * Enable or disable the bounding box overlay the AI Vision sensor outputs on the USB port. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param enabled if the overlay is enabled or disabled + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ +int32_t aivision_set_usb_bounding_box_overlay(uint8_t port, bool enabled); + +/** + * Runs auto white balance to adjust to different lighting conditions. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ +int32_t aivision_start_awb(uint8_t port); + +/** + * Get a code that the AI vision sensor has stored. + * + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param id The id from 1-5 + * \return the code, or a struct with an invalid ID if the operation failed, setting errno + */ +aivision_code_s_t aivision_get_code(uint8_t port, uint32_t id); + +/** + * Set a code that the AI vision sensor will detect for. + * The id of the code is stored in the aivision_code_s_t struct. If there is already a code + * stored in the AI vision sensor with the id, this function will overwrite. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \param code The code to set + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ +int32_t aivision_set_code(uint8_t port, const aivision_code_s_t* wcode); + +/** + * Get the current number of objects detected by the AI vision sensor. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \return the number of objects if the operation was successful or PROS_ERR if the operation failed, setting errno + */ +int32_t aivision_get_object_count(uint8_t port); + +/** + * Get the detected object at a given object index; there are aivision_get_object_count objects and the index starts + * from 0. + * + * 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 a vision sensor + * + * @param port The V5 port number from 1-21 + * @param object_index the object index + * @return the detected object if the operation was successful or an invalid object type if the operation failed, + * setting errno + */ +aivision_object_s_t aivision_get_object(uint8_t port, uint32_t object_index); + +/** + * Get the current reported temperature of the AI Vision sensor in degrees Celsius. + * + * 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 a vision sensor + * + * \param port The V5 port number from 1-21 + * \return the temperature if the operation was successful or PROS_ERR_F if the operation failed, setting errno + */ +double aivision_get_temperature(uint8_t port); + +///@} + +#ifdef __cplusplus +} // namespace c +} // namespace pros +} +#endif + +#endif // _PROS_VISION_H_ \ No newline at end of file diff --git a/include/pros/ai_vision.hpp b/include/pros/ai_vision.hpp new file mode 100644 index 0000000..30863d5 --- /dev/null +++ b/include/pros/ai_vision.hpp @@ -0,0 +1,600 @@ +/** + * \file pros/aivision.hpp + * \ingroup cpp-aivision + * + * Contains prototypes for the VEX AI Vision Sensor-related functions in C++. + * + * This file should not be modified by users, since it gets replaced whenever + * a kernel upgrade occurs. + * + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. + * All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \defgroup cpp-aivision AI Vision Sensor C++ API + * \note Additional example code for this module can be found in its [Tutorial.](@ref aivision) + */ + +#ifndef _PROS_AIVISION_HPP_ +#define _PROS_AIVISION_HPP_ + +#include +#include +#include + +#include "pros/ai_vision.h" +#include "pros/device.hpp" + +namespace pros { +inline namespace v5 { + +/** + * \enum AivisionDetectType + * \ingroup cpp-aivision + * Enum class for describing detection type of objects detected by the AI Vision Sensor. + */ +enum class AivisionDetectType : uint8_t { + color = (1 << 0), /**< object was detected based on color descriptor */ + code = (1 << 1), /**< object was detected based on code descriptor */ + object = (1 << 2), /**< object was detected using AI model */ + tag = (1 << 3) /**< object was detected as an AprilTag */ +}; + +/** + * \enum AivisionModeType + * \ingroup cpp-aivision + * Enum class for enabling/disabling detection types of AI Vision Sensor. + */ +enum class AivisionModeType : uint8_t { + tags = (1 << 0), /**< AprilTag detection */ + colors = (1 << 1), /**< color and code detection */ + objects = (1 << 2), /**< AI model object detection */ + color_merge = (1 << 4), /**< merge adjacent color detections */ + all = (1 << 0) | (1 << 1) | (1 << 2), +}; + +/** + * \enum AivisionTagFamily + * \ingroup cpp-aivision + * Enum class for describing family of apriltags to detect. + */ +enum class AivisionTagFamily { tag_21H7 = 0, tag_16H5 = 1, tag_25H9 = 2, tag_61H11 = 3 }; + +/** + * \ingroup cpp-aivision + */ +class AIVision : public Device { + /** + * \addtogroup cpp-aivision + * @{ + */ + public: + + using Color = aivision_color_s_t; + using Code = aivision_code_s_t; + using Object = aivision_object_s_t; + + /** + * Create a AI Vision Sensor object on the given port. + * + * 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 AI vision sensor + * + * \param port + * The V5 port number from 1-21 + * + * \b Example + * \code + * void opcontrol() { + * pros::AIVision ai_sensor(2); // Creates a vision sensor on port two + * } + * \endcode + */ + explicit AIVision(const std::uint8_t port); + + AIVision(const Device& device) : AIVision(device.get_port()){}; + + /** + * Gets all vision sensors. + * + * \return A vector of AIVision sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector aivision_all = pros::AIVision::get_all_devices(); // All AI vision sensors that are + * connected + * } + * \endcode + */ + static std::vector get_all_devices(); + + /** + * Check if the dected type is the same as the given type. + * + * \return true if the type is the same, false otherwise + * + * \b Example + * \code + * void opcontrol() { + * pros::AIVision aivision(1); + * pros::AIVision::Object object = aivision.get_object(0); + * if (AIVision::is_type(AivisionDetectType::color, object)) { + * printf("is color\n"); + * } else if (AIVision::is_type(AivisionDetectType::object, object)) { + * printf("is object\n"); + * } else if (AIVision::is_type(AivisionDetectType::code, object)) { + * printf("is code\n"); + * } else if (AIVision::is_type(AivisionDetectType::tag, object)) { + * printf("is tag\n"); + * } else { + * printf("unknown\n"); + * } + * } + * \endcode + */ + static bool is_type(const Object& object, AivisionDetectType type); + + /** + * Resets the AI Vision sensor to the initial state. + * + * 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 a vision sensor + * + + * + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * aivision.reset(); + * } + * \endcode + */ + int32_t reset(); + + /** + * Returns a bitfield of the types of objects the AI vision sensor is currently searching for, + * as per AivisionModeType. + * + * 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 a vision sensor + * + + * \return the bitfield if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * int32_t enabled_types = aivision.get_enabled_detection_types(); + * printf("is tag: %d\n", enabled_types | AivisionModeType::tags); + * } + * \endcode + */ + int32_t get_enabled_detection_types(); + + /** + * Enable detecting these types of objects, a bitmask as per aivision_mode_type_e_t. + * Enabling any given type of object will not disable the detection of other objects. + * This must be done explicitly. + * + * For this function you must use bitwise or to combine the types you want to enable. + * + * 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 a vision sensor + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * // start or continue looking for AI model objects + * // enable aivision to look for tags and objects + * aivision.enable_detection_types(AivisionModeType::tags | AivisionModeType::objects); + * } + * \endcode + * + * \param types_mask The types to enable + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + int32_t enable_detection_types(AivisionModeType types_mask); + + /** + * Enable detecting these types of objects, a bitmask as per aivision_mode_type_e_t. + * Enabling any given type of object will not disable the detection of other objects. + * This must be done explicitly. + * + * For this function you can use comma separated values to combine the types you want to enable. + * + * 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 a vision sensor + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * // start or continue looking for AI model objects + * // enable aivision to look for tags and objects + * aivision.enable_detection_types(AivisionModeType::tags, AivisionModeType::objects); + * } + * \endcode + * + * \param types_mask The types to enable + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + template + requires((std::conjunction_v...>)) + int32_t enable_detection_types(Flags... flags) { + auto types_mask = (static_cast(flags) | ...); + return c::aivision_enable_detection_types(this->_port, static_cast(types_mask)); + } + + /** + * Disable detecting these types of objects, a bitmask as per aivision_mode_type_e_t. + * Disabling any given type of object will not affect the detection of other objects. + * + * For this function you must use bitwise or to combine the types you want to disable. + * + * 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 a vision sensor + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * // stop looking for AI model objects (competition elements, for example) + * // disable aivision to look for tags and objects + * aivision.disable_detection_types(AivisionModeType::tags | AivisionModeType::objects); + * } + * \endcode + * + * \param types_mask The types to enable + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + int32_t disable_detection_types(AivisionModeType types_mask); + + /** + * Disable detecting these types of objects, a bitmask as per aivision_mode_type_e_t. + * Disabling any given type of object will not affect the detection of other objects. + * + * For this function you can use comma separated values to combine the types you want to disable. + * + * 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 a vision sensor + * + * \b Example + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * // stop looking for AI model objects (competition elements, for example) + * // disable aivision to look for tags and objects + * aivision.disable_detection_types(AivisionModeType::tags | AivisionModeType::objects); + * } + * \endcode + * + * \param types_mask The types to enable + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + template + requires((std::conjunction_v...>)) + int32_t disable_detection_types(Flags... flags) { + auto types_mask = (static_cast(flags) | ...); + return c::aivision_disable_detection_types(this->_port, static_cast(types_mask)); + } + + /** + * Sets the april tag family to detect. + * If override is true, the AI vision sensor will only look for the given family. + * Otherwise, it will add the given tag to the list of enabled tags. + * + * 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 a vision sensor + * + * \code + * #define AIVISION_PORT 1 + * void initialize() { + * pros::AIVision aivision(AIVISION_PORT); + * // set the only tag family to look for to 21H7 + * aivision.set_tag_family(AivisionTagFamily::tag_21H7); + * // add 16H5 to the list of enabled tag families + * aivision.set_tag_family(AivisionTagFamily::tag_16H5); + * // set the only tag family to look for to 25H9 + * aivision.set_tag_family(AivisionTagFamily::tag_25H9, true); + * } + * \endcode + * + * \param family the tag family to configure the AI Vision sensor to detect + * \param override if true, the given family will be set as the only enabled tag family. + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + */ + int32_t set_tag_family(AivisionTagFamily family, bool override = false); + + /** + * Set a color configuration that the AI vision sensor will detect. + * The color detection type must be separately enabled. + * If a color with the same ID already is stored in the sensor, it will be overwritten. + * + * 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 a vision sensor + * + * \code + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * AIVision::Color color = {1, 207, 19, 25, 10.00, 0.20}; + * aivision.set_color(color); + * } + * \endcode + * + * \param color the color to configure the AI Vision sensor to detect + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ + int32_t set_color(const Color& color); + + /** + * Get a color configuration that the AI vision sensor has stored. + * If you attempt to get a color configuration that has not been previously used, the + * behavior is not defined. + * + * 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 a vision sensor + * + * + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * AIVision::Code color = aivision.get_color(0); + * printf("id: %d, red: %d, green: %d, blue: %d, hue_range: %f, saturation_range: %f\n", + * color.id, color.red, color.green, color.blue, color.hue_range, color.saturation_range); + * } + * + * \param id the id of color from 1-7 + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ + AIVision::Color get_color(uint32_t id); + + /** + * Set a code that the AI vision sensor will detect for. + * The id of the code is stored in the aivision_code_s_t struct. If there is already a code + * stored in the AI vision sensor with the id, this function will overwrite. + * + * 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 a vision sensor + * + * \code + * + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * AIVision::Code code = {1, 207, 19, 25, 10.00, 0.20}; + * aivision.set_code(code); + * } + * + * \endcode + * + * \param code The code to set + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ + uint32_t set_code(const Code& code); + + /** + * Get a code that the AI vision sensor has stored. + * + * + * 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 a vision sensor + * + * \code + * + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * AIVision::Code code = aivision.get_code(0); + * printf("id: %d, length: %d, c1: %d, c2: %d, c3: %d, c4: %d, c5: %d\n", + * code.id, code.length, code.c1, code.c2, code.c3, code.c4, code.c5); + * ) + * } + * + * \endcode + * + * \param id The id from 1-5 + * \return the code, or a struct with an invalid ID if the operation failed, setting errno + */ + AIVision::Code get_code(uint32_t id); + + /** + * Runs auto white balance to adjust to different lighting conditions. + * + * 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 a vision sensor + * + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ + int32_t start_awb(); + + /** + * Get a class name that the AI vision sensor has stored. + * The AI Vision sensor may not correctly report classnames for the first several hundred milliseconds + * of being plugged in. + * By passing in -1 for the id, the function will return the number of class names the AI vision sensor reports. + * For other values of id, the function return value is undefined + * + * 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 a vision sensor + * \code + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * char* class_name = new char[21]; + * aivision.get_class_name(0, class_name); + * printf("%s\n", class_name); + * delete[] class_name; + * } + * + * \endcode + * + * \param id the id of the class name from 0-(AIVISION_MAX_CLASSNAME_COUNT - 1) + * \param class_name a string of length >=20 to store the classname. + * \return PROS_SUCCESS if the operation was successful or PROS_ERR if the operation + * failed, setting errno + */ + int32_t get_class_name(int32_t id, char* class_name); + + /** + * Get a class name that the AI vision sensor has stored. + * The AI Vision sensor may not correctly report classnames for the first several hundred milliseconds + * of being plugged in. + * By passing in -1 for the id, the function will return the number of class names the AI vision sensor reports. + * For other values of id, the function return value is undefined + * + * 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 a vision sensor + * \code + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * auto name = aivision.get_class_name(1); + * + * if(name.has_value()) { + * printf("Class name: %s\n", name.value().c_str()); + * } else { + * printf("Error: %ld\n", errno); + * } + * } + * + * \endcode + * + * \param id the id of the class name from 0-(AIVISION_MAX_CLASSNAME_COUNT - 1) + * \return the class name string in std::optional if the operation was successful + * or an empty optional if the operation failed, setting errno + */ + std::optional get_class_name(int32_t id); + + /** + * Get the current number of objects detected by the AI vision sensor. + * + * 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 a vision sensor + * + * \code + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * int32_t object_count = aivision.get_object_count(); + * printf("%d\n", object_count); + * } + * \endcode + * + * \return the number of objects if the operation was successful or PROS_ERR if the operation failed, setting errno + */ + int32_t get_object_count(); + + /** + * Get the detected object at a given object index; there are aivision_get_object_count objects and the index starts + * from 0. + * + * 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 a vision sensor + * + * \code + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * int32_t object_count = aivision.get_object_count(); + * for (int i = 0; i < object_count; i++) { + * pros::AIVision::Object object = aivision.get_object(i); + * printf("Object %d: %d\n", i, object.type); + * } + * } + * + * \endcode + * + * @param object_index the object index + * @return the detected object if the operation was successful or an invalid object type if the operation failed, + * setting errno + */ + Object get_object(uint32_t object_index); + + /** + * Get all detected objects in a vector. + * + * 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 a vision sensor + * + * \code + * #define AIVISION_PORT 1 + * void opcontrol() { + * pros::AIVision aivision(AIVISION_PORT); + * auto objects = aivision.get_all_objects(); + * for (const auto& object : objects) { + * printf("Object %d: %d\n", object.id, object.type); + * } + * } + * \endcode + * + * @return a vector of all detected objects + */ + std::vector get_all_objects(); + /// @} +}; +} // namespace v5 +} // namespace pros +#endif // _PROS_VISION_HPP_ diff --git a/include/pros/api_legacy.h b/include/pros/api_legacy.h deleted file mode 100644 index 3295ade..0000000 --- a/include/pros/api_legacy.h +++ /dev/null @@ -1,147 +0,0 @@ -/** - * \file pros/api_legacy.h - * \ingroup api-legacy - * - * PROS 2 Legacy API header - * - * Contains declarations for functions that are name-compatible with the PROS 2 - * API. Some functions from the PROS 2 API are not useful or cannot be - * implemented in PROS 3, but most common functions are available. - * - * This file should not be modified by users, since it gets replaced whenever - * a kernel upgrade occurs. - * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. - * All rights reserved. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * \defgroup api-legacy Legacy API - * \note Using this functionality requires including "pros/api_legacy.h" in addition to "api.h". - */ - -#ifndef _PROS_API_LEGACY_H_ -#define _PROS_API_LEGACY_H_ - -#include "api.h" - -#ifdef __cplusplus -#define _NAMESPACE pros:: -#define _CNAMESPACE pros::c:: -#else -#define _NAMESPACE -#define _CNAMESPACE -#endif - -/** - * \ingroup api-legacy - */ - -/** - * \addtogroup api-legacy - * @{ - */ - -/// \name ADI Functions -///@{ -/** - * From adi.h - */ -#define analogCalibrate(port) adi_analog_calibrate(port) -#define analogRead(port) adi_analog_read(port) -#define analogReadCalibrated(port) adi_analog_read_calibrated(port) -#define analogReadCalibratedHR(port) adi_analog_read_calibrated_HR(port) -#define digitalRead(port) adi_digital_read(port) -#define digitalWrite(port, value) adi_digital_write(port, value) -#define pinMode(port, mode) adi_pin_mode(port, mode) -#define adiMotorSet(port, speed) adi_motor_set(port, speed) -#define adiMotorGet(port) adi_motor_get(port) -#define adiMotorStop(port) adi_motor_stop(port) -#define encoderGet(enc) adi_encoder_get(enc) -#define encoderInit(portTop, portBottom, reverse) adi_encoder_init(portTop, portBottom, reverse) -#define encoderShutdown(enc) adi_encoder_shutdown(enc) -#define ultrasonicGet(ult) adi_ultrasonic_get(ult) -#define ultrasonicInit(portEcho, portPing) adi_ultrasonic_init(portEcho, portPing) -#define ultrasonicShutdown(ult) adi_ultrasonic_shutdown(ult) - -///@} - -/// \name Typedefs -///@{ - -typedef _CNAMESPACE adi_encoder_t Encoder; -typedef _CNAMESPACE adi_ultrasonic_t Ultrasonic; - -///@} - -/// \name LCD Functions -///@{ -/** - * From llemu.h - */ -#define lcdInit lcd_initialize -#define lcdReadButtons lcd_read_buttons -#define lcdClear lcd_clear -#define lcdClearLine lcd_clear_line -#define lcdShutdown lcd_shutdown -#define lcdPrint(line, fmt, ...) lcd_print(line, fmt, __VA_ARGS__) -#define lcdSetText(line, text) lcd_set_text(line, text) - -///@} - -/// \name Miscallaneous Functions -///@{ -/** - * From misc.h - */ -#define isEnabled() (!competition_is_disabled()) -#define isAutonomous competition_is_autonomous -#define isOnline competition_is_connected -#define isJoystickConnected(id) controller_is_connected(id) -#define joystickGetAnalog(id, channel) controller_get_analog(id, channel) -///@} - -/// \name RTOS Functions -///@{ -/** - * From rtos.h - */ -#define taskCreate(taskCode, stackDepth, parameters, priority) \ - task_create(taskCode, parameters, priority, stackDepth, "") -#define taskDelete(task) task_delete(task) -#define taskDelay task_delay -#define taskDelayUntil(previousWakeTime, cycleTime) task_delay_until(previousWakeTime, cycleTime) -#define taskPriorityGet(task) task_get_priority(task) -#define taskPrioritySet(task, newPriority) task_priority_set(task, newPriority) -#define taskGetState(task) task_get_state(task) -#define taskSuspend(task) task_suspend(task) -#define taskResume(task) task_resume(task) -#define taskGetCount task_get_count -#define mutexCreate mutex_create -#define mutexTake(mutex, blockTime) mutex_take(mutex, blockTime) -#define mutexGive(mutex) mutex_give(mutex) - -typedef _NAMESPACE task_t TaskHandle; -typedef _NAMESPACE mutex_t Mutex; - -///@} - -/// \name Motor Functions -///@{ -/** - * From motors.h - */ -#define motorSet(port, speed) motor_move(port, speed) -#define motorGet(port) motor_get_voltage(port) -#define motorStop(port) motor_move(port, 0) - -///@} - -///@} - -#undef _NAMESPACE -#undef _CNAMESPACE - -#endif // _PROS_API_LEGACY_H_ diff --git a/include/pros/apix.h b/include/pros/apix.h index fe3fc17..dc6c5b0 100644 --- a/include/pros/apix.h +++ b/include/pros/apix.h @@ -8,12 +8,10 @@ * functions do not typically have as much error handling or require deeper * knowledge of real time operating systems. * - * Visit https://pros.cs.purdue.edu/v5/extended/api.html to learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public @@ -50,7 +48,6 @@ extern "C" { */ /// \name RTOS Facilities -/// See https://pros.cs.purdue.edu/v5/extended/multitasking.html to learn more ///@{ typedef void* queue_t; @@ -60,19 +57,25 @@ typedef void* sem_t; * Unblocks a task in the Blocked state (e.g. waiting for a delay, on a * semaphore, etc.). * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#abort_delay for - * details. + * \param task + * The task to unblock + * + * \return True if the task was unblocked, false otherwise + * + * \b Example: + * \code + * task_t task = task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * task_delay(1000); + * // in another task somewhere else, this will abort the task_delay bove: + * task_abort_delay(task); + * \endcode */ bool task_abort_delay(task_t task); /** * Notify a task when a target task is being deleted. * - * This function will configure the PROS kernel to call - * task_notify_ext(task_to_notify, value, action, NULL) when target_task is - * deleted. - * - * * \param target_task * The task being watched for deletion * \param task_to_notify @@ -81,71 +84,67 @@ bool task_abort_delay(task_t task); * The value to supply to task_notify_ext * \param notify_action * The action to supply to task_notify_ext + * + * \b Example: + * \code + * task_t task_to_delete = task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * task_t task_to_notify = task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn2"); + * + * task_notify_ext(task_to_notify, 0, NOTIFY_ACTION_INCREMENT, NULL); + * + * task_notify_when_deleting(task_to_delete, task_get_current(), 0, NOTIFY_ACTION_NONE); + * task_delete(task_to_delete); + * \endcode */ void task_notify_when_deleting(task_t target_task, task_t task_to_notify, uint32_t value, notify_action_e_t notify_action); -/** - * Creates a recursive mutex which can be locked recursively by the owner. - * - * See - * https://pros.cs.purdue.edu/v5/extended/multitasking.html#recursive_mutexes - * for details. - * - * \return A newly created recursive mutex. - */ -mutex_t mutex_recursive_create(void); - -/** - * Takes a recursive mutex. - * - * See - * https://pros.cs.purdue.edu/v5/extended/multitasking.html#recursive_mutexes - * for details. - * - * \param mutex - * A mutex handle created by mutex_recursive_create - * \param wait_time - * Amount of time to wait before timing out - * - * \return 1 if the mutex was obtained, 0 otherwise - */ -bool mutex_recursive_take(mutex_t mutex, uint32_t timeout); - -/** - * Gives a recursive mutex. - * - * See - * https://pros.cs.purdue.edu/v5/extended/multitasking.html#recursive_mutexes - * for details. - * - * \param mutex - * A mutex handle created by mutex_recursive_create - * - * \return 1 if the mutex was obtained, 0 otherwise - */ -bool mutex_recursive_give(mutex_t mutex); - /** * Returns a handle to the current owner of a mutex. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#extra for - * details. - * * \param mutex * A mutex handle * * \return A handle to the current task that owns the mutex, or NULL if the * mutex isn't owned. + * + * \b Example: + * \code + * mutex_t mutex = mutex_create(); + * + * void task_fn(void* param) { + * while(1) { + * mutex_take(mutex, 1000); + * // critical section + * mutex_give(mutex); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * void opcontrol(void) { +* while (1) { +* if (joystick_get_digital(1, 7, JOY_UP)) { +* task_t owner = mutex_get_owner(mutex); +* if (owner != NULL) { +* printf("Mutex is owned by task %s", task_get_name(owner)); +* } else { +* printf("Mutex is not owned"); +* } +* } +* task_delay(20); +* } +* } + * \endcode */ task_t mutex_get_owner(mutex_t mutex); /** * Creates a counting sempahore. * - * See https://pros.cs.purdue.edu/v5/tutorials/multitasking.html#semaphores for - *details. - * * \param max_count * The maximum count value that can be reached. * \param init_count @@ -153,28 +152,86 @@ task_t mutex_get_owner(mutex_t mutex); * * \return A newly created semaphore. If an error occurred, NULL will be * returned and errno can be checked for hints as to why sem_create failed. + * + * \b Example: + * \code + * // Binary semaphore acts as a mutex + * sem_t sem = sem_create(1, 0); + * + * void task_fn(void* param) { + * while(1) { + * sem_take(sem, 1000); + * // critical section + * sem_give(sem); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * \endcode */ sem_t sem_create(uint32_t max_count, uint32_t init_count); /** * Deletes a semaphore (or binary semaphore) * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#semaphores for - * details. - * * \param sem * Semaphore to delete + * + * \b Example: + * \code + * // Binary semaphore acts as a mutex + * sem_t sem = sem_create(1, 0); + * + * void task_fn(void* param) { + * while(1) { + * sem_take(sem, 1000); + * // critical section + * sem_give(sem); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * void opcontrol(void) { + * while (1) { + * if (joystick_get_digital(1, 7, JOY_UP)) { + * // honestly this is a bad example because you should never + * // delete a semaphore like this + * sem_delete(sem); + * } + * task_delay(20); + * } + * } + * + * \endcode */ void sem_delete(sem_t sem); /** * Creates a binary semaphore. * - * See - * https://pros.cs.purdue.edu/v5/extended/multitasking#.htmlbinary_semaphores - * for details. - * * \return A newly created semaphore. + * + * \b Example: + * \code + * // Binary semaphore acts as a mutex + * sem_t sem = sem_binary_create(); + * + * void task_fn(void* param) { + * while(1) { + * sem_take(sem, 1000); + * // critical section + * sem_give(sem); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * \endcode */ sem_t sem_binary_create(void); @@ -182,9 +239,6 @@ sem_t sem_binary_create(void); * Waits for the semaphore's value to be greater than 0. If the value is already * greater than 0, this function immediately returns. * - * See https://pros.cs.purdue.edu/v5/tutorials/multitasking.html#semaphores for - * details. - * * \param sem * Semaphore to wait on * \param timeout @@ -195,44 +249,98 @@ sem_t sem_binary_create(void); * \return True if the semaphore was successfully take, false otherwise. If * false is returned, then errno is set with a hint about why the sempahore * couldn't be taken. + * + * \b Example: + * \code + * // Binary semaphore acts as a mutex + * sem_t sem = sem_create(1, 0); + * + * void task_fn(void* param) { + * while(1) { + * if(!sem_wait(sem, 1000)) { + * printf("Failed to take semaphore"); + * task_delay(1000); + * continue; + * } + * // critical section + * sem_give(sem); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * void opcontrol(void) { + * while (1) { + * if (sem_wait(sem, 0))) { + * printf("Semaphore is available"); + * } + * task_delay(20); + * } + * } + * \endcode */ bool sem_wait(sem_t sem, uint32_t timeout); /** * Increments a semaphore's value. * - * See https://pros.cs.purdue.edu/v5/tutorials/multitasking.html#semaphores for - * details. - * * \param sem * Semaphore to post * * \return True if the value was incremented, false otherwise. If false is * returned, then errno is set with a hint about why the semaphore couldn't be * taken. + * + * \b Example: + * \code + * // Binary semaphore acts as a mutex + * sem_t sem = sem_create(1, 0); + * + * void task_fn(void* param) { + * while(1) { + * sem_post(sem); // increments, mimicking to "claim" + * // critical section + * sem_give(sem); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * \endcode */ bool sem_post(sem_t sem); /** * Returns the current value of the semaphore. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#extra for - * details. - * * \param sem * A semaphore handle * * \return The current value of the semaphore (e.g. the number of resources * available) + * + * \b Example of sem_get_count: + * \code + * // Binary semaphore acts as a mutex + * sem_t sem = sem_create(1, 0); + * printf("semaphore count: %d", sem_get_count(sem)); + * // semaphore count: 0 + * sem_take(sem, 1000); + * printf("semaphore count: %d", sem_get_count(sem)); + * // semaphore count: 1 + * sem_give(sem); + * printf("semaphore count: %d", sem_get_count(sem)); + * // semaphore count: 0 + * + * \endcode */ uint32_t sem_get_count(sem_t sem); /** * Creates a queue. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param length * The maximum number of items that the queue can contain. * \param item_size @@ -240,6 +348,17 @@ uint32_t sem_get_count(sem_t sem); * * \return A handle to a newly created queue, or NULL if the queue cannot be * created. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * int item[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * printf("queue length: %d", queue_get_length(queue)); + * } + * \endcode */ queue_t queue_create(uint32_t length, uint32_t item_size); @@ -247,9 +366,6 @@ queue_t queue_create(uint32_t length, uint32_t item_size); * Posts an item to the front of a queue. The item is queued by copy, not by * reference. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * The queue handle * \param item @@ -260,6 +376,16 @@ queue_t queue_create(uint32_t length, uint32_t item_size); * indefinitely. * * \return True if the item was preprended, false otherwise. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * int item[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * printf("queue length: %d", queue_get_length(queue)); + * } */ bool queue_prepend(queue_t queue, const void* item, uint32_t timeout); @@ -267,9 +393,6 @@ bool queue_prepend(queue_t queue, const void* item, uint32_t timeout); * Posts an item to the end of a queue. The item is queued by copy, not by * reference. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * The queue handle * \param item @@ -280,15 +403,23 @@ bool queue_prepend(queue_t queue, const void* item, uint32_t timeout); * indefinitely. * * \return True if the item was preprended, false otherwise. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * int item[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * printf("queue length: %d", queue_get_length(queue)); + * } + * \endcode */ bool queue_append(queue_t queue, const void* item, uint32_t timeout); /** * Receive an item from a queue without removing the item from the queue. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * The queue handle * \param buffer @@ -298,15 +429,26 @@ bool queue_append(queue_t queue, const void* item, uint32_t timeout); * the time of the call. TIMEOUT_MAX can be used to block indefinitely. * * \return True if an item was copied into the buffer, false otherwise. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * char* item = "Hello! this is a test"; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * char* recv = malloc(sizeof("Hello! this is a test")); + * queue_peek(queue, recv, 1000); + * printf("Queue: %s", recv); + * free(recv); + * } + * \endcode */ bool queue_peek(queue_t queue, void* const buffer, uint32_t timeout); /** * Receive an item from the queue. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * The queue handle * \param buffer @@ -318,43 +460,80 @@ bool queue_peek(queue_t queue, void* const buffer, uint32_t timeout); * is zero and the queue is empty. * * \return True if an item was copied into the buffer, false otherwise. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * char* item = "Hello! this is a test"; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * char* recv = malloc(sizeof("Hello! this is a test")); + * queue_recv(queue, recv, 1000); + * printf("Queue: %s", recv); + * free(recv); + * } + * \endcode */ bool queue_recv(queue_t queue, void* const buffer, uint32_t timeout); /** * Return the number of messages stored in a queue. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * The queue handle. * * \return The number of messages available in the queue. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * + * int item[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * printf("queue waiting: %d", queue_get_waiting(queue)); + * } + * \endcode */ uint32_t queue_get_waiting(const queue_t queue); /** * Return the number of spaces left in a queue. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * The queue handle. * * \return The number of spaces available in the queue. + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * + * int item[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * printf("queue available: %d", queue_get_available(queue)); + * } + * \endcode */ uint32_t queue_get_available(const queue_t queue); /** * Delete a queue. * - * See https://pros.cs.purdue.edu/v5/extended/multitasking.html#queues for - * details. - * * \param queue * Queue handle to delete + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * queue_delete(queue); + * } + * \endcode */ void queue_delete(queue_t queue); @@ -363,6 +542,17 @@ void queue_delete(queue_t queue); * * \param queue * Queue handle to reset + * + * \b Example: + * \code + * void opcontrol(void) { + * queue_t queue = queue_create(10, sizeof(int)); + * int item[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + * queue_prepend(queue, item, 1000); + * queue_append(queue, item, 1000); + * queue_reset(queue); + * } + * \endcode */ void queue_reset(queue_t queue); @@ -389,6 +579,13 @@ void queue_reset(queue_t queue); * The type of device to register * * \return 1 upon success, PROS_ERR upon failure + * + * \b Example: + * \code + * void opcontrol(void) { + * registry_bind_port(1, E_DEVICE_MOTOR); + * } + * \endcode */ int registry_bind_port(uint8_t port, v5_device_e_t device_type); @@ -405,6 +602,14 @@ int registry_bind_port(uint8_t port, v5_device_e_t device_type); * The port number to deregister * * \return 1 upon success, PROS_ERR upon failure + * + * \b Example: + * \code + * void opcontrol(void) { + * registry_bind_port(1, E_DEVICE_MOTOR); + * registry_unbind_port(1); + * } + * \endcode */ int registry_unbind_port(uint8_t port); @@ -420,6 +625,14 @@ int registry_unbind_port(uint8_t port); * * \return The type of device that is registered into the port (NOT what is * plugged in) + * + * \b Example: + * \code + * void opcontrol(void) { + * registry_bind_port(1, E_DEVICE_MOTOR); + * printf("port 1 is registered to a motor: %d", registry_get_bound_type(1) == E_DEVICE_MOTOR); + * } + * \endcode */ v5_device_e_t registry_get_bound_type(uint8_t port); @@ -435,11 +648,61 @@ v5_device_e_t registry_get_bound_type(uint8_t port); * * \return The type of device that is plugged into the port (NOT what is * registered) + * + * \b Example: + * \code + * void opcontrol(void) { + * registry_bind_port(1, E_DEVICE_MOTOR); + * printf("port 1 is registered to a motor: %d", registry_get_plugged_type(1) == E_DEVICE_MOTOR); + * } + * \endcode */ v5_device_e_t registry_get_plugged_type(uint8_t port); ///@} +/// \name Startup options +///@{ + +/** + * Enable/disable the PROS banner printed to the serial stream. + * + * \warning This function must be called BEFORE the PROS daemon starts. + * The easiest way to acheive this is to NOT call this function directly, + * and instead use the BANNER_ENABLE macro. + * + * \param enable + * Whether the banner should be enabled or disabled. + */ +void enable_banner(bool enabled); + +/** + * This priority value, when used with __attribute__((constructor( ))), is + * guaranteed to run before PROS initializes. + */ +#define PRE_PROS_INIT_PRIORITY 101 + +/** + * Enable/disable the PROS banner printed to the serial stream. + * + * \warning This macro must be used in global scope, outside of any function. + * + * \param enable + * Whether the banner should be enabled or disabled. + */ +#ifdef __cplusplus +#define ENABLE_BANNER(enabled) static_assert(!__builtin_strcmp(__FUNCTION__, "top level"), \ + "Cannot use ENABLE_BANNER inside a function!"); \ + __attribute__((constructor(PRE_PROS_INIT_PRIORITY))) static void _enable_banner_impl() \ + { pros::c::enable_banner(enabled); } +#else +#define ENABLE_BANNER(enabled) static_assert(!__builtin_strcmp(__FUNCTION__, "top level"), \ + "Cannot use ENABLE_BANNER inside a function!"); \ + __attribute__((constructor(PRE_PROS_INIT_PRIORITY))) static void _enable_banner_impl() \ + { enable_banner(enabled); } +#endif +///@} + /// \name Filesystem ///@{ @@ -451,10 +714,16 @@ v5_device_e_t registry_get_plugged_type(uint8_t port); * details on the different actions. * \param extra_arg * An argument to pass in based on the action + * + * \b Example: + * \code + * void opcontrol(void) { + * serctl(SERCTL_SET_BAUDRATE, (void*) 9600); + * } */ int32_t serctl(const uint32_t action, void* const extra_arg); -/** +/* * Control settings of the microSD card driver. * * \param action @@ -478,6 +747,14 @@ int32_t serctl(const uint32_t action, void* const extra_arg); * microSD card file) * \param extra_arg * An argument to pass in based on the action + * + * \b Example: + * \code + * void opcontrol(void) { + * int32_t fd = open("serial", O_RDWR); + * fdctl(fd, SERCTL_SET_BAUDRATE, (void*) 9600); + * } + * \endcode */ int32_t fdctl(int file, const uint32_t action, void* const extra_arg); @@ -540,8 +817,6 @@ int32_t motor_is_reversed(int8_t port); * When used with serctl, the extra argument must be the little endian * representation of the stream identifier (e.g. "sout" -> 0x74756f73) * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial - * to learn more. */ #define SERCTL_ACTIVATE 10 @@ -552,8 +827,6 @@ int32_t motor_is_reversed(int8_t port); * When used with serctl, the extra argument must be the little endian * representation of the stream identifier (e.g. "sout" -> 0x74756f73) * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial - * to learn more. */ #define SERCTL_DEACTIVATE 11 @@ -563,8 +836,6 @@ int32_t motor_is_reversed(int8_t port); * The extra argument is not used with this action, provide any value (e.g. * NULL) instead * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial - * to learn more. */ #define SERCTL_BLKWRITE 12 @@ -574,8 +845,6 @@ int32_t motor_is_reversed(int8_t port); * The extra argument is not used with this action, provide any value (e.g. * NULL) instead * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial - * to learn more. */ #define SERCTL_NOBLKWRITE 13 @@ -586,8 +855,6 @@ int32_t motor_is_reversed(int8_t port); * The extra argument is not used with this action, provide any value (e.g. * NULL) instead * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial - * to learn more. */ #define SERCTL_ENABLE_COBS 14 @@ -598,8 +865,6 @@ int32_t motor_is_reversed(int8_t port); * The extra argument is not used with this action, provide any value (e.g. * NULL) instead * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/filesystem.html#serial - * to learn more. */ #define SERCTL_DISABLE_COBS 15 @@ -607,8 +872,6 @@ int32_t motor_is_reversed(int8_t port); * Action macro to check if there is data available from the Generic Serial * Device * - * The extra argument is not used with this action, provide any value (e.g. - * NULL) instead */ #define DEVCTL_FIONREAD 16 @@ -616,8 +879,6 @@ int32_t motor_is_reversed(int8_t port); * Action macro to check if there is space available in the Generic Serial * Device's output buffer * - * The extra argument is not used with this action, provide any value (e.g. - * NULL) instead */ #define DEVCTL_FIONWRITE 18 diff --git a/include/pros/colors.h b/include/pros/colors.h index 638cd34..431d9d8 100644 --- a/include/pros/colors.h +++ b/include/pros/colors.h @@ -6,11 +6,23 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * Copyright (c) 2017-2020 Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License v. 2.0. If a copy of the MPL was not distributed with this * file You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \defgroup c-colors Colors C API + */ + +/** + * \ingroup c-colors + * \note These functions can be used for dynamic device instantiation. + */ + +/** + * \addtogroup c-colors + * @{ */ #ifndef _PROS_COLORS_H_ @@ -25,6 +37,14 @@ namespace pros { namespace c { #endif + +/** + * \enum color_e_t + * @brief + * Enum of possible colors + * + * Contains common colors, all members are self descriptive. + */ typedef enum color_e { COLOR_ALICE_BLUE = 0x00F0F8FF, COLOR_ANTIQUE_WHITE = 0x00FAEBD7, @@ -174,6 +194,8 @@ typedef enum color_e { COLOR_YELLOW_GREEN = 0x009ACD32, } color_e_t; + ///@} + #ifdef __cplusplus } // namespace c } // namespace pros diff --git a/include/pros/colors.hpp b/include/pros/colors.hpp index e3d0ba1..c19ec6e 100644 --- a/include/pros/colors.hpp +++ b/include/pros/colors.hpp @@ -6,17 +6,35 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * Copyright (c) 2017-2022 Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License v. 2.0. If a copy of the MPL was not distributed with this * file You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \defgroup cpp-colors C++ Color API */ #ifndef _PROS_COLORS_HPP_ #define _PROS_COLORS_HPP_ namespace pros{ +/** + * \ingroup cpp-colors + */ + +/** + * \addtogroup cpp-colors + * @{ + */ + +/** + * \enum Color + * @brief + * Enum class of possible colors + * + * Contains common colors, all members are self descriptive. + */ enum class Color { alice_blue = 0x00F0F8FF, antique_white = 0x00FAEBD7, @@ -167,4 +185,6 @@ enum class Color { }; } // namespace pros + ///@} + #endif //_PROS_COLORS_HPP_ diff --git a/include/pros/device.h b/include/pros/device.h index 572b982..c6fb5bf 100644 --- a/include/pros/device.h +++ b/include/pros/device.h @@ -8,11 +8,13 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2021, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \defgroup c-device VEX Generic Device C API (For Advanced Users) */ #ifndef _PROS_DEVICE_H_ @@ -25,35 +27,63 @@ namespace pros::c { extern "C" { #endif -/* +/** + * \ingroup c-device + * \note These functions can be used for dynamic device instantiation. + */ + +/** + * \addtogroup c-device + * @{ + */ + +/** + * \enum v5_device_e + * \brief * List of possible v5 devices * * This list contains all current V5 Devices, and mirrors V5_DeviceType from the * api. */ typedef enum v5_device_e { - E_DEVICE_NONE = 0, - E_DEVICE_MOTOR = 2, - E_DEVICE_ROTATION = 4, - E_DEVICE_IMU = 6, - E_DEVICE_DISTANCE = 7, - E_DEVICE_RADIO = 8, - E_DEVICE_VISION = 11, - E_DEVICE_ADI = 12, - E_DEVICE_OPTICAL = 16, - E_DEVICE_GPS = 20, - E_DEVICE_SERIAL = 129, + E_DEVICE_NONE = 0, ///< No device is plugged into the port + E_DEVICE_MOTOR = 2, ///< A motor is plugged into the port + E_DEVICE_ROTATION = 4, ///< A rotation sensor is plugged into the port + E_DEVICE_IMU = 6, ///< An inertial sensor is plugged into the port + E_DEVICE_DISTANCE = 7, ///< A distance sensor is plugged into the port + E_DEVICE_RADIO = 8, ///< A radio is plugged into the port + E_DEVICE_VISION = 11, ///< A vision sensor is plugged into the port + E_DEVICE_ADI = 12, ///< This port is an ADI expander + E_DEVICE_OPTICAL = 16, ///< An optical sensor is plugged into the port + E_DEVICE_GPS = 20, ///< A GPS sensor is plugged into the port + E_DEVICE_AIVISION = 29, ///< An AI Vision sensor is plugged into the port + E_DEVICE_SERIAL = 129, ///< A serial device is plugged into the port E_DEVICE_GENERIC __attribute__((deprecated("use E_DEVICE_SERIAL instead"))) = E_DEVICE_SERIAL, - E_DEVICE_UNDEFINED = 255 + E_DEVICE_UNDEFINED = 255 ///< The device type is not defined, or is not a valid device } v5_device_e_t; /** * Gets the type of device on given port. * * \return The device type as an enum. + * + * \b Example + * \code + * #define DEVICE_PORT 1 + * + * void opcontrol() { + * while (true) { + * v5_device_e_t pt = get_plugged_type(DEVICE_PORT); + * printf("device plugged type: {plugged type: %d}\n", pt); + * delay(20); + * } + * } + * \endcode */ v5_device_e_t get_plugged_type(uint8_t port); +///@} + #ifdef __cplusplus } // namespace c } // namespace pros diff --git a/include/pros/device.hpp b/include/pros/device.hpp index 7faf6a7..560e03f 100644 --- a/include/pros/device.hpp +++ b/include/pros/device.hpp @@ -6,11 +6,13 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2021, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \defgroup cpp-device VEX Generic Device C++ API (For Advanced Users) */ #ifndef _PROS_DEVICE_HPP_ @@ -21,25 +23,37 @@ namespace pros { inline namespace v5 { +/** + * \ingroup cpp-device + * \note These functions can be used for dynamic device instantiation. + */ -/* +/** + * \addtogroup cpp-device + * @{ + */ + +/** + * \enum DeviceType + * \brief * Enum of possible v5 devices. * * Contains all current V5 Devices. */ enum class DeviceType { - none = 0, - motor = 2, - rotation = 4, - imu = 6, - distance = 7, - radio = 8, - vision = 11, - adi = 12, - optical = 16, - gps = 20, - serial = 129, - undefined = 255 + none = 0, ///< No device is plugged into the port + motor = 2, ///< A motor is plugged into the port + rotation = 4, ///< A rotation sensor is plugged into the port + imu = 6, ///< An inertial sensor is plugged into the port + distance = 7, ///< A distance sensor is plugged into the port + radio = 8, ///< A radio is plugged into the port + vision = 11, ///< A vision sensor is plugged into the port + adi = 12, ///< This port is an ADI expander + optical = 16, ///< An optical sensor is plugged into the port + gps = 20, ///< A GPS sensor is plugged into the port + aivision = 29, ///< An AI vision sensor is plugged into the port + serial = 129, ///< A serial device is plugged into the port + undefined = 255 ///< The device type is not defined, or is not a valid device }; class Device { @@ -48,6 +62,15 @@ class Device { * Creates a Device object. * * \param port The V5 port number from 1-21 + * + * \b Example + * \code + * #define DEVICE_PORT 1 + * + * void opcontrol() { + * Device device(DEVICE_PORT); + * } + * \endcode */ explicit Device(const std::uint8_t port); @@ -55,13 +78,38 @@ class Device { * Gets the port number of the Smart Device. * * \return The smart device's port number. + * + * \b Example + * \code + * void opcontrol() { + * #define DEVICE_PORT 1 + * while (true) { + * Device device(DEVICE_PORT); + * printf("device plugged type: {port: %d}\n", device.get_port()); + * delay(20); + * } + * } + * \endcode */ - std::uint8_t get_port(void); + std::uint8_t get_port(void) const; /** * Checks if the device is installed. * * \return true if the corresponding device is installed, false otherwise. + * \b Example + * + * \code + * #define DEVICE_PORT 1 + * + * void opcontrol() { + * Device device(DEVICE_PORT); + * while (true) { + * printf("device plugged type: {is_installed: %d}\n", device.is_installed()); + * delay(20); + * } + * } + * \endcode */ virtual bool is_installed(); @@ -73,10 +121,67 @@ class Device { * EACCES - Mutex of port cannot be taken (access denied). * * \return The device type as an enum. + * + * \b Example + * \code + * #define DEVICE_PORT 1 + * + * void opcontrol() { + Device device(DEVICE_PORT); + * while (true) { + * DeviceType dt = device.get_plugged_type(); + * printf("device plugged type: {plugged type: %d}\n", dt); + * delay(20); + * } + * } + * \endcode */ pros::DeviceType get_plugged_type() const; + /** + * Gets the type of device on a given port. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Mutex of port cannot be taken (access denied). + * + * \param port The V5 port number from 1-21 + * + * \return The device type as an enum. + * + * \b Example + * \code + * #define DEVICE_PORT 1 + * + * void opcontrol() { + * while (true) { + * DeviceType dt = pros::Device::get_plugged_type(DEVICE_PORT); + * printf("device plugged type: {plugged type: %d}\n", dt); + * delay(20); + * } + * } + * \endcode + */ + static pros::DeviceType get_plugged_type(std::uint8_t port); + + /** + * Gets all devices of a given device type. + * + * \param device_type The pros::DeviceType enum that matches the type of device desired. + * + * \return A vector of Device objects for the given device type. + * + * \b Example + * \code + * void opcontrol() { + * std::vector motor_devices = pros::Device::get_all_devices(pros::DeviceType::motor); // All Device objects are motors + * } + * \endcode + */ + + static std::vector get_all_devices(pros::DeviceType device_type = pros::DeviceType::undefined); + protected: /** * Creates a Device object. @@ -92,6 +197,8 @@ class Device { protected: const std::uint8_t _port; const enum DeviceType _deviceType = pros::DeviceType::none; + + ///@} }; } // namespace v5 } // namespace pros diff --git a/include/pros/distance.h b/include/pros/distance.h index cbe1040..e64f0d9 100644 --- a/include/pros/distance.h +++ b/include/pros/distance.h @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the VEX Distance sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/distance.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -111,6 +108,18 @@ int32_t distance_get_confidence(uint8_t port); * \param port The V5 Distance Sensor port number from 1-21 * \return The size value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * #define DISTANCE_PORT 1 + * + * void opcontrol() { + * while (true) { + * printf("Distance Object Size: %d\n", distance_get_object_size(DISTANCE_PORT)); + * delay(20); + * } + * } + * \endcode */ int32_t distance_get_object_size(uint8_t port); @@ -132,7 +141,7 @@ int32_t distance_get_object_size(uint8_t port); * * void opcontrol() { * while (true) { - * printf("Distance Object Size: %d\n", distance_get_object_size(DISTANCE_PORT)); + * printf("Distance Object Velocity: %f\n", distance_get_object_velocity(DISTANCE_PORT)); * delay(20); * } * } diff --git a/include/pros/distance.hpp b/include/pros/distance.hpp index 96ba1a1..17df3d1 100644 --- a/include/pros/distance.hpp +++ b/include/pros/distance.hpp @@ -4,18 +4,15 @@ * * Contains prototypes for the V5 Distance Sensor-related functions. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/distance.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-distance VEX Distance Sensor C++ API */ @@ -37,7 +34,7 @@ class Distance : public Device { /** * \addtogroup cpp-distance * @{ - */ + */ public: /** * Creates a Distance Sensor object for the given port. @@ -49,9 +46,19 @@ class Distance : public Device { * * \param port * The V5 port number from 1-21 + * + * \b Example + * \code + * #define DISTANCE_PORT 1 + * + * void opcontrol() { + * Distance distance(DISTANCE_PORT); + * } + * \endcode */ - explicit Distance(const std::uint8_t port); + Distance(const std::uint8_t port); + Distance(const Device& device) : Distance(device.get_port()){}; /** * Get the currently measured distance from the sensor in mm * @@ -61,10 +68,65 @@ class Distance : public Device { * ENODEV - The port cannot be configured as an Distance Sensor * * \return The distance value or PROS_ERR if the operation failed, setting - * errno. + * errno. Will return 9999 if the sensor can not detect an object. + * + * \b Example + * \code + * #define DISTANCE_PORT 1 + * + * void opcontrol() { + Distance distance(DISTANCE_PORT); + * while (true) { + * printf("Distance: %d\n", distance.get()); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get(); + /** + * Get the currently measured distance from the sensor in mm. + * \note This function is identical to get(). + * + * 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 Distance Sensor + * + * \return The distance value or PROS_ERR if the operation failed, setting + * errno. Will return 9999 if the sensor can not detect an object. + * + * \b Example + * \code + * #define DISTANCE_PORT 1 + * + * void opcontrol() { + Distance distance(DISTANCE_PORT); + * while (true) { + * printf("Distance: %d\n", distance.get_distance()); + * delay(20); + * } + * } + * \endcode + */ + virtual std::int32_t get_distance(); + + /** + * Gets all distance sensors. + * + * \return A vector of Distance sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector distance_all = pros::Distance::get_all_devices(); // All distance sensors that are + * connected + * } + * \endcode + */ + static std::vector get_all_devices(); + /** * Get the confidence in the distance reading * @@ -79,6 +141,19 @@ class Distance : public Device { * * \return The confidence value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * #define DISTANCE_PORT 1 + * + * void opcontrol() { + Distance distance(DISTANCE_PORT); + * while (true) { + * printf("Distance confidence: %d\n", distance.get_confidence()); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get_confidence(); @@ -95,7 +170,20 @@ class Distance : public Device { * ENODEV - The port cannot be configured as an Distance Sensor * * \return The size value or PROS_ERR if the operation failed, setting - * errno. + * errno. Will return -1 if the sensor is not able to determine object size. + * + * \b Example + * \code + * #define DISTANCE_PORT 1 + * + * void opcontrol() { + Distance distance(DISTANCE_PORT); + * while (true) { + * printf("Distance object size: %d\n", distance.get_object_size()); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get_object_size(); @@ -109,26 +197,51 @@ class Distance : public Device { * * \return The velocity value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * + * void opcontrol() { + * Distance distance(DISTANCE_PORT); + * while (true) { + * printf("Distance object velocity: %f\n", distance.get_object_velocity()); + * delay(20); + * } + * } + * \endcode */ virtual double get_object_velocity(); - /** - * This is the overload for the << operator for printing to streams - * - * Prints in format(this below is all in one line with no new line): - * Distance [port: (port number), distance: (distance), confidence: (confidence), - * object size: (object size), object velocity: (object velocity)] - */ + /** + * This is the overload for the << operator for printing to streams + * + * Prints in format(this below is all in one line with no new line): + * Distance [port: (port number), distance: (distance), confidence: (confidence), + * object size: (object size), object velocity: (object velocity)] + */ friend std::ostream& operator<<(std::ostream& os, pros::Distance& distance); - + private: ///@} }; namespace literals { +/** + * Constructs a Distance sensor object from a literal ending in _dist via calling the constructor + * + * \return a pros::Distance for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Distance dist = 2_dist; //Makes an dist object on port 2 + * } + * \endcode + */ const pros::Distance operator"" _dist(const unsigned long long int d); } // namespace literals -} +} // namespace v5 } // namespace pros #endif diff --git a/include/pros/error.h b/include/pros/error.h index a7e4e54..e1d03b6 100644 --- a/include/pros/error.h +++ b/include/pros/error.h @@ -6,7 +6,7 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright Copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright Copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -18,12 +18,25 @@ #include "limits.h" // Different Byte Size Errors + +/// @brief +/// Return This on Byte Sized Return Error #define PROS_ERR_BYTE (INT8_MAX) + +/// @brief +/// Return This on 2 Byte Sized Return Error #define PROS_ERR_2_BYTE (INT16_MAX) + +/// @brief +/// Return This on 4 Byte Sized Return Error #define PROS_ERR (INT32_MAX) + +/// @brief +/// Return This on 8 Byte Sized Return Error #define PROS_ERR_F (INFINITY) -// Return This on Success +/// @brief +/// Return This on Success (1) #define PROS_SUCCESS (1) #endif diff --git a/include/pros/ext_adi.h b/include/pros/ext_adi.h index 4c7cd45..18fde00 100644 --- a/include/pros/ext_adi.h +++ b/include/pros/ext_adi.h @@ -4,12 +4,10 @@ * * Contains prototypes for interfacing with the 3-Wire Expander. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -70,6 +68,19 @@ namespace c { * the configuration * * \return The ADI configuration for the given port + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void opcontrol() { + * ext_adi_port_set_config(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT, E_ADI_ANALOG_IN); + * // Displays the value of E_ADI_ANALOG_IN + * printf("Port Type: %d\n", ext_adi_port_get_config(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT)); + * } + * \endcode */ adi_port_config_e_t ext_adi_port_get_config(uint8_t smart_port, uint8_t adi_port); @@ -88,6 +99,18 @@ adi_port_config_e_t ext_adi_port_get_config(uint8_t smart_port, uint8_t adi_port * the configuration * * \return The value stored for the given port + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void opcontrol() { + * ext_adi_port_set_config(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT, E_ADI_ANALOG_IN); + * printf("Port Value: %d\n", ext_adi_get_value(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT)); + * } + * \endcode */ int32_t ext_adi_port_get_value(uint8_t smart_port, uint8_t adi_port); @@ -108,6 +131,17 @@ int32_t ext_adi_port_get_value(uint8_t smart_port, uint8_t adi_port); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void opcontrol() { + * ext_adi_port_set_config(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT, E_ADI_ANALOG_IN); + * } + * \endcode */ int32_t ext_adi_port_set_config(uint8_t smart_port, uint8_t adi_port, adi_port_config_e_t type); @@ -132,6 +166,18 @@ int32_t ext_adi_port_set_config(uint8_t smart_port, uint8_t adi_port, adi_port_c * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define DIGITAL_SENSOR_PORT 1 + * + * void initialize() { + * ext_adi_port_set_config(ADI_EXPANDER_PORT, DIGITAL_SENSOR_PORT, E_ADI_DIGITAL_OUT); + * ext_adi_set_value(ADI_EXPANDER_PORT, DIGITAL_SENSOR_PORT, HIGH); + * } + * \endcode */ int32_t ext_adi_port_set_value(uint8_t smart_port, uint8_t adi_port, int32_t value); @@ -160,6 +206,20 @@ int32_t ext_adi_port_set_value(uint8_t smart_port, uint8_t adi_port, int32_t val * The ADI port to calibrate (from 1-8, 'a'-'h', 'A'-'H') * * \return The average sensor value computed by this function + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void initialize() { + * ext_adi_analog_calibrate(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT); + * printf("Calibrated Reading: %d\n", + * ext_adi_analog_read_calibrated(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT)); + * // All readings from then on will be calibrated + * } + * \endcode */ int32_t ext_adi_analog_calibrate(uint8_t smart_port, uint8_t adi_port); @@ -183,6 +243,20 @@ int32_t ext_adi_analog_calibrate(uint8_t smart_port, uint8_t adi_port); * * \return The analog sensor value, where a value of 0 reflects an input voltage * of nearly 0 V and a value of 4095 reflects an input voltage of nearly 5 V + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void opcontrol() { + * while (true) { + * printf("Sensor Reading: %d\n", ext_adi_analog_read(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT)); + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_analog_read(uint8_t smart_port, uint8_t adi_port); @@ -208,6 +282,20 @@ int32_t ext_adi_analog_read(uint8_t smart_port, uint8_t adi_port); * * \return The difference of the sensor value from its calibrated default from * -4095 to 4095 + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void opcontrol() { + * while (true) { + * printf("Sensor Reading: %d\n", ext_adi_analog_read_calibrated(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT)); + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_analog_read_calibrated(uint8_t smart_port, uint8_t adi_port); @@ -238,6 +326,22 @@ int32_t ext_adi_analog_read_calibrated(uint8_t smart_port, uint8_t adi_port); * * \return The difference of the sensor value from its calibrated default from * -16384 to 16384 + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void opcontrol() { + * while (true) { + * ext_adi_analog_calibrate(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT); + * + * printf("Sensor Reading: %d\n", ext_adi_analog_read_calibrated_HR(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT)); + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_analog_read_calibrated_HR(uint8_t smart_port, uint8_t adi_port); @@ -261,6 +365,21 @@ int32_t ext_adi_analog_read_calibrated_HR(uint8_t smart_port, uint8_t adi_port); * The ADI port to read (from 1-8, 'a'-'h', 'A'-'H') * * \return True if the pin is HIGH, or false if it is LOW + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define DIGITAL_SENSOR_PORT 1 + * + * void opcontrol() { + * while (true) { + * printf(“Sensor Value: %dn”, + * ext_adi_digital_read(ADI_EXPANDER_PORT, DIGITAL_SENSOR_PORT)); + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_digital_read(uint8_t smart_port, uint8_t adi_port); @@ -288,6 +407,22 @@ int32_t ext_adi_digital_read(uint8_t smart_port, uint8_t adi_port); * * \return 1 if the button is pressed and had not been pressed * the last time this function was called, 0 otherwise. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define DIGITAL_SENSOR_PORT 1 + * + * void opcontrol() { + * while (true) { + * if (ext_adi_digital_get_new_press(ADI_EXPANDER_PORT, DIGITAL_SENSOR_PORT)) { + * // Toggle pneumatics or other state operations + * } + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_digital_get_new_press(uint8_t smart_port, uint8_t adi_port); @@ -312,6 +447,23 @@ int32_t ext_adi_digital_get_new_press(uint8_t smart_port, uint8_t adi_port); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define DIGITAL_SENSOR_PORT 1 + * + * void opcontrol() { + * bool state = LOW; + * while (true) { + * state != state; + * ext_adi_digital_write(ADI_EXPANDER_PORT, DIGITAL_SENSOR_PORT, state); + * + * delay(5); // toggle the sensor value every 50ms + * } + * } + * \endcode */ int32_t ext_adi_digital_write(uint8_t smart_port, uint8_t adi_port, bool value); @@ -332,6 +484,17 @@ int32_t ext_adi_digital_write(uint8_t smart_port, uint8_t adi_port, bool value); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define ANALOG_SENSOR_PORT 1 + * + * void initialize() { + * ext_adi_pin_mode(ADI_EXPANDER_PORT, ANALOG_SENSOR_PORT, INPUT_ANALOG); + * } + * \endcode */ int32_t ext_adi_pin_mode(uint8_t smart_port, uint8_t adi_port, uint8_t mode); @@ -354,6 +517,19 @@ int32_t ext_adi_pin_mode(uint8_t smart_port, uint8_t adi_port, uint8_t mode); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define MOTOR_PORT 1 + * + * void opcontrol() { + * ext_adi_motor_set(ADI_EXPANDER_PORT, MOTOR_PORT, 127); // Go full speed forward + * delay(1000); + * ext_adi_motor_set(ADI_EXPANDER_PORT, MOTOR_PORT, 0); // Stop the motor + * } + * \endcode */ int32_t ext_adi_motor_set(uint8_t smart_port, uint8_t adi_port, int8_t speed); @@ -372,6 +548,22 @@ int32_t ext_adi_motor_set(uint8_t smart_port, uint8_t adi_port, int8_t speed); * The ADI port to get (from 1-8, 'a'-'h', 'A'-'H') * * \return The last set speed of the motor on the given port + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 # + * define MOTOR_PORT 1 + * + * void opcontrol() { + * ext_adi_motor_set(ADI_EXPANDER_PORT, + * MOTOR_PORT, 127); // Go full speed forward + * printf(“Commanded Motor Power: %dn”, + * ext_adi_motor_get(ADI_EXPANDER_PORT, MOTOR_PORT)); // Will display 127 + * delay(1000); + * ext_adi_motor_set(ADI_EXPANDER_PORT, MOTOR_PORT, 0); // Stop the motor + * } + * \endcode */ int32_t ext_adi_motor_get(uint8_t smart_port, uint8_t adi_port); @@ -391,14 +583,27 @@ int32_t ext_adi_motor_get(uint8_t smart_port, uint8_t adi_port); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define MOTOR_PORT 1 + * + * void opcontrol() { + * ext_adi_motor_set(ADI_EXPANDER_PORT, MOTOR_PORT, 127); // Go full speed forward + * delay(1000); + * ext_adi_motor_set(ADI_EXPANDER_PORT, MOTOR_PORT, 0); // Stop the motor + * ext_adi_motor_stop(ADI_EXPANDER_PORT, MOTOR_PORT); // use this instead + * } + * \endcode */ int32_t ext_adi_motor_stop(uint8_t smart_port, uint8_t adi_port); /** * Reference type for an initialized encoder. * - * This merely contains the port number for the encoder, unlike its use as an - * object to store encoder data in PROS 2. + * This merely contains the port number for the encoder. */ typedef int32_t ext_adi_encoder_t; @@ -418,6 +623,23 @@ typedef int32_t ext_adi_encoder_t; * * \return The signed and cumulative number of counts since the last start or * reset + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define PORT_TOP 1 #define PORT_BOTTOM 2 + * + * void opcontrol() { + * ext_adi_encoder_t enc = ext_adi_encoder_init(ADI_EXPANDER_PORT, + * PORT_TOP, PORT_BOTTOM, false); + * while (true) { + * printf(“Encoder Value: %dn”, + * ext_adi_encoder_get(enc)); + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_encoder_get(ext_adi_encoder_t enc); @@ -442,6 +664,22 @@ int32_t ext_adi_encoder_get(ext_adi_encoder_t enc); * * \return An adi_encoder_t object to be stored and used for later calls to * encoder functions + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define PORT_TOP 1 + * #define PORT_BOTTOM 2 + * + * void opcontrol() { + * ext_adi_encoder_t enc = ext_adi_encoder_init(ADI_EXPANDER_PORT, PORT_TOP, PORT_BOTTOM, false); + * while (true) { + * printf("Encoder Value: %d\n", ext_adi_encoder_get(enc)); + * delay(5); + * } + * } + * \endcode */ ext_adi_encoder_t ext_adi_encoder_init(uint8_t smart_port, uint8_t adi_port_top, uint8_t adi_port_bottom, bool reverse); @@ -462,6 +700,20 @@ ext_adi_encoder_t ext_adi_encoder_init(uint8_t smart_port, uint8_t adi_port_top, * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define PORT_TOP 1 + * #define PORT_BOTTOM 2 + * + * void opcontrol() { + * ext_adi_encoder_t enc = ext_adi_encoder_init(ADI_EXPANDER_PORT, PORT_TOP, PORT_BOTTOM, false); + * delay(1000); // Move the encoder around in this time + * ext_adi_encoder_reset(enc); // The encoder is now zero again + * } + * \endcode */ int32_t ext_adi_encoder_reset(ext_adi_encoder_t enc); @@ -479,14 +731,27 @@ int32_t ext_adi_encoder_reset(ext_adi_encoder_t enc); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define ADI_EXPANDER_PORT 20 + * #define PORT_TOP 1 + * #define PORT_BOTTOM 2 + * + * void opcontrol() { + * ext_adi_encoder_t enc = ext_adi_encoder_init(ADI_EXPANDER_PORT, PORT_TOP, PORT_BOTTOM, false); + * // Use the encoder + * ext_adi_encoder_shutdown(enc); + * } + * \endcode */ int32_t ext_adi_encoder_shutdown(ext_adi_encoder_t enc); /** * Reference type for an initialized ultrasonic. * - * This merely contains the port number for the ultrasonic, unlike its use as an - * object to store encoder data in PROS 2. + * This merely contains the port number for the ultrasonic. */ typedef int32_t ext_adi_ultrasonic_t; @@ -508,6 +773,23 @@ typedef int32_t ext_adi_ultrasonic_t; * * \return The distance to the nearest object in m^-4 (10000 indicates 1 meter), * measured from the sensor's mounting points. + * + * \b Example + * \code + * + * #define PORT_PING 1 + * #define PORT_ECHO 2 + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_ultrasonic_t ult = ext_adi_ultrasonic_init(ADI_EXPANDER_PORT, PORT_PING, PORT_ECHO); + * while (true) { + * // Print the distance read by the ultrasonic + * printf("Distance: %d\n", ext_adi_ultrasonic_get(ult)); + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_ultrasonic_get(ext_adi_ultrasonic_t ult); @@ -531,6 +813,23 @@ int32_t ext_adi_ultrasonic_get(ext_adi_ultrasonic_t ult); * * \return An adi_ultrasonic_t object to be stored and used for later calls to * ultrasonic functions + * + * \b Example + * \code + * + * #define PORT_PING 1 + * #define PORT_ECHO 2 + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_ultrasonic_t ult = ext_adi_ultrasonic_init(ADI_EXPANDER_PORT, PORT_PING, PORT_ECHO); + * while (true) { + * // Print the distance read by the ultrasonic + * printf("Distance: %d\n", ext_adi_ultrasonic_get(ult)); + * delay(5); + * } + * } + * \endcode */ ext_adi_ultrasonic_t ext_adi_ultrasonic_init(uint8_t smart_port, uint8_t adi_port_ping, uint8_t adi_port_echo); @@ -548,14 +847,31 @@ ext_adi_ultrasonic_t ext_adi_ultrasonic_init(uint8_t smart_port, uint8_t adi_por * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define PORT_PING 1 + * #define PORT_ECHO 2 + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_ultrasonic_t ult = ext_adi_ultrasonic_init(ADI_EXPANDER_PORT, PORT_PING, PORT_ECHO); + * while (true) { + * // Print the distance read by the ultrasonic + * printf("Distance: %d\n", ext_adi_ultrasonic_get(ult)); + * delay(5); + * } + * ext_adi_ultrasonic_shutdown(ult); + * } + * \endcode */ int32_t ext_adi_ultrasonic_shutdown(ext_adi_ultrasonic_t ult); /** * Reference type for an initialized gyroscope. * - * This merely contains the port number for the gyroscope, unlike its use as an - * object to store gyro data in PROS 2. + * This merely contains the port number for the gyroscope. * * (Might Be useless with the wire expander.) */ @@ -579,6 +895,23 @@ typedef int32_t ext_adi_gyro_t; * The adi_gyro_t object for which the angle will be returned * * \return The gyro angle in degrees. + * + * \b Example + * \code + * + * #define GYRO_PORT 1 + * #define GYRO_MULTIPLIER 1 // Standard behavior + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_gyro_t gyro = ext_adi_gyro_init(ADI_EXPANDER_PORT, GYRO_PORT, GYRO_MULTIPLIER); + * while (true) { + * // Print the gyro's heading + * printf("Heading: %lf\n", ext_adi_gyro_get(gyro)); + * delay(5); + * } + * } + * \endcode */ double ext_adi_gyro_get(ext_adi_gyro_t gyro); @@ -606,6 +939,23 @@ double ext_adi_gyro_get(ext_adi_gyro_t gyro); * * \return An adi_gyro_t object containing the given port, or PROS_ERR if the * initialization failed. + * + * \b Example + * \code + * + * #define GYRO_PORT 1 + * #define GYRO_MULTIPLIER 1 // Standard behavior + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_gyro_t gyro = ext_adi_gyro_init(ADI_EXPANDER_PORT, GYRO_PORT, GYRO_MULTIPLIER); + * while (true) { + * // Print the gyro's heading + * printf("Heading: %lf\n", ext_adi_gyro_get(gyro)); + * delay(5); + * } + * } + * \endcode */ ext_adi_gyro_t ext_adi_gyro_init(uint8_t smart_port, uint8_t adi_port, double multiplier); @@ -623,6 +973,31 @@ ext_adi_gyro_t ext_adi_gyro_init(uint8_t smart_port, uint8_t adi_port, double mu * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define GYRO_PORT 1 + * #define GYRO_MULTIPLIER 1 // Standard behavior + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_gyro_t gyro = ext_adi_gyro_init(ADI_EXPANDER_PORT, GYRO_PORT, GYRO_MULTIPLIER); + * uint32_t now = millis(); + * while (true) { + * // Print the gyro's heading + * printf("Heading: %lf\n", ext_adi_gyro_get(gyro)); + * + * if (millis() - now > 2000) { + * // Reset the gyro every 2 seconds + * ext_adi_gyro_reset(gyro); + * now = millis(); + * } + * + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_gyro_reset(ext_adi_gyro_t gyro); @@ -640,14 +1015,38 @@ int32_t ext_adi_gyro_reset(ext_adi_gyro_t gyro); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define GYRO_PORT 1 + * #define GYRO_MULTIPLIER 1 // Standard behavior + * #define ADI_EXPANDER_PORT 20 + * + * void opcontrol() { + * ext_adi_gyro_t gyro = ext_adi_gyro_init(ADI_EXPANDER_PORT, GYRO_PORT, GYRO_MULTIPLIER); + * uint32_t now = millis(); + * while (true) { + * // Print the gyro's heading + * printf("Heading: %lf\n", ext_adi_gyro_get(gyro)); + * + * if (millis() - now > 2000) { + * ext_adi_gyro_shutdown(gyro); + * // Shut down the gyro after two seconds + * break; + * } + * + * delay(5); + * } + * } + * \endcode */ int32_t ext_adi_gyro_shutdown(ext_adi_gyro_t gyro); /** * Reference type for an initialized potentiometer. * - * This merely contains the port number for the potentiometer, unlike its use as an - * object to store gyro data in PROS 2. + * This merely contains the port number for the potentiometer. */ typedef int32_t ext_adi_potentiometer_t; diff --git a/include/pros/gps.h b/include/pros/gps.h index 0586483..5cc5eef 100644 --- a/include/pros/gps.h +++ b/include/pros/gps.h @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the VEX GPS. * - * Visit https://pros.cs.purdue.edu/v5/api/c/gps.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -29,7 +26,7 @@ #ifdef __cplusplus extern "C" { namespace pros { -#endif +#endif /** * \ingroup c-gps @@ -58,23 +55,36 @@ typedef struct __attribute__((__packed__)) gps_status_s { double x; /// Y Position (meters) double y; - /// Percieved Pitch based on GPS + IMU + /// Perceived Pitch based on GPS + IMU double pitch; - /// Percieved Roll based on GPS + IMU + /// Perceived Roll based on GPS + IMU double roll; - /// Percieved Yaw based on GPS + IMU + /// Perceived Yaw based on GPS + IMU double yaw; } gps_status_s_t; +/** + * \struct gps_orientation_s_t + */ +typedef struct __attribute__((__packed__)) gps_orientation_s { + /// Perceived Pitch based on GPS + IMU + double pitch; + /// Perceived Roll based on GPS + IMU + double roll; + /// Perceived Yaw based on GPS + IMU + double yaw; +} gps_orientation_s_t; + + /** * \struct gps_raw_s */ struct gps_raw_s { - /// Percieved Pitch based on GPS + IMU + /// Perceived Pitch based on GPS + IMU double x; - /// Percieved Roll based on GPS + IMU + /// Perceived Roll based on GPS + IMU double y; - /// Percieved Yaw based on GPS + IMU + /// Perceived Yaw based on GPS + IMU double z; }; @@ -168,74 +178,6 @@ int32_t gps_initialize_full(uint8_t port, double xInitial, double yInitial, doub */ int32_t gps_set_offset(uint8_t port, double xOffset, double yOffset); -/** - * Gets the position and roll, yaw, and pitch of the GPS. - * - * 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 a GPS - * EAGAIN - The sensor is still calibrating - * - * \param port - * The V5 GPS port number from 1-21 - * - * \return A struct (gps_status_s_t) containing values mentioned above. - * If the operation failed, all the structure's members are filled with - * PROS_ERR_F and errno is set. - */ -gps_status_s_t gps_get_status(uint8_t port); - -/** - * Gets the x and y position on the field of the GPS in meters. - * - * 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 a GPS - * EAGAIN - The sensor is still calibrating - * - * \param port - * The V5 GPS port number from 1-21 - * - * \return A struct (gps_position_s_t) containing values mentioned above. - * If the operation failed, all the structure's members are filled with - * PROS_ERR_F and errno is set. - */ -gps_position_s_t gps_get_position(uint8_t port); - -/** - * Get the GPS's raw gyroscope values - * - * 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 a GPS - * EAGAIN - The sensor is still calibrating - * - * \param port - * The V5 GPS port number from 1-21 - * \return The raw gyroscope values. If the operation failed, all the - * structure's members are filled with PROS_ERR_F and errno is set. - */ -gps_gyro_s_t gps_get_gyro_rate(uint8_t port); - -/** - * Get the GPS's raw accelerometer values - * - * 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 GPS - * EAGAIN - The sensor is still calibrating - * - * \param port - * The V5 GPS's port number from 1-21 - * \return The raw accelerometer values. If the operation failed, all the - * structure's members are filled with PROS_ERR_F and errno is set. - */ -gps_accel_s_t gps_get_accel(uint8_t port); - /** * Get the GPS's cartesian location relative to the center of turning/origin in meters. * @@ -258,7 +200,7 @@ gps_accel_s_t gps_get_accel(uint8_t port); * gps_position_s_t pos; * * while (true) { - * pos = gps_get_offset(GPS_PORT, x, y); + * pos = gps_get_offset(GPS_PORT); * screen_print(TEXT_MEDIUM, 1, "X Offset: %4d, Y Offset: %4d", pos.x, pos.y); * delay(20); * } @@ -324,6 +266,9 @@ int32_t gps_set_position(uint8_t port, double xInitial, double yInitial, double * * void initialize() { * gps_set_data_rate(GPS_PORT, GPS_DATA_RATE); + * while (true) { + * // Do something + * } * } * \endcode */ @@ -351,6 +296,7 @@ int32_t gps_set_data_rate(uint8_t port, uint32_t rate); * void opcontrol() { * double error; * error = gps_get_error(GPS_PORT); + * screen_print(TEXT_MEDIUM, 1, "Error: %4d", error); * } * \endcode */ @@ -371,28 +317,26 @@ double gps_get_error(uint8_t port); * \return A struct (gps_status_s_t) containing values mentioned above. * If the operation failed, all the structure's members are filled with * PROS_ERR_F and errno is set. - * + * * \b Example * \code * #define GPS_PORT 1 - * + * * void opcontrol() { - * struct gps_status_s_t status; - * + * gps_status_s_t status; + * * while (true) { - * status = gps_get_status(GPS_PORT); - * screen_print(TEXT_MEDIUM, 1, "x: %3f, y: %3f, pitch: %3f", status.x, status.y); - * screen_print(TEXT_MEDIUM, 2, "yaw: %3f, roll: %3f", status.pitch, status.yaw); - * screen_print(TEXT_MEDIUM, 3, "roll: %3f", status.roll); + * status = gps_get_position_and_orientation(GPS_PORT); + * printf("X: %f, Y: %f, Pitch: %f, Roll: %f, Yaw: %f\n", status.x, status.y, status.pitch, status.roll, status.yaw); * delay(20); * } * } * \endcode */ -gps_status_s_t gps_get_status(uint8_t port); +gps_status_s_t gps_get_position_and_orientation(uint8_t port); /** - * Get the heading in [0,360) degree values. + * Gets the x and y position on the field of the GPS in meters. * * This function uses the following values of errno when an error state is * reached: @@ -403,27 +347,29 @@ gps_status_s_t gps_get_status(uint8_t port); * \param port * The V5 GPS port number from 1-21 * - * \return The heading in [0,360) degree values. If the operation failed, - * returns PROS_ERR_F and errno is set. + * \return A struct (gps_position_s_t) containing values mentioned above. + * If the operation failed, all the structure's members are filled with + * PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 - * + * * void opcontrol() { - * double heading; - * + * gps_position_s_t position; + * * while (true) { - * heading = gps_get_heading(GPS_PORT); + * position = gps_get_position(GPS_PORT); + * printf("X: %f, Y: %f\n", position.x, position.y); * delay(20); * } * } * \endcode */ -double gps_get_heading(uint8_t port); +gps_position_s_t gps_get_position(uint8_t port); /** - * Get the heading in the max double value and min double value scale. + * Gets the X position in meters of the robot relative to the starting position. * * This function uses the following values of errno when an error state is * reached: @@ -433,28 +379,61 @@ double gps_get_heading(uint8_t port); * * \param port * The V5 GPS port number from 1-21 - * - * \return The heading in [DOUBLE_MIN, DOUBLE_MAX] values. If the operation - * fails, returns PROS_ERR_F and errno is set. + * + * \return The X position in meters. If the operation failed, + * returns PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 - * + * * void opcontrol() { - * double heading; + * double pos_x; + * + * while (true) { + * pos_x = gps_get_position_x(GPS_PORT); + * printf("X: %f\n", pos_x); + * delay(20); + * } + * } + * \endcode + */ +double gps_get_position_x(uint8_t port); + +/** + * Gets the Y position in meters of the robot relative to the starting position. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 * + * \return The Y position in meters. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double pos_y; + * * while (true) { - * heading = gps_get_heading_raw(GPS_PORT); + * pos_y = gps_get_position_y(GPS_PORT); + * printf("Y: %f\n", pos_y); * delay(20); * } * } * \endcode */ -double gps_get_heading_raw(uint8_t port); +double gps_get_position_y(uint8_t port); /** - * Gets the GPS sensor's elapsed rotation value + * Gets the pitch, roll, and yaw of the GPS relative to the starting orientation. * * This function uses the following values of errno when an error state is * reached: @@ -464,24 +443,62 @@ double gps_get_heading_raw(uint8_t port); * * \param port * The V5 GPS port number from 1-21 - * \return The elased heading in degrees. If the operation fails, returns + * + * \return A struct (gps_orientation_s_t) containing values mentioned above. + * If the operation failed, all the structure's members are filled with * PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 - * + * * void opcontrol() { - * double elapsed_rotation; + * gps_orientation_s_t orientation; + * + * while (true) { + * orientation = gps_get_orientation(GPS_PORT); + * printf("pitch: %f, roll: %f, yaw: %f\n", orientation.pitch, orientation.roll, orientation.yaw); + * delay(20); + * } + * } + * \endcode +*/ +gps_orientation_s_t gps_get_orientation(uint8_t port); + +/** + * Gets the pitch of the robot in degrees relative to the starting oreintation. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 + * + * \return The pitch in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. * - * elapsed_rotation = gps_get_rotation(GPS_PORT); + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double pitch; + * + * while (true) { + * pitch = gps_get_pitch(GPS_PORT); + * printf("pitch: %f\n", pitch); + * delay(20); + * } * } * \endcode */ -double gps_get_rotation(uint8_t port); +double gps_get_pitch(uint8_t port); /** - * Set the GPS sensor's rotation value to target value + * Gets the roll of the robot in degrees relative to the starting oreintation. * * This function uses the following values of errno when an error state is * reached: @@ -491,24 +508,61 @@ double gps_get_rotation(uint8_t port); * * \param port * The V5 GPS port number from 1-21 - * \param target - * Target rotation value to set rotation value to - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. + * + * \return The roll in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 + * + * void opcontrol() { + * double roll; + * + * while (true) { + * roll = gps_get_roll(GPS_PORT); + * printf("roll: %f\n", roll); + * delay(20); + * } + * } + * \endcode + */ +double gps_get_roll(uint8_t port); + +/** + * Gets the yaw of the robot in degrees relative to the starting oreintation. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 * + * \return The yaw in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * * void opcontrol() { - * gps_set_rotation(GPS_PORT, 60); + * double yaw; + * + * while (true) { + * yaw = gps_get_yaw(GPS_PORT); + * printf("yaw: %f\n", yaw); + * delay(20); + * } * } * \endcode */ -int32_t gps_set_rotation(uint8_t port, double target); +double gps_get_yaw(uint8_t port); /** - * Tare the GPS sensor's rotation value + * Get the heading in [0,360) degree values. * * This function uses the following values of errno when an error state is * reached: @@ -518,19 +572,58 @@ int32_t gps_set_rotation(uint8_t port, double target); * * \param port * The V5 GPS port number from 1-21 - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. + * + * \return The heading in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 + * + * void opcontrol() { + * double heading; + * + * while (true) { + * heading = gps_get_heading(GPS_PORT); + * printf("heading: %f\n", heading); + * delay(20); + * } + * } + * \endcode + */ +double gps_get_heading(uint8_t port); + +/** + * Get the heading in the max double value and min double value scale. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 + * + * \return The heading in [DOUBLE_MIN, DOUBLE_MAX] values. If the operation + * fails, returns PROS_ERR_F and errno is set. * - * void initialize() { - * gps_tare_rotation(GPS_PORT); + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double heading_raw; + * + * while (true) { + * heading_raw = gps_get_heading_raw(GPS_PORT); + * printf("heading_raw: %f\n", heading_raw); + * delay(20); + * } * } * \endcode */ -int32_t gps_tare_rotation(uint8_t port); +double gps_get_heading_raw(uint8_t port); /** * Get the GPS's raw gyroscope values @@ -543,25 +636,119 @@ int32_t gps_tare_rotation(uint8_t port); * * \param port * The V5 GPS port number from 1-21 - * \return The raw gyroscope values. If the operation failed, all the + * \return A struct (gps_gyro_s_t) containing values mentioned above. + * If the operation failed, all the * structure's members are filled with PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * gps_gyro_s_t gyro; + * + * while (true) { + * gyro = gps_get_gyro(GPS_PORT); + * printf("Gyro: %f %f %f\n", gyro.x, gyro.y, gyro.z); + * delay(20); + * } + * } + * \endcode + */ +gps_gyro_s_t gps_get_gyro_rate(uint8_t port); + +/** + * Get the GPS's raw gyroscope value in x-axis + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 + * \return The raw gyroscope value in x-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 + * + * void opcontrol() { + * double gyro_x; + * + * while (true) { + * gyro_x = gps_get_gyro_x(GPS_PORT); + * printf("gyro_x: %f\n", gyro_x); + * delay(20); + * } + * } + * \endcode +*/ +double gps_get_gyro_rate_x(uint8_t port); + +/** + * Get the GPS's raw gyroscope value in y-axis + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating * + * \param port + * The V5 GPS port number from 1-21 + * \return The raw gyroscope value in y-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * * void opcontrol() { - * struct gps_gyro_s_t gyro; + * double gyro_y; + * + * while (true) { + * gyro_y = gps_get_gyro_y(GPS_PORT); + * printf("gyro_y: %f\n", gyro_y); + * delay(20); + * } + * } + * \endcode +*/ +double gps_get_gyro_rate_y(uint8_t port); + +/** + * Get the GPS's raw gyroscope value in z-axis * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 + * \return The raw gyroscope value in z-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double gyro_z; + * * while (true) { - * gyro = gps_get_gyro_rate(GPS_PORT); - * screen_print(TEXT_MEDIUM, 1, "gyroscope- x: %3f, y: %3f, z: %3f", gyro.x, gyro.y, gyro.z); + * gyro_z = gps_get_gyro_z(GPS_PORT); + * printf("gyro_z: %f\n", gyro_z); * delay(20); * } * } * \endcode - */ -gps_gyro_s_t gps_get_gyro_rate(uint8_t port); +*/ +double gps_get_gyro_rate_z(uint8_t port); /** * Get the GPS's raw accelerometer values @@ -574,26 +761,119 @@ gps_gyro_s_t gps_get_gyro_rate(uint8_t port); * * \param port * The V5 GPS's port number from 1-21 - * \return The raw accelerometer values. If the operation failed, all the + * \return A struct (gps_accel_s_t) containing values mentioned above. + * If the operation failed, all the * structure's members are filled with PROS_ERR_F and errno is set. * * \b Example * \code * #define GPS_PORT 1 - * + * * void opcontrol() { - * struct gps_accel_s_t accel; - * + * gps_accel_s_t accel; + * * while (true) { * accel = gps_get_accel(GPS_PORT); - * screen_print(TEXT_MEDIUM, 1, "accleration- x: %3f, y: %3f, z: %3f", accel.x, accel.y, accel.z); + * printf("X: %f, Y: %f, Z: %f\n", accel.x, accel.y, accel.z); + * delay(20); * } * } * \endcode */ gps_accel_s_t gps_get_accel(uint8_t port); -///@} +/** + * Get the GPS's raw accelerometer value in x-axis + * + * 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 GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS's port number from 1-21 + * \return The raw accelerometer value in x-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double accel_x; + * + * while (true) { + * accel_x = gps_get_accel_x(GPS_PORT); + * printf("accel_x: %f\n", accel_x); + * delay(20); + * } + * } + * \endcode +*/ +double gps_get_accel_x(uint8_t port); + +/** + * Get the GPS's raw accelerometer value in y-axis + * + * 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 GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS's port number from 1-21 + * \return The raw accelerometer value in y-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double accel_y; + * + * while (true) { + * accel_y = gps_get_accel_y(GPS_PORT); + * printf("accel_y: %f\n", accel_y); + * delay(20); + * } + * } + * \endcode +*/ +double gps_get_accel_y(uint8_t port); + +/** + * Get the GPS's raw accelerometer value in z-axis + * + * 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 GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS's port number from 1-21 + * \return The raw accelerometer value in z-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * double accel_z; + * + * while (true) { + * accel_z = gps_get_accel_z(GPS_PORT); + * printf("accel_z: %f\n", accel_z); + * delay(20); + * } + * } + * \endcode +*/ +double gps_get_accel_z(uint8_t port); #ifdef __cplusplus } diff --git a/include/pros/gps.hpp b/include/pros/gps.hpp index 9922bec..b9fc7b5 100644 --- a/include/pros/gps.hpp +++ b/include/pros/gps.hpp @@ -4,18 +4,15 @@ * * Contains prototypes for functions related to the VEX GPS. * - * Visit https://pros.cs.purdue.edu/v5/api/cpp/gps.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-gps VEX GPS Sensor C API * \note For a pros-specific usage guide on the GPS, please check out our article [here.](@ref gps) */ @@ -28,8 +25,8 @@ #include #include -#include "pros/gps.h" #include "pros/device.hpp" +#include "pros/gps.h" namespace pros { inline namespace v5 { @@ -44,18 +41,113 @@ class Gps : public Device { */ public: - explicit Gps(const std::uint8_t port) : Device(port, DeviceType::gps){}; + /** + * Creates a GPS object for the given port. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 port number from 1-21 + * \b Example: + * \code + * pros::Gps gps(1); + * \endcode + * + */ + Gps(const std::uint8_t port) : Device(port, DeviceType::gps){}; - explicit Gps(const std::uint8_t port, double xInitial, double yInitial, double headingInitial) : Device(port, DeviceType::gps){ + Gps(const Device& device) : Gps(device.get_port()){}; + + /** + * Creates a GPS object for the given port. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 port number from 1-21 + * \param xInitial + * Cartesian 4-Quadrant X initial position (meters) + * \param yInitial + * Cartesian 4-Quadrant Y initial position (meters) + * \param headingInitial + * Initial heading (degrees) + * + * \b Example: + * \code + * pros::Gps gps(1, 1.30, 1.20, 90); + * \endcode + * + */ + explicit Gps(const std::uint8_t port, double xInitial, double yInitial, double headingInitial) + : Device(port, DeviceType::gps) { pros::c::gps_set_position(port, xInitial, yInitial, headingInitial); }; - explicit Gps(const std::uint8_t port, double xOffset, double yOffset) : Device(port, DeviceType::gps){ + /** + * Creates a GPS object for the given port. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 port number from 1-21 + * \param xOffset + * Cartesian 4-Quadrant X offset from center of turning (meters) + * \param yOffset + * Cartesian 4-Quadrant Y offset from center of turning (meters) + * + * \b Example: + * \code + * pros::Gps gps(1, 1.30, 1.20); + * \endcode + * + */ + explicit Gps(const std::uint8_t port, double xOffset, double yOffset) : Device(port, DeviceType::gps) { pros::c::gps_set_offset(port, xOffset, yOffset); }; - explicit Gps(const std::uint8_t port, double xInitial, double yInitial, double headingInitial, double xOffset, double yOffset) - : Device(port, DeviceType::gps){ + /** + * Creates a GPS object for the given port. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 port number from 1-21 + * \param xInitial + * Initial 4-Quadrant X Position, with (0,0) being at the center of the field (meters) + * \param yInitial + * Initial 4-Quadrant Y Position, with (0,0) being at the center of the field (meters) + * \param headingInitial + * Initial Heading, with 0 being North, 90 being East, 180 being South, and 270 being West (degrees) + * \param xOffset + * Cartesian 4-Quadrant X offset from center of turning (meters) + * \param yOffset + * Cartesian 4-Quadrant Y offset from center of turning (meters) + * + * \b Example: + * \code + * pros::Gps gps(1, 1.30, 1.20, 180, 1.30, 1.20); + * \endcode + * + */ + explicit Gps(const std::uint8_t port, double xInitial, double yInitial, double headingInitial, double xOffset, + double yOffset) + : Device(port, DeviceType::gps) { pros::c::gps_initialize_full(port, xInitial, yInitial, headingInitial, xOffset, yOffset); }; @@ -81,6 +173,20 @@ class Gps : public Device { * Heading with 0 being north on the field, in degrees [0,360) going clockwise * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT, 1.1, 1.2, 180, .4, .4); + * // this is equivalent to the above line + * gps.initialize_full(1.1, 1.2, 180, .4, .4); + * while (true) { + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t initialize_full(double xInitial, double yInitial, double headingInitial, double xOffset, double yOffset) const; @@ -100,38 +206,67 @@ class Gps : public Device { * Cartesian 4-Quadrant Y offset from center of turning (meters) * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT, 1.1, 1.2, 180, .4, .4); + * // this is equivalent to the above line + * gps.set_offset(.4, .4); + * while (true) { + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t set_offset(double xOffset, double yOffset) const; /** - * Get the GPS's cartesian location relative to the center of turning/origin in meters. - * - * 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 a GPS - * EAGAIN - The sensor is still calibrating - * - * \param port - * The V5 GPS port number from 1-21 - * \return A struct (gps_position_s_t) containing the X and Y values if the operation - * failed, setting errno. - * - * \b Example - * \code - * #define GPS_PORT 1 - * - * void opcontrol() { - * gps_position_s_t pos; - * Gps gps(GPS_PORT); - * while (true) { - * pos = gps.get_offset(); - * screen_print(TEXT_MEDIUM, 1, "X Offset: %4d, Y Offset: %4d", pos.x, pos.y); - * delay(20); - * } - * } - * \endcode - */ + + * Gets all GPS sensors. + * + * \return A vector of Gps sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector gps_all = pros::Gps::get_all_devices(); // All GPS sensors that are connected + * } + * \endcode + */ + static std::vector get_all_devices(); + + /** + * Get the GPS's cartesian location relative to the center of turning/origin in meters. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \param port + * The V5 GPS port number from 1-21 + * \return A struct (gps_position_s_t) containing the X and Y values if the operation + * failed, setting errno. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * gps_position_s_t pos; + * Gps gps(GPS_PORT); + * while (true) { + * pos = gps.get_offset(); + * screen_print(TEXT_MEDIUM, 1, "X Offset: %4d, Y Offset: %4d", pos.x, pos.y); + * delay(20); + * } + * } + * \endcode + */ virtual pros::gps_position_s_t get_offset() const; /** @@ -151,6 +286,21 @@ class Gps : public Device { * Heading with 0 being north on the field, in degrees [0,360) going clockwise * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * gps.set_position(1.3, 1.4, 180); + * while (true) { + * printf("X: %f, Y: %f, Heading: %f\n", gps.get_position().x, + * gps.get_position().y, gps.get_position().heading); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t set_position(double xInitial, double yInitial, double headingInitial) const; @@ -167,6 +317,21 @@ class Gps : public Device { * Data rate in milliseconds (Minimum: 5 ms) * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * gps.set_data_rate(10); + * while (true) { + * printf("X: %f, Y: %f, Heading: %f\n", gps.get_position().x, + * gps.get_position().y, gps.get_position().heading); + * delay(10); + * } + * } + * \endcode */ virtual std::int32_t set_data_rate(std::uint32_t rate) const; @@ -181,6 +346,18 @@ class Gps : public Device { * * \return Possible RMS (Root Mean Squared) error in meters for GPS position. * If the operation failed, returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * double error = gps.get_error(); + * printf("Error: %f\n", error); + * pros::delay(20); + * } + * \endcode */ virtual double get_error() const; @@ -197,8 +374,24 @@ class Gps : public Device { * \return A struct (gps_status_s_t) containing values mentioned above. * If the operation failed, all the structure's members are filled with * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * gps_status_s_t status; + * while (true) { + * status = gps.get_position_and_orientation(); + * printf("X: %f, Y: %f, Roll: %f, Pitch: %f, Yaw: %f\n", + * status.x, status.y, status.roll, status.pitch, status.yaw); + * delay(20); + * } + * } + * \endcode */ - virtual pros::gps_status_s_t get_status() const; + virtual pros::gps_status_s_t get_position_and_orientation() const; /** * Gets the x and y position on the field of the GPS in meters. @@ -212,9 +405,195 @@ class Gps : public Device { * \return A struct (gps_position_s_t) containing values mentioned above. * If the operation failed, all the structure's members are filled with * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * gps_position_s_t position; + * while (true) { + * position = gps.get_position(); + * printf("X: %f, Y: %f\n", position.x, position.y); + * delay(20); + * } + * } + * \endcode */ virtual pros::gps_position_s_t get_position() const; + /** + * Gets the X position in meters of the robot relative to the starting position. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \return The X position in meters. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double pos_x = gps.get_position_x(); + * printf("X: %f\n", pos_x); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_position_x() const; + + /** + * Gets the Y position in meters of the robot relative to the starting position. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \return The Y position in meters. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double pos_y = gps.get_position_y(); + * printf("Y: %f\n", pos_y); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_position_y() const; + + /** + * Gets the pitch, roll, and yaw of the GPS relative to the starting orientation. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \return A struct (gps_orientation_s_t) containing values mentioned above. + * If the operation failed, all the structure's members are filled with + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * gps_orientation_s_t orientation; + * while (true) { + * orientation = gps.get_orientation(); + * printf("pitch: %f, roll: %f, yaw: %f\n", orientation.pitch, + * orientation.roll, orientation.yaw); + * delay(20); + * } + * } + * \endcode + */ + virtual pros::gps_orientation_s_t get_orientation() const; + + /** + * Gets the pitch of the robot in degrees relative to the starting oreintation. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \return The pitch in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double pitch = gps.get_pitch(); + * printf("pitch: %f\n", pitch); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_pitch() const; + + /** + * Gets the roll of the robot in degrees relative to the starting oreintation. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \return The roll in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double roll = gps.get_roll(); + * printf("roll: %f\n", roll); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_roll() const; + + /** + * Gets the yaw of the robot in degrees relative to the starting oreintation. + * + * 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 a GPS + * EAGAIN - The sensor is still calibrating + * + * \return The yaw in [0,360) degree values. If the operation failed, + * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double yaw = gps.get_yaw(); + * printf("yaw: %f\n", yaw); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_yaw() const; + /** * Get the heading in [0,360) degree values. * @@ -227,6 +606,20 @@ class Gps : public Device { * * \return The heading in [0,360) degree values. If the operation failed, * returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double heading = gps.get_heading(); + * printf("Heading: %f\n", heading); + * pros::delay(20); + * } + * } + * \endcode */ virtual double get_heading() const; @@ -241,11 +634,25 @@ class Gps : public Device { * * \return The heading in [DOUBLE_MIN, DOUBLE_MAX] values. If the operation * fails, returns PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double heading = gps.get_heading_raw(); + * printf("Heading: %f\n", heading); + * pros::delay(20); + * } + * } + * \endcode */ virtual double get_heading_raw() const; /** - * Gets the GPS sensor's elapsed rotation value + * Get the GPS's raw gyroscope value in z-axis * * This function uses the following values of errno when an error state is * reached: @@ -253,13 +660,27 @@ class Gps : public Device { * ENODEV - The port cannot be configured as a GPS * EAGAIN - The sensor is still calibrating * - * \return The elased heading in degrees. If the operation fails, returns + * \return The raw gyroscope value in z-axis. If the operation fails, returns * PROS_ERR_F and errno is set. + * + \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double gyro_z = gps.get_gyro_z(); + * printf("gyro_z: %f\n", gyro_z); + * pros::delay(20); + * } + * } + * \endcode */ - virtual double get_rotation() const; + virtual pros::gps_gyro_s_t get_gyro_rate() const; /** - * Set the GPS sensor's rotation value to target value + * Get the GPS's raw gyroscope value in x-axis * * This function uses the following values of errno when an error state is * reached: @@ -267,15 +688,27 @@ class Gps : public Device { * ENODEV - The port cannot be configured as a GPS * EAGAIN - The sensor is still calibrating * - * \param target - * Target rotation value to set rotation value to - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. + * \return The raw gyroscope value in x-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double gyro_x = gps.get_gyro_x(); + * printf("gyro_x: %f\n", gyro_x); + * pros::delay(20); + * } + * } + * \endcode */ - virtual std::int32_t set_rotation(double target) const; + virtual double get_gyro_rate_x() const; /** - * Tare the GPS sensor's rotation value + * Get the GPS's raw gyroscope value in y-axis * * This function uses the following values of errno when an error state is * reached: @@ -283,13 +716,27 @@ class Gps : public Device { * ENODEV - The port cannot be configured as a GPS * EAGAIN - The sensor is still calibrating * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. + * \return The raw gyroscope value in y-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double gyro_y = gps.get_gyro_y(); + * printf("gyro_y: %f\n", gyro_y); + * pros::delay(20); + * } + * } + * \endcode */ - virtual std::int32_t tare_rotation() const; + virtual double get_gyro_rate_y() const; /** - * Get the GPS's raw gyroscope values + * Get the GPS's raw gyroscope value in z-axis * * This function uses the following values of errno when an error state is * reached: @@ -297,10 +744,24 @@ class Gps : public Device { * ENODEV - The port cannot be configured as a GPS * EAGAIN - The sensor is still calibrating * - * \return The raw gyroscope values. If the operation failed, all the - * structure's members are filled with PROS_ERR_F and errno is set. - */ - virtual pros::gps_gyro_s_t get_gyro_rate() const; + * \return The raw gyroscope value in z-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double gyro_z = gps.get_gyro_z(); + * printf("gyro_z: %f\n", gyro_z); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_gyro_rate_z() const; /** * Get the GPS's raw accelerometer values @@ -311,31 +772,166 @@ class Gps : public Device { * ENODEV - The port cannot be configured as an GPS * EAGAIN - The sensor is still calibrating * - * \param port - * The V5 GPS's port number from 1-21 * \return The raw accelerometer values. If the operation failed, all the * structure's members are filled with PROS_ERR_F and errno is set. */ virtual pros::gps_accel_s_t get_accel() const; + /** + * Get the GPS's raw accelerometer value in x-axis + * + * 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 GPS + * EAGAIN - The sensor is still calibrating + * + * \return The raw accelerometer value in x-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double accel_x = gps.get_accel_x(); + * printf("accel_x: %f\n", accel_x); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_accel_x() const; + + /** + * Get the GPS's raw accelerometer value in y-axis + * + * 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 GPS + * EAGAIN - The sensor is still calibrating + * + * \return The raw accelerometer value in y-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double accel_y = gps.get_accel_y(); + * printf("accel_y: %f\n", accel_y); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_accel_y() const; + + /** + * Get the GPS's raw accelerometer value in z-axis + * + * 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 GPS + * EAGAIN - The sensor is still calibrating + * + * \return The raw accelerometer value in z-axis. If the operation fails, returns + * PROS_ERR_F and errno is set. + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * double accel_z = gps.get_accel_z(); + * printf("accel_z: %f\n", accel_z); + * pros::delay(20); + * } + * } + * \endcode + */ + virtual double get_accel_z() const; + /** * This is the overload for the << operator for printing to streams - * + * * Prints in format: * Gps [port: gps._port, x: (x position), y: (y position), heading: (gps heading), rotation: (gps rotation)] + * + * \b Example + * \code + * #define GPS_PORT 1 + * + * void opcontrol() { + * Gps gps(GPS_PORT); + * while(true) { + * std::cout << gps << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ friend std::ostream& operator<<(std::ostream& os, const pros::Gps& gps); -///@} + /** + * Gets a gps sensor that is plugged in to the brain + * + * \note The first time this function is called it returns the gps sensor at the lowest port + * If this function is called multiple times, it will cycle through all the ports. + * For example, if you have 1 gps sensor on the robot + * this function will always return a gps sensor object for that port. + * If you have 2 gps sensors, all the odd numered calls to this function will return objects + * for the lower port number, + * all the even number calls will return gps objects for the higher port number + * + * + * This functions uses the following values of errno when an error state is + * reached: + * ENODEV - No gps sensor is plugged into the brain + * + * \return A gps object corresponding to a port that a gps sensor is connected to the brain + * If no gps sensor is plugged in, it returns a gps sensor on port PROS_ERR_BYTE + * + */ + static Gps get_gps(); + ///@} }; // Gps Class namespace literals { - const pros::Gps operator""_gps(const unsigned long long int g); +/** + * Constructs a Gps object with the given port number + * + * \b Example + * \code + * using namespace literals; + * + * void opcontrol() { + * pros::Gps gps = 1_gps; + * while (true) { + * pos = gps.get_position(); + * screen_print(TEXT_MEDIUM, 1, "X Position: %4d, Y Position: %4d", pos.x, pos.y); + * delay(20); + * } + * } + * \endcode + */ +const pros::Gps operator""_gps(const unsigned long long int g); } // namespace literals +/// @brief +/// Alias for Gps is GPS for user convenience. using GPS = Gps; -} // namespace v5 -} // namespace pros +} // namespace v5 +} // namespace pros #endif diff --git a/include/pros/imu.h b/include/pros/imu.h index 48ec472..00ed164 100644 --- a/include/pros/imu.h +++ b/include/pros/imu.h @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the VEX Inertial sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/imu.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -44,13 +41,25 @@ namespace pros { * @brief Indicates IMU status. */ typedef enum imu_status_e { + E_IMU_STATUS_READY = 0, // IMU is connected but not currently calibrating /** The IMU is calibrating */ - E_IMU_STATUS_CALIBRATING = 0x01, + E_IMU_STATUS_CALIBRATING = 1, /** Used to indicate that an error state was reached in the imu_get_status function,\ not that the IMU is necessarily in an error state */ E_IMU_STATUS_ERROR = 0xFF, } imu_status_e_t; +typedef enum imu_orientation_e { + E_IMU_Z_UP = 0, // IMU has the Z axis UP (VEX Logo facing DOWN) + E_IMU_Z_DOWN = 1, // IMU has the Z axis DOWN (VEX Logo facing UP) + E_IMU_X_UP = 2, // IMU has the X axis UP + E_IMU_X_DOWN = 3, // IMU has the X axis DOWN + E_IMU_Y_UP = 4, // IMU has the Y axis UP + E_IMU_Y_DOWN = 5, // IMU has the Y axis DOWN + E_IMU_ORIENTATION_ERROR = 0xFF // NOTE: used for returning an error from the get_physical_orientation function, not + // that the IMU is necessarily in an error state +} imu_orientation_e_t; + /** * \struct quaternion_s_t */ @@ -430,8 +439,8 @@ imu_status_e_t imu_get_status(uint8_t port); * * void opcontrol() { * while (true) { - * imu_gyro_s_t gyro = imu_get_gyro_rate(IMU_PORT); - * printf("IMU gyro values: {x: %f, y: %f, z: %f}\n", gyro.x, gyro.y, gyro.z); + * int32_t val = imu_set_euler(IMU_PORT, {45, 60, 90}); + * printf("IMU : {gyro vals: %d}\n", val); * delay(20); * } * } @@ -937,6 +946,21 @@ int32_t imu_set_roll(uint8_t port, double target); */ int32_t imu_set_yaw(uint8_t port, double target); +/** + * Returns the physical orientation of the IMU + * + * 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 Inertial Sensor + * + * \param port + * The V5 Inertial Sensor port number from 1-21 + * \returns The orientation of the Inertial Sensor or PROS_ERR if an error occured. + * + */ +imu_orientation_e_t imu_get_physical_orientation(uint8_t port); + /** @} */ /** @} */ diff --git a/include/pros/imu.hpp b/include/pros/imu.hpp index 636ed36..4163d85 100644 --- a/include/pros/imu.hpp +++ b/include/pros/imu.hpp @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the VEX Inertial sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/imu.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -22,10 +19,10 @@ #define _PROS_IMU_HPP_ #include +#include -#include "pros/imu.h" #include "pros/device.hpp" -#include +#include "pros/imu.h" namespace pros { /** @@ -43,8 +40,9 @@ namespace pros { */ enum class ImuStatus { + ready = 0, /** The IMU is calibrating */ - calibrating = 0x01, + calibrating = 19, /** Used to indicate that an error state was reached in the imu_get_status function,\ not that the IMU is necessarily in an error state */ error = 0xFF, @@ -57,13 +55,60 @@ inline namespace v5 { class Imu : public Device { /** * \addtogroup cpp-imu - * ///@{ + * @{ */ - public: - explicit Imu(const std::uint8_t port) : Device(port, DeviceType::imu) {}; + /** + * Creates an Imu object for the given port + * + * 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). + * + * \param port + * The V5 Inertial Sensor port number from 1-21 + * + * \b Example + * \code + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Do something with the sensor data + * } + * } + * \endcode + */ + + + Imu(const std::uint8_t port) : Device(port, DeviceType::imu){}; + Imu(const Device& device) : Imu(device.get_port()){}; + + /** + * Gets a IMU sensor that is plugged in to the brain + * + * \note The first time this function is called it returns the IMU sensor at the lowest port + * If this function is called multiple times, it will cycle through all the ports. + * For example, if you have 1 IMU sensor on the robot + * this function will always return a IMU sensor object for that port. + * If you have 2 IMU sensors, all the odd numered calls to this function will return objects + * for the lower port number, + * all the even number calls will return IMU objects for the higher port number + * + * + * This functions uses the following values of errno when an error state is + * reached: + * ENODEV - No IMU sensor is plugged into the brain + * + * \return A IMU object corresponding to a port that a IMU sensor is connected to the brain + * If no IMU sensor is plugged in, it returns a IMU sensor on port PROS_ERR_BYTE + * + */ + static Imu get_imu(); /** * Calibrate IMU * @@ -83,6 +128,19 @@ class Imu : public Device { * Whether this function blocks during calibration. * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * // Block until calibration is complete + * imu.reset(true); + * } + * \endcode */ virtual std::int32_t reset(bool blocking = false) const; /** @@ -106,8 +164,48 @@ class Imu : public Device { * \param rate The data refresh interval in milliseconds * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the refresh rate to 5ms + * std::int32_t status = imu.set_data_rate(5); + * delay(20); + * + * // Check if the operation was successful + * if (status == PROS_ERR) { + * // Do something with the error + * } + * + * // Do something with the sensor data + * } + * } + * \endcode */ virtual std::int32_t set_data_rate(std::uint32_t rate) const; + + + /** + * Gets all IMU sensors. + * + * \return A vector of Imu sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector imu_all = pros::Imu::get_all_devices(); // All IMU sensors that are connected + * } + * \endcode + */ + + static std::vector get_all_devices(); + /** * Get the total number of degrees the Inertial Sensor has spun about the z-axis * @@ -125,6 +223,22 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return The degree value or PROS_ERR_F if the operation failed, setting * errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the total number of degrees the sensor has spun + * printf("Total rotation: %f\n", imu.get_rotation()); + * delay(20); + * } + * } + * \endcode */ virtual double get_rotation() const; /** @@ -145,6 +259,22 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return The degree value or PROS_ERR_F if the operation failed, setting * errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's heading + * printf("Heading: %f\n", imu.get_heading()); + * delay(20); + * } + * } + * \endcode */ virtual double get_heading() const; /** @@ -161,6 +291,23 @@ class Imu : public Device { * \return The quaternion representing the sensor's orientation. If the * operation failed, all the quaternion's members are filled with PROS_ERR_F and * errno is set. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's quaternion + * pros::quaternion_s_t quat = imu.get_quaternion(); + * cout << "Quaternion: " << quat.w << ", " << quat.x << ", " << quat.y << ", " << quat.z << endl; + * delay(20); + * } + * } + * \endcode */ virtual pros::quaternion_s_t get_quaternion() const; /** @@ -177,6 +324,23 @@ class Imu : public Device { * \return The Euler angles representing the sensor's orientation. If the * operation failed, all the structure's members are filled with PROS_ERR_F and * errno is set. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's Euler angles + * pros::euler_s_t euler = imu.get_euler(); + * cout << "Euler: " << euler.roll << ", " << euler.pitch << ", " << euler.yaw << endl; + * delay(20); + * } + * } + * \endcode */ virtual pros::euler_s_t get_euler() const; /** @@ -192,6 +356,22 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return The pitch angle, or PROS_ERR_F if the operation failed, setting * errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's pitch + * printf("Pitch: %f\n", imu.get_pitch()); + * delay(20); + * } + * } + * \endcode */ virtual double get_pitch() const; /** @@ -206,6 +386,22 @@ class Imu : public Device { * \param port * The V5 Inertial Sensor port number from 1-21 * \return The roll angle, or PROS_ERR_F if the operation failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's roll + * printf("Roll: %f\n", imu.get_roll()); + * delay(20); + * } + * } + * \endcode */ virtual double get_roll() const; /** @@ -220,6 +416,22 @@ class Imu : public Device { * \param port * The V5 Inertial Sensor port number from 1-21 * \return The yaw angle, or PROS_ERR_F if the operation failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's yaw + * printf("Yaw: %f\n", imu.get_yaw()); + * delay(20); + * } + * } + * \endcode */ virtual double get_yaw() const; /** @@ -235,6 +447,23 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return The raw gyroscope values. If the operation failed, all the * structure's members are filled with PROS_ERR_F and errno is set. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's raw gyroscope values + * pros::imu_gyro_s_t gyro = imu.get_gyro_rate(); + * cout << "Gyro: " << gyro.x << ", " << gyro.y << ", " << gyro.z << endl; + * delay(20); + * } + * } + * \endcode */ virtual pros::imu_gyro_s_t get_gyro_rate() const; /** @@ -250,6 +479,28 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's rotation value to 10 + * imu.set_rotation(10); + * delay(20); + * + * // Do something with sensor + * + * // Reset the sensor's rotation value to 0 + * imu.tare_rotation(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare_rotation() const; /** @@ -265,6 +516,28 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's heading value to 10 + * imu.set_heading(10); + * delay(20); + * + * // Do something with sensor + * + * // Reset the sensor's heading value to 0 + * imu.tare_heading(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare_heading() const; /** @@ -280,6 +553,28 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's pitch value to 10 + * imu.set_pitch(10); + * delay(20); + * + * // Do something with sensor + * + * // Reset the sensor's pitch value to 0 + * imu.tare_pitch(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare_pitch() const; /** @@ -295,6 +590,28 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's yaw value to 10 + * imu.set_yaw(10); + * delay(20); + * + * // Do something with sensor + * + * // Reset the sensor's yaw value to 0 + * imu.tare_yaw(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare_yaw() const; /** @@ -310,6 +627,28 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's roll value to 10 + * imu.set_roll(10); + * delay(20); + * + * // Do something with sensor + * + * // Reset the sensor's roll value to 0 + * imu.tare_roll(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare_roll() const; /** @@ -325,6 +664,22 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Reset all values of the sensor to 0 + * imu.tare(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare() const; /** @@ -340,6 +695,22 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Reset all euler values of the sensor to 0 + * imu.tare_euler(); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t tare_euler() const; /** @@ -358,6 +729,24 @@ class Imu : public Device { * Target value for the heading value to be set to * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's heading value to 10 + * imu.set_heading(10); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual std::int32_t set_heading(const double target) const; /** @@ -375,6 +764,24 @@ class Imu : public Device { * Target value for the rotation value to be set to * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's rotation value to 10 + * imu.set_rotation(10); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual std::int32_t set_rotation(const double target) const; /** @@ -393,6 +800,24 @@ class Imu : public Device { * Target value for yaw value to be set to * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's yaw value to 10 + * imu.set_yaw(10); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual std::int32_t set_yaw(const double target) const; /** @@ -410,6 +835,24 @@ class Imu : public Device { * Target value for the pitch value to be set to * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's pitch value to 10 + * imu.set_pitch(10); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual std::int32_t set_pitch(const double target) const; /** @@ -428,6 +871,24 @@ class Imu : public Device { * Target euler values for the euler values to be set to * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's roll value to 100 + * imu.set_roll(100); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual std::int32_t set_roll(const double target) const; /** @@ -446,6 +907,24 @@ class Imu : public Device { * Target euler values for the euler values to be set to * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Set the sensor's euler values to 50 + * imu.set_euler(50); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual std::int32_t set_euler(const pros::euler_s_t target) const; /** @@ -461,6 +940,25 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return The raw accelerometer values. If the operation failed, all the * structure's members are filled with PROS_ERR_F and errno is set. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's raw accelerometer values + * pros::imu_accel_s_t accel = imu.get_accel(); + * printf("x: %f, y: %f, z: %f\n", accel.x, accel.y, accel.z); + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual pros::imu_accel_s_t get_accel() const; /** @@ -476,6 +974,25 @@ class Imu : public Device { * The V5 Inertial Sensor port number from 1-21 * \return The Inertial Sensor's status code, or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Get the sensor's status + * pros::ImuStatus status = imu.get_status(); + * cout << "Status: " << status << endl; + * delay(20); + * + * // Do something with sensor + * } + * } + * \endcode */ virtual pros::ImuStatus get_status() const; /** @@ -483,15 +1000,52 @@ class Imu : public Device { * * \return true if the V5 Inertial Sensor is calibrating or false * false if it is not. + * + * \b Example + * \code + * + * #define IMU_PORT 1 + * + * void opcontrol() { + * pros::Imu imu(IMU_PORT); + * + * while (true) { + * // Calibrate the sensor + * imu.reset(); + * delay(20); + * + * // Check if the sensor is calibrating + * if (imu.is_calibrating()) { + * printf("Calibrating...\n"); + * } + * + * // Do something with sensor + * } + * } + * \endcode */ virtual bool is_calibrating() const; + /** + * Returns the physical orientation of the IMU + * + * 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 Inertial Sensor + * + * \param port + * The V5 Inertial Sensor port number from 1-21 + * \returns The physical orientation of the Inertial Sensor or PROS_ERR if an error occured. + * + */ + virtual imu_orientation_e_t get_physical_orientation() const; /** - * This is the overload for the << operator for printing to streams - * - * Prints in format(this below is all in one line with no new line): - * Imu [port: imu._port, rotation: (rotation), heading: (heading), - * pitch: (pitch angle), roll: (roll angle), yaw: (yaw angle), + * This is the overload for the << operator for printing to streams + * + * Prints in format(this below is all in one line with no new line): + * Imu [port: imu._port, rotation: (rotation), heading: (heading), + * pitch: (pitch angle), roll: (roll angle), yaw: (yaw angle), * gyro rate: {x,y,z}, get accel: {x,y,z}, calibrating: (calibrating boolean)] */ friend std::ostream& operator<<(std::ostream& os, const pros::Imu& imu); @@ -500,6 +1054,19 @@ class Imu : public Device { }; namespace literals { +/** + * Constructs a Imu from a literal ending in _imu via calling the constructor + * + * \return a pros::Imu for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Imu imu = 2_imu; //Makes an IMU object on port 2 + * } + * \endcode + */ const pros::Imu operator"" _imu(const unsigned long long int i); } // namespace literals diff --git a/include/pros/link.h b/include/pros/link.h index 8d40455..e4a1472 100644 --- a/include/pros/link.h +++ b/include/pros/link.h @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the robot to robot communications. * - * Visit https://pros.cs.purdue.edu/v5/api/c/link.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -41,29 +38,31 @@ namespace pros { /** * \enum link_type_e_t + * \brief Enum for the type of link (TX or RX) */ typedef enum link_type_e { - /// Indicating that the radio is a reciever. - E_LINK_RECIEVER = 0, - E_LINK_TRANSMITTER, - E_LINK_RX = E_LINK_RECIEVER, - E_LINK_TX = E_LINK_TRANSMITTER + E_LINK_RECIEVER = 0, ///< Indicates that the radio is a reciever. + E_LINK_TRANSMITTER, ///< Indicates that the link is a transmitter. + E_LINK_RX = E_LINK_RECIEVER, ///< Alias for E_LINK_RECIEVER + E_LINK_TX = E_LINK_TRANSMITTER ///< Alias for E_LINK_TRANSMITTER } link_type_e_t; #ifdef PROS_USE_SIMPLE_NAMES #ifdef __cplusplus -#define LINK_RECIEVER pros::E_LINK_RECIEVER +#define LINK_RECEIVER pros::E_LINK_RECEIVER #define LINK_TRANSMITTER pros::E_LINK_TRANSMITTER #define LINK_RX pros::E_LINK_RX #define LINK_TX pros::E_LINK_TX #else -#define LINK_RECIEVER E_LINK_RECIEVER +#define LINK_RECEIVER E_LINK_RECEIVER #define LINK_TRANSMITTER E_LINK_TRANSMITTER #define LINK_RX E_LINK_RX #define LINK_TX E_LINK_TX #endif #endif +/// @brief +/// The maximum size of a link buffer #define LINK_BUFFER_SIZE 512 #ifdef __cplusplus @@ -75,7 +74,7 @@ namespace c { * 1 to 2 second delay from when this function is called to when the link is initializes. * PROS currently only supports the use of one radio per brain. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -87,8 +86,8 @@ namespace c { * Unique link ID in the form of a string, needs to be different from other links in * the area. * \param type - * Indicates whether the radio link on the brain is a transmitter or reciever, - * with the transmitter having double the transmitting bandwidth as the recieving + * Indicates whether the radio link on the brain is a transmitter or receiver, + * with the transmitter having double the transmitting bandwidth as the receiving * end (1040 bytes/s vs 520 bytes/s). * * \return PROS_ERR if initialization fails, 1 if the initialization succeeds. @@ -111,7 +110,7 @@ uint32_t link_init(uint8_t port, const char* link_id, link_type_e_t type); * from when this function is called to when the link is initializes. * PROS currently only supports the use of one radio per brain. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -123,8 +122,8 @@ uint32_t link_init(uint8_t port, const char* link_id, link_type_e_t type); * Unique link ID in the form of a string, needs to be different from other links in * the area. * \param type - * Indicates whether the radio link on the brain is a transmitter or reciever, - * with the transmitter having double the transmitting bandwidth as the recieving + * Indicates whether the radio link on the brain is a transmitter or receiver, + * with the transmitter having double the transmitting bandwidth as the receiving * end (1040 bytes/s vs 520 bytes/s). * * \return PROS_ERR if initialization fails, 1 if the initialization succeeds. @@ -145,7 +144,7 @@ uint32_t link_init_override(uint8_t port, const char* link_id, link_type_e_t typ /** * Checks if a radio link on a port is active or not. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -175,7 +174,7 @@ bool link_connected(uint8_t port); /** * Returns the bytes of data available to be read * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -205,7 +204,7 @@ uint32_t link_raw_receivable_size(uint8_t port); /** * Returns the bytes of data available in transmission buffer. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -234,7 +233,7 @@ uint32_t link_raw_transmittable_size(uint8_t port); /** * Send raw serial data through vexlink. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -271,7 +270,7 @@ uint32_t link_transmit_raw(uint8_t port, void* data, uint16_t data_size); /** * Receive raw serial data through vexlink. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -308,7 +307,7 @@ uint32_t link_receive_raw(uint8_t port, void* dest, uint16_t data_size); /** * Send packeted message through vexlink, with a checksum and start byte. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -345,7 +344,7 @@ uint32_t link_transmit(uint8_t port, void* data, uint16_t data_size); /** * Receive packeted message through vexlink, with a checksum and start byte. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -383,7 +382,7 @@ uint32_t link_receive(uint8_t port, void* dest, uint16_t data_size); /** * Clear the receive buffer of the link, and discarding the data. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. diff --git a/include/pros/link.hpp b/include/pros/link.hpp index 8991d80..995d433 100644 --- a/include/pros/link.hpp +++ b/include/pros/link.hpp @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to robot to robot communications. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/link.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * Copyright (c) 2017-2021, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -30,7 +27,6 @@ namespace pros { /** * \ingroup cpp-link - * */ class Link : public Device { /** @@ -44,7 +40,7 @@ class Link : public Device { * Initializes a link on a radio port, with an indicated type. There might be a * 1 to 2 second delay from when this function is called to when the link is initializes. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -56,34 +52,46 @@ class Link : public Device { * Unique link ID in the form of a string, needs to be different from other links in * the area. * \param type - * Indicates whether the radio link on the brain is a transmitter or reciever, - * with the transmitter having double the transmitting bandwidth as the recieving + * Indicates whether the radio link on the brain is a transmitter or receiver, + * with the transmitter having double the transmitting bandwidth as the receiving * end (1040 bytes/s vs 520 bytes/s). * \param ov - * Indicates if the radio on the given port needs vexlink to override the controller radio + * Indicates if the radio on the given port needs vexlink to override the controller radio. Defualts to True. * * \return PROS_ERR if initialization fails, 1 if the initialization succeeds. + * + * \b Example: + * \code + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * \endcode */ - explicit Link(const std::uint8_t port, const std::string link_id, link_type_e_t type, bool ov = false); - + explicit Link(const std::uint8_t port, const std::string link_id, link_type_e_t type, bool ov = true); /** * Checks if a radio link on a port is active or not. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. * ENXIO - The sensor is still calibrating, or no link is connected via the radio. * * \return If a radio is connected to a port and it's connected to a link. + * + * \b Example: + * \code + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * if (link.connected()) { + * // do something + * } + * \endcode */ bool connected(); /** * Returns the bytes of data number of without protocol available to be read * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -91,26 +99,42 @@ class Link : public Device { * * \return PROS_ERR if port is not a link/radio, else the bytes available to be * read by the user. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * printf("Bytes available to read: %d", link.receivable_size()); + * } + * \endcode */ std::uint32_t raw_receivable_size(); /** * Returns the bytes of data available in transmission buffer. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. * ENXIO - The sensor is still calibrating, or no link is connected via the radio. * * \return PROS_ERR if port is not a link/radio, + * else the bytes available to be transmitted by the user. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * printf("Bytes available to transmit: %d", link.transmittable_size()); + * } */ std::uint32_t raw_transmittable_size(); /** * Send raw serial data through vexlink. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -126,13 +150,23 @@ class Link : public Device { * * \return PROS_ERR if port is not a link, and the successfully transmitted * data size if it succeeded. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * std::uint8_t data[4] = {0x01, 0x02, 0x03, 0x04}; + * link.transmit_raw(data, 4); + * } + * + * \endcode */ std::uint32_t transmit_raw(void* data, std::uint16_t data_size); /** * Receive raw serial data through vexlink. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -147,13 +181,22 @@ class Link : public Device { * * \return PROS_ERR if port is not a link, and the successfully received * data size if it succeeded. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * std::uint8_t data[4]; + * link.receive_raw(data, 4); + * } + * \endcode */ std::uint32_t receive_raw(void* dest, std::uint16_t data_size); /** * Send packeted message through vexlink, with a checksum and start byte. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -169,13 +212,22 @@ class Link : public Device { * * \return PROS_ERR if port is not a link, and the successfully transmitted * data size if it succeeded. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * std::uint8_t data[4] = {0x01, 0x02, 0x03, 0x04}; + * link.transmit(data, 4); + * } + * \endcode */ std::uint32_t transmit(void* data, std::uint16_t data_size); /** * Receive packeted message through vexlink, with a checksum and start byte. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. @@ -191,19 +243,36 @@ class Link : public Device { * * \return PROS_ERR if port is not a link, and the successfully received * data size if it succeeded. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * std::uint8_t data[4]; + * link.receive(data, 4); + * } + * \endcode */ std::uint32_t receive(void* dest, std::uint16_t data_size); /** * Clear the receive buffer of the link, and discarding the data. * - * This function uses the following values of errno when an error state is + * \note 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 a radio. * ENXIO - The sensor is still calibrating, or no link is connected via the radio. - + * * \return PROS_ERR if port is not a link, 1 if the operation succeeded. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Link link(1, "my_link", pros::E_LINK_TX); + * link.clear_receive_buf(); + * } + * \endcode */ std::uint32_t clear_receive_buf(); diff --git a/include/pros/llemu.h b/include/pros/llemu.h index cc18221..1f3ee4a 100644 --- a/include/pros/llemu.h +++ b/include/pros/llemu.h @@ -1,35 +1,23 @@ -/** - * \file pros/llemu.h - * \ingroup c-llemu - * - * Legacy LCD Emulator - * - * This file defines a high-level API for emulating the three-button, UART-based - * VEX LCD, containing a set of functions that facilitate the use of a software- - * emulated version of the classic VEX LCD module. - * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. - * - * This file should not be modified by users, since it gets replaced whenever - * a kernel upgrade occurs. - * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * \defgroup c-llemu LLEMU C API - */ - - #ifndef _PROS_LLEMU_H_ #define _PROS_LLEMU_H_ // TODO:? Should there be weak symbols for the C api in here as well? +#include "stdbool.h" #include "stdint.h" +/******************************************************************************/ +/** LLEMU Conditional Include **/ +/** **/ +/** When the libvgl versions of llemu.h is present, common.mk will **/ +/** define a macro which lets this file know that liblvgl's llemu.h is **/ +/** present. If it is, we conditionally include it so that it gets **/ +/** included into api.h. **/ +/******************************************************************************/ +#ifdef _PROS_INCLUDE_LIBLVGL_LLEMU_H +#include "liblvgl/llemu.h" +#endif + #ifdef __cplusplus extern "C" { namespace pros { @@ -54,7 +42,7 @@ namespace c { * \return True if the operation was successful, or false otherwise, setting * errno values as specified above. */ -bool __attribute__((weak)) lcd_print(int16_t line, const char* fmt, ...) { +bool __attribute__((weak)) lcd_print(__attribute__((unused)) int16_t line, __attribute__((unused)) const char* fmt, ...) { return false; } @@ -64,17 +52,4 @@ bool __attribute__((weak)) lcd_print(int16_t line, const char* fmt, ...) { } // extern "C" #endif//__cplusplus - -/******************************************************************************/ -/** LLEMU Conditional Include **/ -/** **/ -/** When the libvgl versions of llemu.h is present, common.mk will **/ -/** define a macro which lets this file know that liblvgl's llemu.h is **/ -/** present. If it is, we conditionally include it so that it gets **/ -/** included into api.h. **/ -/******************************************************************************/ -#ifdef _PROS_INCLUDE_LIBLVGL_LLEMU_H -#include "liblvgl/llemu.h" -#endif - #endif // _PROS_LLEMU_H_ diff --git a/include/pros/llemu.hpp b/include/pros/llemu.hpp index 2eeaf3d..6e86017 100644 --- a/include/pros/llemu.hpp +++ b/include/pros/llemu.hpp @@ -3,17 +3,15 @@ * \ingroup cpp-llemu * * Legacy LCD Emulator - * - * This file defines a high-level API for emulating the three-button, UART-based + * + * \details This file defines a high-level API for emulating the three-button, UART-based * VEX LCD, containing a set of functions that facilitate the use of a software- * emulated version of the classic VEX LCD module. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/adi.html to learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -26,6 +24,18 @@ #include #include +/******************************************************************************/ +/** LLEMU Conditional Include **/ +/** **/ +/** When the libvgl versions of llemu.hpp is present, common.mk will **/ +/** define a macro which lets this file know that liblvgl's llemu.hpp is **/ +/** present. If it is, we conditionally include it so that it gets **/ +/** included into api.h. **/ +/******************************************************************************/ +#ifdef _PROS_INCLUDE_LIBLVGL_LLEMU_HPP +#include "liblvgl/llemu.hpp" +#endif + /******************************************************************************/ /** LLEMU Weak Stubs **/ /** **/ @@ -33,11 +43,15 @@ /******************************************************************************/ namespace pros { - + /** * \ingroup cpp-llemu */ +#if defined(_PROS_KERNEL_SUPPRESS_LLEMU_WARNING) || defined(_PROS_INCLUDE_LIBLVGL_LLEMU_HPP) namespace lcd { +#else +namespace [[deprecated("Without liblvgl, LLEMU functions will not display anything. To install liblvgl run \"pros c install liblvgl\" in the PROS terminal.")]] lcd { +#endif #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" namespace { @@ -53,23 +67,33 @@ namespace lcd { using lcd_btn_cb_fn_t = void (*)(void); - - // Weak symbols that allow the main.cpp file to still work with LVGL - // decoupled from the kernel. - // For the Doxygen comments related to these functions, please see the file - // "liblvgl/llemu.hpp" in the liblvgl repo + /* + * These weak symbols allow the example main.cpp in to compile even when + * the liblvgl template is missing from the project. + * + * For documentation on these functions, please see the doxygen comments for + * these functions in the libvgl llemu headers. + */ + extern __attribute__((weak)) bool is_initialized(void); + extern __attribute__((weak)) bool initialize(void); + extern __attribute__((weak)) bool shutdown(void); extern __attribute__((weak)) bool set_text(std::int16_t line, std::string text); + extern __attribute__((weak)) bool clear(void); extern __attribute__((weak)) bool clear_line(std::int16_t line); - extern __attribute__((weak)) bool initialize(void); - extern __attribute__((weak)) std::uint8_t read_buttons(void); + // TODO: Text_Align is defined in liblvgl so this ain't going to compile for now. + // extern __attribute__((weak)) void set_text_align(Text_Align text_align); + extern __attribute__((weak)) void register_btn0_cb(lcd_btn_cb_fn_t cb); extern __attribute__((weak)) void register_btn1_cb(lcd_btn_cb_fn_t cb); - extern __attribute__((weak)) bool is_initialized(void); - - + extern __attribute__((weak)) void register_btn2_cb(lcd_btn_cb_fn_t cb); + extern __attribute__((weak)) std::uint8_t read_buttons(void); /** * \addtogroup cpp-llemu - * @{ + * @{ + */ + + /* + * Note: This template resides in this file since the */ /** @@ -84,19 +108,27 @@ namespace lcd { * The line on which to display the text [0-7] * \param fmt * Format string - * \param ... + * \param ...args * Optional list of arguments for the format string * * \return True if the operation was successful, or false otherwise, setting * errno values as specified above. + * + * \b Example + * \code + * #include "pros/llemu.hpp" + * + * void initialize() { + * pros::lcd::initialize(); + * pros::lcd::print(0, "My formatted text: %d!", 2); + * } + * \endcode */ template bool print(std::int16_t line, const char* fmt, Params... args) { return pros::c::lcd_print(line, fmt, convert_args(args)...); } - /// @} - #ifndef LCD_BTN_LEFT #define LCD_BTN_LEFT 4 #endif @@ -108,19 +140,8 @@ namespace lcd { #ifndef LCD_BTN_RIGHT #define LCD_BTN_RIGHT 1 #endif + /// @} } // namespace lcd } // namespace pros -/******************************************************************************/ -/** LLEMU Conditional Include **/ -/** **/ -/** When the libvgl versions of llemu.hpp is present, common.mk will **/ -/** define a macro which lets this file know that liblvgl's llemu.hpp is **/ -/** present. If it is, we conditionally include it so that it gets **/ -/** included into api.h. **/ -/******************************************************************************/ -#ifdef _PROS_INCLUDE_LIBLVGL_LLEMU_HPP -#include "liblvgl/llemu.hpp" -#endif - #endif // _PROS_LLEMU_HPP_ diff --git a/include/pros/misc.h b/include/pros/misc.h index ee4ec66..8123fbf 100644 --- a/include/pros/misc.h +++ b/include/pros/misc.h @@ -5,19 +5,16 @@ * Contains prototypes for miscellaneous functions pertaining to the controller, * battery, and competition control. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/controller.html to - * learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reservered. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup c-misc Miscellaneous C API * \note Additional example code for this module can be found in its [Tutorial.](@ref controller) */ @@ -41,9 +38,16 @@ /// \name V5 Competition //@{ -#define COMPETITION_DISABLED (1 << 0) +/*#define COMPETITION_DISABLED (1 << 0) #define COMPETITION_AUTONOMOUS (1 << 1) #define COMPETITION_CONNECTED (1 << 2) +#define COMPETITION_SYSTEM (1 << 3)*/ +typedef enum { + COMPETITION_DISABLED = 1 << 0, + COMPETITION_CONNECTED = 1 << 2, + COMPETITION_AUTONOMOUS = 1 << 1, + COMPETITION_SYSTEM = 1 << 3, +} competition_status; #ifdef __cplusplus extern "C" { @@ -57,7 +61,7 @@ namespace c { * * \return The competition control status as a mask of bits with * COMPETITION_{ENABLED,AUTONOMOUS,CONNECTED}. - * + * * \b Example * \code * void initialize() { @@ -70,17 +74,11 @@ namespace c { */ uint8_t competition_get_status(void); -#ifdef __cplusplus -} -} -} -#endif - /** * \fn competition_is_disabled() - * + * * \return True if the V5 Brain is disabled, false otherwise. - * + * * \b Example * \code * void my_task_fn(void* ignore) { @@ -88,17 +86,17 @@ uint8_t competition_get_status(void); * // Run competition tasks (like Lift Control or similar) * } * } - * + * * void initialize() { * task_t my_task = task_create(my_task_fn, NULL, TASK_PRIO_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "My Task"); * } * \endcode */ -#define competition_is_disabled() ((competition_get_status() & COMPETITION_DISABLED) != 0) +uint8_t competition_is_disabled(void); /** * \return True if the V5 Brain is connected to competition control, false otherwise. - * + * * \b Example * \code * void initialize() { @@ -109,11 +107,11 @@ uint8_t competition_get_status(void); * } * \endcode */ -#define competition_is_connected() ((competition_get_status() & COMPETITION_CONNECTED) != 0) +uint8_t competition_is_connected(void); /** * \return True if the V5 Brain is in autonomous mode, false otherwise. - * + * * \b Example * \code * void my_task_fn(void* ignore) { @@ -125,14 +123,46 @@ uint8_t competition_get_status(void); * // Run whatever code is desired to just execute in autonomous * } * } - * + * * void initialize() { * task_t my_task = task_create(my_task_fn, NULL, TASK_PRIO_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "My Task"); * } * \endcode */ -#define competition_is_autonomous() ((competition_get_status() & COMPETITION_AUTONOMOUS) != 0) +uint8_t competition_is_autonomous(void); +/** + * \return True if the V5 Brain is connected to VEXnet Field Controller, false otherwise. + * + * \b Example + * \code + * void initialize() { + * if (competition_is_field()) { + * // connected to VEXnet Field Controller + * } + * } + * \endcode + */ +uint8_t competition_is_field(void); + +/** + * \return True if the V5 Brain is connected to VEXnet Competition Switch, false otherwise. + * + * \b Example + * \code + * void initialize() { + * if (competition_is_switch()) { + * // connected to VEXnet Competition Switch + * } + * } + */ +uint8_t competition_is_switch(void); + +#ifdef __cplusplus +} +} +} +#endif ///@} /// \name V5 Controller @@ -146,22 +176,23 @@ namespace pros { * \enum */ typedef enum { - ///The master controller. + /// The master controller. E_CONTROLLER_MASTER = 0, - ///The partner controller. - E_CONTROLLER_PARTNER } controller_id_e_t; + /// The partner controller. + E_CONTROLLER_PARTNER +} controller_id_e_t; /** * \enum */ typedef enum { - ///The horizontal axis of the controller’s left analog stick. + /// The horizontal axis of the controller’s left analog stick. E_CONTROLLER_ANALOG_LEFT_X = 0, - ///The vertical axis of the controller’s left analog stick. + /// The vertical axis of the controller’s left analog stick. E_CONTROLLER_ANALOG_LEFT_Y, - ///The horizontal axis of the controller’s right analog stick. + /// The horizontal axis of the controller’s right analog stick. E_CONTROLLER_ANALOG_RIGHT_X, - ///The vertical axis of the controller’s right analog stick. + /// The vertical axis of the controller’s right analog stick. E_CONTROLLER_ANALOG_RIGHT_Y } controller_analog_e_t; @@ -169,30 +200,32 @@ typedef enum { * \enum */ typedef enum { - ///The first trigger on the left side of the controller. + /// The first trigger on the left side of the controller. E_CONTROLLER_DIGITAL_L1 = 6, - ///The second trigger on the left side of the controller. + /// The second trigger on the left side of the controller. E_CONTROLLER_DIGITAL_L2, - ///The first trigger on the right side of the controller. + /// The first trigger on the right side of the controller. E_CONTROLLER_DIGITAL_R1, - ///The second trigger on the right side of the controller. + /// The second trigger on the right side of the controller. E_CONTROLLER_DIGITAL_R2, - ///The up arrow on the left arrow pad of the controller. + /// The up arrow on the left arrow pad of the controller. E_CONTROLLER_DIGITAL_UP, - ///The down arrow on the left arrow pad of the controller. + /// The down arrow on the left arrow pad of the controller. E_CONTROLLER_DIGITAL_DOWN, - ///The left arrow on the left arrow pad of the controller. + /// The left arrow on the left arrow pad of the controller. E_CONTROLLER_DIGITAL_LEFT, - ///The right arrow on the left arrow pad of the controller. + /// The right arrow on the left arrow pad of the controller. E_CONTROLLER_DIGITAL_RIGHT, - ///The ‘X’ button on the right button pad of the controller. + /// The ‘X’ button on the right button pad of the controller. E_CONTROLLER_DIGITAL_X, - ///The ‘B’ button on the right button pad of the controller. + /// The ‘B’ button on the right button pad of the controller. E_CONTROLLER_DIGITAL_B, - ///The ‘Y’ button on the right button pad of the controller. + /// The ‘Y’ button on the right button pad of the controller. E_CONTROLLER_DIGITAL_Y, - ///The ‘A’ button on the right button pad of the controller. - E_CONTROLLER_DIGITAL_A + /// The ‘A’ button on the right button pad of the controller. + E_CONTROLLER_DIGITAL_A, + /// The power button on the front of the controller. + E_CONTROLLER_DIGITAL_POWER } controller_digital_e_t; #ifdef PROS_USE_SIMPLE_NAMES @@ -215,6 +248,7 @@ typedef enum { #define DIGITAL_B pros::E_CONTROLLER_DIGITAL_B #define DIGITAL_Y pros::E_CONTROLLER_DIGITAL_Y #define DIGITAL_A pros::E_CONTROLLER_DIGITAL_A +#define DIGITAL_POWER pros::E_CONTROLLER_DIGITAL_POWER #else #define CONTROLLER_MASTER E_CONTROLLER_MASTER #define CONTROLLER_PARTNER E_CONTROLLER_PARTNER @@ -238,26 +272,27 @@ typedef enum { #endif /** - * \def Given an id and a port, this macro sets the port variable based on the id and allows the mutex to take that port. - * + * \def Given an id and a port, this macro sets the port variable based on the id and allows the mutex to take that + * port. + * * \returns error (in the function/scope it's in) if the controller failed to connect or an invalid id is given. -*/ + */ #define CONTROLLER_PORT_MUTEX_TAKE(id, port) \ - switch (id) { \ - case E_CONTROLLER_MASTER: \ - port = V5_PORT_CONTROLLER_1; \ - break; \ - case E_CONTROLLER_PARTNER: \ - port = V5_PORT_CONTROLLER_2; \ - break; \ - default: \ - errno = EINVAL; \ - return PROS_ERR; \ - } \ - if (!internal_port_mutex_take(port)) { \ - errno = EACCES; \ - return PROS_ERR; \ - } \ + switch (id) { \ + case E_CONTROLLER_MASTER: \ + port = V5_PORT_CONTROLLER_1; \ + break; \ + case E_CONTROLLER_PARTNER: \ + port = V5_PORT_CONTROLLER_2; \ + break; \ + default: \ + errno = EINVAL; \ + return PROS_ERR; \ + } \ + if (!internal_port_mutex_take(port)) { \ + errno = EACCES; \ + return PROS_ERR; \ + } #ifdef __cplusplus namespace c { @@ -277,7 +312,7 @@ namespace c { * Must be one of CONTROLLER_MASTER or CONTROLLER_PARTNER * * \return 1 if the controller is connected, 0 otherwise - * + * * \b Example * \code * void initialize() { @@ -309,7 +344,7 @@ int32_t controller_is_connected(controller_id_e_t id); * * \return The current reading of the analog channel: [-127, 127]. * If the controller was not connected, then 0 is returned - * + * * \b Example * \code * void opcontrol() { @@ -336,7 +371,7 @@ int32_t controller_get_analog(controller_id_e_t id, controller_analog_e_t channe * Must be one of E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER * * \return The controller's battery capacity - * + * * \b Example * \code * void initialize() { @@ -360,7 +395,7 @@ int32_t controller_get_battery_capacity(controller_id_e_t id); * Must be one of E_CONTROLLER_MASTER or E_CONTROLLER_PARTNER * * \return The controller's battery level - * + * * \b Example * \code * void initialize() { @@ -388,7 +423,7 @@ int32_t controller_get_battery_level(controller_id_e_t id); * * \return 1 if the button on the controller is pressed. * If the controller was not connected, then 0 is returned - * + * * \b Example * \code * void opcontrol() { @@ -433,7 +468,7 @@ int32_t controller_get_digital(controller_id_e_t id, controller_digital_e_t butt * * \return 1 if the button on the controller is pressed and had not been pressed * the last time this function was called, 0 otherwise. - * + * * \b Example * \code * void opcontrol() { @@ -441,7 +476,7 @@ int32_t controller_get_digital(controller_id_e_t id, controller_digital_e_t butt * if (controller_get_digital_new_press(E_CONTROLLER_MASTER, E_CONTROLLER_DIGITAL_A)) { * // Toggle pneumatics or other similar actions * } - * + * * delay(2); * } * } @@ -449,6 +484,45 @@ int32_t controller_get_digital(controller_id_e_t id, controller_digital_e_t butt */ int32_t controller_get_digital_new_press(controller_id_e_t id, controller_digital_e_t button); +/** + * Returns a falling-edge case for a controller button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under + * the same circumstances, so only one task should call this function for any + * given button. E.g., Task A calls this function for buttons 1 and 2. + * Task B may call this function for button 3, but should not for buttons + * 1 or 2. A typical use-case for this function is to call inside opcontrol + * to detect new button releases, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is not pressed and had been + * pressed the last time this function was called, 0 otherwise. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (master.get_digital_new_release(pros::E_CONTROLLER_DIGITAL_A)) { + * // Toggle pneumatics or other similar actions + * } + * + * delay(2); + * } + * } + * \endcode + */ +int32_t controller_get_digital_new_release(controller_id_e_t id, controller_digital_e_t button); + /** * Sets text to the controller LCD screen. * @@ -476,7 +550,7 @@ int32_t controller_get_digital_new_press(controller_id_e_t id, controller_digita * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * void opcontrol() { @@ -519,7 +593,7 @@ int32_t controller_print(controller_id_e_t id, uint8_t line, uint8_t col, const * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * void opcontrol() { @@ -557,9 +631,14 @@ int32_t controller_set_text(controller_id_e_t id, uint8_t line, uint8_t col, con * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code + * void opcontrol() { + * controller_set_text(E_CONTROLLER_MASTER, 0, 0, "Example"); + * delay(100); + * controller_clear_line(E_CONTROLLER_MASTER, 0); + * } * \endcode */ int32_t controller_clear_line(controller_id_e_t id, uint8_t line); @@ -583,13 +662,13 @@ int32_t controller_clear_line(controller_id_e_t id, uint8_t line); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * void opcontrol() { * controller_set_text(E_CONTROLLER_MASTER, 0, 0, "Example"); * delay(100); - * controller_clear_line(E_CONTROLLER_MASTER, 0); + * controller_clear(E_CONTROLLER_MASTER); * } * \endcode */ @@ -617,7 +696,7 @@ int32_t controller_clear(controller_id_e_t id); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. - * + * * \b Example * \code * void opcontrol() { @@ -643,7 +722,7 @@ int32_t controller_rumble(controller_id_e_t id, const char* rumble_pattern); * EACCES - Another resource is currently trying to access the battery port. * * \return The current voltage of the battery - * + * * \b Example * \code * void initialize() { @@ -661,7 +740,7 @@ int32_t battery_get_voltage(void); * EACCES - Another resource is currently trying to access the battery port. * * \return The current current of the battery - * + * * \b Example * \code * void initialize() { @@ -679,7 +758,7 @@ int32_t battery_get_current(void); * EACCES - Another resource is currently trying to access the battery port. * * \return The current temperature of the battery - * + * * \b Example * \code * void initialize() { @@ -697,7 +776,7 @@ double battery_get_temperature(void); * EACCES - Another resource is currently trying to access the battery port. * * \return The current capacity of the battery - * + * * \b Example * \code * void initialize() { @@ -711,7 +790,7 @@ double battery_get_capacity(void); * Checks if the SD card is installed. * * \return 1 if the SD card is installed, 0 otherwise - * + * * \b Example * \code * void opcontrol() { @@ -721,6 +800,49 @@ double battery_get_capacity(void); */ int32_t usd_is_installed(void); +/** + * Lists the files in a directory specified by the path + * Puts the list of file names (NOT DIRECTORIES) into the buffer seperated by newlines + * + * This function uses the following values of errno when an error state is + * reached: + * + * EIO - Hard error occured in the low level disk I/O layer + * EINVAL - file or directory is invalid, or length is invalid + * EBUSY - THe physical drinve cannot work + * ENOENT - cannot find the path or file + * EINVAL - the path name format is invalid + * EACCES - Access denied or directory full + * EEXIST - Access denied + * EROFS - SD card is write protected + * ENXIO - drive number is invalid or not a FAT32 drive + * ENOBUFS - drive has no work area + * ENFILE - too many open files + * + * + * + * \note use a path of "\" to list the files in the main directory NOT "/usd/" + * DO NOT PREPEND YOUR PATHS WITH "/usd/" + * + * \return 1 on success or PROS_ERR on failure setting errno + * + * \b Example + * \code + * void opcontrol() { + * char* test = (char*) malloc(128); + * pros::c::usd_list_files("/", test, 128); + * pros::delay(200); + * printf("%s\n", test); //Prints the file names in the root directory seperated by newlines + * pros::delay(100); + * pros::c::usd_list_files("/test", test, 128); + * pros::delay(200); + * printf("%s\n", test); //Prints the names of files in the folder named test seperated by newlines + * pros::delay(100); + * } + * \endcode + */ +int32_t usd_list_files(const char* path, char* buffer, int32_t len); + /******************************************************************************/ /** Date and Time **/ /******************************************************************************/ @@ -729,16 +851,16 @@ extern const char* baked_date; extern const char* baked_time; typedef struct { - uint16_t year; // Year - 1980 + uint16_t year; // Year - 1980 uint8_t day; - uint8_t month; // 1 = January + uint8_t month; // 1 = January } date_s_t; typedef struct { uint8_t hour; uint8_t min; uint8_t sec; - uint8_t sec_hund; // hundredths of a second + uint8_t sec_hund; // hundredths of a second } time_s_t; ///@} @@ -747,7 +869,7 @@ typedef struct { #ifdef __cplusplus } -} // namespace pros +} // namespace pros } #endif diff --git a/include/pros/misc.hpp b/include/pros/misc.hpp index 68a7ae0..b0a115e 100644 --- a/include/pros/misc.hpp +++ b/include/pros/misc.hpp @@ -5,19 +5,16 @@ * Contains prototypes for miscellaneous functions pertaining to the controller, * battery, and competition control. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/controller.html to - * learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reservered. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-misc Miscellaneous C++ API * \note Additional example code for this module can be found in its [Tutorial.](@ref controller) */ @@ -25,16 +22,15 @@ #ifndef _PROS_MISC_HPP_ #define _PROS_MISC_HPP_ -#include "pros/misc.h" - #include #include +#include "pros/misc.h" + namespace pros { inline namespace v5 { /** * \ingroup cpp-misc - * */ class Controller { /** @@ -60,6 +56,16 @@ class Controller { * port. * * \return 1 if the controller is connected, 0 otherwise + * + * \b Example + * \code + * void status_display_controller(){ + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * if(!master.is_connected()) { + * pros::lcd::print(0, "Main controller is not connected!"); + * } + * } + * \endcode */ std::int32_t is_connected(void); @@ -78,6 +84,17 @@ class Controller { * * \return The current reading of the analog channel: [-127, 127]. * If the controller was not connected, then 0 is returned + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * motor_move(1, master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); + * delay(2); + * } + * } + * \endcode */ std::int32_t get_analog(controller_analog_e_t channel); @@ -90,6 +107,14 @@ class Controller { * port. * * \return The controller's battery capacity + * + * \b Example + * \code + * void initialize() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * printf("Battery Capacity: %d\n", master.get_battery_capacity()); + * } + * \endcode */ std::int32_t get_battery_capacity(void); @@ -102,6 +127,14 @@ class Controller { * port. * * \return The controller's battery level + * + * \b Example + * \code + * void initialize() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * printf("Battery Level: %d\n", master.get_battery_level()); + * } + * \endcode */ std::int32_t get_battery_level(void); @@ -120,6 +153,22 @@ class Controller { * * \return 1 if the button on the controller is pressed. * If the controller was not connected, then 0 is returned + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (master.get_digital(pros::E_CONTROLLER_DIGITAL_A)) { + * motor_set(1, 100); + * } + * else { + * motor_set(1, 0); + * } + * delay(2); + * } + * } + * \endcode */ std::int32_t get_digital(controller_digital_e_t button); @@ -145,9 +194,62 @@ class Controller { * * \return 1 if the button on the controller is pressed and had not been * pressed the last time this function was called, 0 otherwise. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (master.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_A)) { + * // Toggle pneumatics or other similar actions + * } + * + * delay(2); + * } + * } + * \endcode */ std::int32_t get_digital_new_press(controller_digital_e_t button); + /** + * Returns a falling-edge case for a controller button press. + * + * This function is not thread-safe. + * Multiple tasks polling a single button may return different results under + * the same circumstances, so only one task should call this function for any + * given button. E.g., Task A calls this function for buttons 1 and 2. + * Task B may call this function for button 3, but should not for buttons + * 1 or 2. A typical use-case for this function is to call inside opcontrol + * to detect new button releases, and not in any other tasks. + * + * This function uses the following values of errno when an error state is + * reached: + * EACCES - Another resource is currently trying to access the controller + * port. + * + * \param button + * The button to read. Must be one of + * DIGITAL_{RIGHT,DOWN,LEFT,UP,A,B,Y,X,R1,R2,L1,L2} + * + * \return 1 if the button on the controller is not pressed and had been + * pressed the last time this function was called, 0 otherwise. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (master.get_digital_new_release(pros::E_CONTROLLER_DIGITAL_A)) { + * // Toggle pneumatics or other similar actions + * } + * + * delay(2); + * } + * } + * \endcode + */ + std::int32_t get_digital_new_release(controller_digital_e_t button); + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" template @@ -181,6 +283,22 @@ class Controller { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * int count = 0; + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (!(count % 25)) { + * // Only print every 50ms, the controller text update rate is slow + * master.print(0, 0, "Counter: %d", count); + * } + * count++; + * delay(2); + * } + * } + * \endcode */ template std::int32_t print(std::uint8_t line, std::uint8_t col, const char* fmt, Params... args) { @@ -207,6 +325,22 @@ class Controller { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * int count = 0; + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (!(count % 25)) { + * // Only print every 50ms, the controller text update rate is slow + * master.set_text(0, 0, "Example text"); + * } + * count++; + * delay(2); + * } + * } + * \endcode */ std::int32_t set_text(std::uint8_t line, std::uint8_t col, const char* str); std::int32_t set_text(std::uint8_t line, std::uint8_t col, const std::string& str); @@ -227,6 +361,16 @@ class Controller { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * master.set_text(0, 0, "Example"); + * delay(100); + * master.clear_line(0); + * } + * \endcode */ std::int32_t clear_line(std::uint8_t line); @@ -248,6 +392,22 @@ class Controller { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * int count = 0; + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * while (true) { + * if (!(count % 25)) { + * // Only send every 50ms, the controller update rate is slow + * master.rumble(". - . -"); + * } + * count++; + * delay(2); + * } + * } + * \endcode */ std::int32_t rumble(const char* rumble_pattern); @@ -265,6 +425,16 @@ class Controller { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Controller master(pros::E_CONTROLLER_MASTER); + * master.set_text(0, 0, "Example"); + * delay(100); + * master.clear(); + * } + * \endcode */ std::int32_t clear(void); @@ -272,7 +442,7 @@ class Controller { controller_id_e_t _id; ///@} }; -} // namespace v5 +} // namespace v5 namespace battery { /** @@ -287,6 +457,13 @@ namespace battery { * EACCES - Another resource is currently trying to access the battery port. * * \return The current voltage of the battery + * + * \b Example + * \code + * void initialize() { + * printf("Battery Level: %.2f\n", get_capacity()); + * } + * \endcode */ double get_capacity(void); @@ -298,6 +475,13 @@ double get_capacity(void); * EACCES - Another resource is currently trying to access the battery port. * * \return The current current of the battery + * + * \b Example + * \code + * void initialize() { + * printf("Battery Current: %d\n", get_current()); + * } + * \endcode */ int32_t get_current(void); @@ -309,6 +493,13 @@ int32_t get_current(void); * EACCES - Another resource is currently trying to access the battery port. * * \return The current temperature of the battery + * + * \b Example + * \code + * void initialize() { + * printf("Battery's Temperature: %.2f\n", get_temperature()); + * } + * \endcode */ double get_temperature(void); @@ -320,6 +511,13 @@ double get_temperature(void); * EACCES - Another resource is currently trying to access the battery port. * * \return The current capacity of the battery + * + * \b Example + * \code + * void initialize() { + * printf("Battery's Voltage: %d\n", get_voltage()); + * } + * \endcode */ int32_t get_voltage(void); ///@} @@ -331,11 +529,27 @@ namespace competition { * * \return The competition control status as a mask of bits with * COMPETITION_{ENABLED,AUTONOMOUS,CONNECTED}. + * + * \b Example + * \code + * void status_display_task(){ + * if(!is_connected()) { + * pros::lcd::print(0, "V5 Brain is not connected!"); + * } + * if(is_autonomous()) { + * pros::lcd::print(0, "V5 Brain is in autonomous mode!"); + * } + * if(!is_disabled()) { + * pros::lcd::print(0, "V5 Brain is disabled!"); + * } + * \endcode */ std::uint8_t get_status(void); std::uint8_t is_autonomous(void); std::uint8_t is_connected(void); std::uint8_t is_disabled(void); +std::uint8_t is_field_control(void); +std::uint8_t is_competition_switch(void); } // namespace competition namespace usd { @@ -343,8 +557,58 @@ namespace usd { * Checks if the SD card is installed. * * \return 1 if the SD card is installed, 0 otherwise + * + * \b Example + * \code + * void opcontrol() { + * printf("%i", is_installed()); + * } + * \endcode */ std::int32_t is_installed(void); +/** + * Lists the files in a directory specified by the path + * Puts the list of file names (NOT DIRECTORIES) into the buffer seperated by newlines + * + * This function uses the following values of errno when an error state is + * reached: + * + * EIO - Hard error occured in the low level disk I/O layer + * EINVAL - file or directory is invalid, or length is invalid + * EBUSY - THe physical drinve cannot work + * ENOENT - cannot find the path or file + * EINVAL - the path name format is invalid + * EACCES - Access denied or directory full + * EEXIST - Access denied + * EROFS - SD card is write protected + * ENXIO - drive number is invalid or not a FAT32 drive + * ENOBUFS - drive has no work area + * ENFILE - too many open files + * + * + * + * \note use a path of "\" to list the files in the main directory NOT "/usd/" + * DO NOT PREPEND YOUR PATHS WITH "/usd/" + * + * \return 1 on success or PROS_ERR on failure setting errno + * + * \b Example + * \code + * void opcontrol() { + * char* test = (char*) malloc(128); + * pros::usd::list_files("/", test, 128); + * pros::delay(200); + * printf("%s\n", test); //Prints the file names in the root directory seperated by newlines + * pros::delay(100); + * pros::list_files("/test", test, 128); + * pros::delay(200); + * printf("%s\n", test); //Prints the names of files in the folder named test seperated by newlines + * pros::delay(100); + * } + * \endcode + */ + +std::int32_t list_files(const char* path, char* buffer, std::int32_t len); } // namespace usd } // namespace pros diff --git a/include/pros/motor_group.hpp b/include/pros/motor_group.hpp index 9b668a6..839a411 100644 --- a/include/pros/motor_group.hpp +++ b/include/pros/motor_group.hpp @@ -1,6 +1,6 @@ /** - * \file pros/motors.hpp - * \ingroup cpp-motors + * \file pros/motor_group.hpp + * \ingroup cpp-motor-group * * Contains prototypes for the V5 Motor-related functions. * @@ -10,13 +10,13 @@ * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * \defgroup cpp-motors Motors C++ API + * \defgroup cpp-motor-group Motors C++ API * \note Additional example code for this module can be found in its [Tutorial](@ref motors). */ @@ -37,64 +37,130 @@ namespace pros { inline namespace v5 { class MotorGroup : public virtual AbstractMotor { /** - * \addtogroup cpp-motors + * \addtogroup cpp-motor-group * @{ */ public: - explicit MotorGroup(const std::initializer_list, const pros::v5::MotorGears gearset = pros::v5::MotorGears::green, - const pros::v5::MotorUnits encoder_units = pros::v5::MotorUnits::degrees); - explicit MotorGroup(const std::vector& ports, const pros::v5::MotorGears gearset = pros::v5::MotorGears::green, - const pros::v5::MotorUnits encoder_units = pros::v5::MotorUnits::degrees); - std::int32_t operator=(const std::int32_t); - - /// \name Motor movement functions - /// These functions allow programmers to make motors move - ///@{ - /** - * Sets the voltage for the motor from -128 to 127. + * Constructs a new MotorGroup object. * - * This is designed to map easily to the input from the controller's analog - * stick for simple opcontrol use. The actual behavior of the motor is - * analogous to use of pros::Motor::move(), or motorSet from the PROS 2 API. + * 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 a motor + * + * \param port + * A initializer list of V5 port numbers from 1 to 21, or from -21 to -1 for reversed motors. + * A reversed motor will reverse the input or output movement functions and movement related + * telemetry in order to produce consistant behavior with non-reversed motors + * + * \param gearset = pros::v5::MotorGears::invalid + * Optional parameter for the gearset for the motor. + * Does not explicitly set the motor gearset if it is invalid or not specified + * + * \param encoder_units = pros::v5::MotorUnits::invalid + * Optional parameter for the encoder units of the motor + * Does not explicitly set the motor units if it is invalid or not specified + * + * \b Example + * \code + * void opcontrol() { + * MotorGroup first_mg({1, -2}); //Creates a motor on port 1 and a reversed motor on port 2 + * MotorGroup rotations_mg({4, 5}, pros::v5::MotorGears::blue, pros::v5::MotorUnits::rotations); + * //Creates a motor group on ports 4 and 5 with blue motors using rotaions as the encoder units + * } + * \endcode + */ + MotorGroup(const std::initializer_list, + const pros::v5::MotorGears gearset = pros::v5::MotorGears::invalid, + const pros::v5::MotorUnits encoder_units = pros::v5::MotorUnits::invalid); + /** + * Constructs a new MotorGroup object. * * 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 a motor * - * \param voltage - * The new motor voltage from -127 to 127 + * EDOM - The motor group is empty * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. + * \param port + * A initializer list of V5 port numbers from 1 to 21, or from -21 to -1 for reversed motors. + * A reversed motor will reverse the input or output movement functions and movement related + * telemetry in order to produce consistant behavior with non-reversed motors * - * \b Example + * \param gearset = pros::v5::MotorGears::invalid + * \param gearset = pros::v5::MotorGears::green + * Optional parameter for the gearset for the motor. + * Does not explicitly set the motor gearset if it is invalid or not specified + * + * \param encoder_units = pros::v5::MotorUnits::invalid + * Optional parameter for the encoder units of the motor + * Does not explicitly set the motor units if it is invalid or not specified + * + * \b Example * \code * void opcontrol() { - * pros::MotorGroup MotorGroup ({1}, E_MOTOR_GEARSET_18); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * pros::delay(2); - * } + * MotorGroup first_mg({1, -2}); //Creates a motor on port 1 and a reversed motor on port 2 with + * with both motors using the green gearset and degrees as the encoder units + * MotorGroup rotations_mg({4, 5}, pros::v5::MotorGears::blue, pros::v5::MotorUnits::rotations); + * //Creates a motor group on ports 4 and 5 with blue motors using rotaions as the encoder units + * } + * \endcode + */ + MotorGroup(const std::vector& ports, const pros::v5::MotorGears gearset = pros::v5::MotorGears::invalid, + const pros::v5::MotorUnits encoder_units = pros::v5::MotorUnits::invalid); + + /** + * Constructs a new MotorGroup object from an abstract motor. + * + * 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 a motor + * + * EDOM - The motor group is empty + * + * \param abstract_motor + * THe abstract motor to turn into a motor group + * Uses abstract_motor.get_port_all() to get the vector of ports + * + * + * \b Example + * \code + * void opcontrol() { + * MotorGroup first_mg({1, -2}); //Creates a motor on port 1 and a reversed motor on port 2 with + * with both motors using the green gearset and degrees as the encoder units + * AbstractMotor abs_mtr_group = first_mg; + * MotorGroup new_mg = (MotorGroup) abs_mtr_group; * } * \endcode */ - std::int32_t operator=(std::int32_t voltage) const; + + MotorGroup(AbstractMotor& motor_group); + + /// \name Motor movement functions + /// These functions allow programmers to make motors move + ///@{ /** - * Sets the voltage for the motor from -127 to 127. + * Sets the voltage for the motor group from -127 to 127. * * This is designed to map easily to the input from the controller's analog * stick for simple opcontrol use. The actual behavior of the motor is - * analogous to use of motor_move(), or motorSet() from the PROS 2 API. + * analogous to use of motor_move() * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * * \param voltage - * The new motor voltage from -127 to 127 + * The new voltage from -127 to 127 * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -102,10 +168,10 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void opcontrol() { - * pros::MotorGroup MotorGroup ({1}); + * pros::MotorGroup MotorGroup ({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor.move(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); + * mg.move(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); * pros::delay(2); * } * } @@ -114,7 +180,7 @@ class MotorGroup : public virtual AbstractMotor { std::int32_t move(std::int32_t voltage) const; /** - * Sets the target absolute position for the motor to move to. + * Sets the target absolute position for the motor group to move to. * * This movement is relative to the position of the motor when initialized or * the position when it was most recently reset with @@ -126,6 +192,7 @@ class MotorGroup : public virtual AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - the motor group has size 0 * * \param position * The absolute position to move to in the motor's encoder units @@ -138,19 +205,19 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); // Moves 100 units forward - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { - * // Continue running this loop as long as the motor is not within +-5 units of its goal + * pros::MotorGroup mg ({1,3}); + * mg.move_absolute(100, 100); // Moves 100 units forward + * while (!((mg.get_position() < 105) && (mg.get_position() > 95))) { + * // Continue running this loop as long as the mg is not within +-5 units of its goal * pros::delay(2); * } - * motor.move_absolute(100, 100); // This does not cause a movement - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { + * mg.move_absolute(100, 100); // This does not cause a movement + * while (!((mg.get_position() < 105) && (mg.get_position() > 95))) { * pros::delay(2); * } - * motor.tare_position(); - * motor.move_absolute(100, 100); // Moves 100 units forward - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { + * mg.tare_position(); + * mg.move_absolute(100, 100); // Moves 100 units forward + * while (!((mg.get_position() < 105) && (mg.get_position() > 95))) { * pros::delay(2); * } * } @@ -159,11 +226,11 @@ class MotorGroup : public virtual AbstractMotor { std::int32_t move_absolute(const double position, const std::int32_t velocity) const; /** - * Sets the relative target position for the motor to move to. + * Sets the relative target position for the motor group to move to. * - * This movement is relative to the current position of the motor as given in - * pros::Motor::motor_get_position(). Providing 10.0 as the position parameter - * would result in the motor moving clockwise 10 units, no matter what the + * This movement is relative to the current position of each motor as given in + * pros::MotorGroup::get_position(). Providing 10.0 as the position parameter + * would result in the motor moving 10 units, no matter what the * current position is. * * \note This function simply sets the target for the motor, it does not block @@ -172,6 +239,7 @@ class MotorGroup : public virtual AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * * \param position * The relative position to move to in the motor's encoder units @@ -184,14 +252,14 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * pros::Motor motor (1); - * motor.move_relative(100, 100); // Moves 100 units forward - * while (!((motor.get_position() < 105) && (motor.get_position() > 95))) { + * pros::MotorGroup mg({1,3}); + * mg.move_relative(100, 100); // Moves 100 units forward + * while (!((mg.get_position() < 105) && (mg.get_position() > 95))) { * // Continue running this loop as long as the motor is not within +-5 units of its goal * pros::delay(2); * } - * motor.move_relative(100, 100); // Also moves 100 units forward - * while (!((motor.get_position() < 205) && (motor.get_position() > 195))) { + * mg.move_relative(100, 100); // Also moves 100 units forward + * while (!((mg.get_position() < 205) && (mg.get_position() > 195))) { * pros::delay(2); * } * } @@ -200,7 +268,7 @@ class MotorGroup : public virtual AbstractMotor { std::int32_t move_relative(const double position, const std::int32_t velocity) const; /** - * Sets the velocity for the motor. + * Sets the velocity for the motor group. * * This velocity corresponds to different actual speeds depending on the * gearset used for the motor. This results in a range of +-100 for @@ -211,9 +279,10 @@ class MotorGroup : public virtual AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * * \param velocity - * The new motor velocity from -+-100, +-200, or +-600 depending on the + * The new velocity from +-100, +-200, or +-600 depending on the * motor's gearset * * \return 1 if the operation was successful or PROS_ERR if the operation @@ -222,24 +291,22 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * pros::Motor motor (1); - * motor.move_velocity(100); + * pros::MotorGroup mg({1,3}); + * mg.move_velocity(100); * pros::delay(1000); // Move at 100 RPM for 1 second - * motor.move_velocity(0); + * mg.move_velocity(0); * } * \endcode */ std::int32_t move_velocity(const std::int32_t velocity) const; /** - * Sets the output voltage for the motor from -12000 to 12000 in millivolts. + * Sets the output voltage for the motor group from -12000 to 12000 in millivolts. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 * \param voltage * The new voltage value from -12000 to 12000 * @@ -249,26 +316,85 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * motor.move_voltage(12000); + * mg.move_voltage(12000); * pros::delay(1000); // Move at max voltage for 1 second - * motor.move_voltage(0); + * mg.move_voltage(0); * } * \endcode */ std::int32_t move_voltage(const std::int32_t voltage) const; + /** + * Stops the motor group using the currently configured brake mode. + * + * This function sets motor velocity to zero, which will cause it to act + * according to the set brake mode. If brake mode is set to MOTOR_BRAKE_HOLD, + * this function may behave differently than calling move_absolute(0) + * or motor_move_relative(0). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * EDOM - The motor group is empty + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * Motor motor(1); + * mg.move_voltage(12000); + * pros::delay(1000); // Move at max voltage for 1 second + * motor.brake(); + * } + * \endcode + */ std::int32_t brake(void) const; + /** + * Changes the output velocity for a profiled movement (move_absolute or + * move_relative). This will have no effect if the motor group is not following + * a profiled movement. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \param velocity + * The new motor velocity from +-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::MotorGroup mg ({1,3}); + * mg.move_absolute(100, 100); + * pros::delay(100); + * mg.modify_profiled_velocity(0); // Stop the motor group early + * } + * \endcode + */ std::int32_t modify_profiled_velocity(const std::int32_t velocity) const; + /** - * Gets the target position set for the motor by the user, with a parameter + * Gets the target position set for a motor in the motor group, with a parameter * for the motor index. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * - * \param index The index of the motor to get the target position of. + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group * * \return The target position in its encoder units or PROS_ERR_F if the * operation failed, setting errno. @@ -276,22 +402,50 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); - * std::cout << "Motor Target: " << motor.get_target_position(); + * pros::MotorGroup mg({1,3}); + * mg.move_absolute(100, 100); + * // get the target position from motor at index 1. (port 3) + * std::cout << "Motor Target: " << mg.get_target_position(1); * // Prints 100 * } * \endcode */ double get_target_position(const std::uint8_t index) const; + + /** + * Gets a vector of the the target positions set for the motor group + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The Motor group is empty + * + * \return The a vector of the target positions in its encoder units or PROS_ERR_F if the + * operation failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::MotorGroup mg({1,3}); + * mg.move_absolute(100, 100); + * std::cout << "Motor Target: " << mg.get_target_position_all()[0]; + * // Prints 100 + * } + * \endcode + */ std::vector get_target_position_all(void) const; /** - * Gets the velocity commanded to the motor by the user. + * Gets the velocity commanded to the motor by the user at the index specified. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * EDOM - The motor group was empty + * + * \param index Optional parameter. + * The zero indexed index of the motor in the motor group * * \return The commanded motor velocity from +-100, +-200, or +-600, or * PROS_ERR if the operation failed, setting errno. @@ -299,18 +453,43 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg ({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor.move_velocity(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); - * std::cout << "Motor Velocity: " << motor.get_target_velocity(); - * // Prints the value of E_CONTROLLER_ANALOG_LEFT_Y + * mg.move_velocity(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); + * // get the target velocity from motor at index 1. (port 3) + * std::cout << "Motor Velocity: " << mg.get_target_velocity(1); * pros::delay(2); * } * } * \endcode */ std::int32_t get_target_velocity(const std::uint8_t index = 0) const; + + /** + * Gets a vector of the velocity commanded to the motor by the user + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - THe motor group is empty + * + * \return A vector of the commanded motor velocity from +-100, +-200, or +-600, or + * PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg ({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg.move_velocity(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); + * std::cout << "Motor Velocity: " << mg.get_target_velocity_all(); + * pros::delay(2); + * } + * } + * \endcode + */ std::vector get_target_velocity_all(void) const; ///@} @@ -320,335 +499,719 @@ class MotorGroup : public virtual AbstractMotor { ///@{ /** - * Gets the actual velocity of the motor. + * Gets the actual velocity of a motor in the motor group. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * + * EDOM - THe motor group is empty + * + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter. + * The zero indexed index of the motor in the motor group + * * \return The motor's actual velocity in RPM or PROS_ERR_F if the operation * failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * while (true) { - * motor = controller_get_analog(E_CONTROLLER_MASTER, E_CONTROLLER_ANALOG_LEFT_Y); - * printf("Actual velocity: %lf\n", motor.get_actual_velocity()); + * mg = controller_get_analog(E_CONTROLLER_MASTER, E_CONTROLLER_ANALOG_LEFT_Y); + * // get the actual velocity from motor at index 1. (port 3) + * printf("Actual velocity: %lf\n", mg.get_actual_velocity(1)); * pros::delay(2); * } * } * \endcode */ double get_actual_velocity(const std::uint8_t index = 0) const; - std::vector get_actual_velocity_all(void) const; /** - * Gets the current drawn by the motor in mA. + * Gets a vector of the the actual velocity of each motor the motor group. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \return The motor's current in mA or PROS_ERR if the operation failed, - * setting errno. + * EDOM - THe motor group is empty + * + * \return A vector of the each motor's actual velocity in RPM or PROS_ERR_F if the operation + * failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); + * pros::MotorGroup mg({1,3}); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Current Draw: " << motor.get_current_draw(); + * mg = controller_get_analog(E_CONTROLLER_MASTER, E_CONTROLLER_ANALOG_LEFT_Y); + * // get the target velocity from motor at index 1. (port 3) + * printf("Actual velocity: %lf\n", mg.get_actual_velocity(1)); * pros::delay(2); * } * } * \endcode */ - std::int32_t get_current_draw(const std::uint8_t index = 0) const; - std::vector get_current_draw_all(void) const; + std::vector get_actual_velocity_all(void) const; /** - * Gets the direction of movement for the motor. + * Gets the current drawn by a motor in the motor group in mA. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \return 1 for moving in the positive direction, -1 for moving in the - * negative direction, and PROS_ERR if the operation failed, setting errno. + * EDOM - The motor group is empty + * + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter. + * The zero indexed index of the motor in the motor group + * + * \return The motor's current in mA or PROS_ERR if the operation failed, + * setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Direction: " << motor.get_direction(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * //Print the current draw for the motor at index 1. (port 3) + * std::cout << "Motor Current Draw: " << mg.get_current_draw(1); * pros::delay(2); * } * } * \endcode */ - std::int32_t get_direction(const std::uint8_t index = 0) const; - std::vector get_direction_all(void) const; - + std::int32_t get_current_draw(const std::uint8_t index = 0) const; /** - * Gets the efficiency of the motor in percent. - * - * An efficiency of 100% means that the motor is moving electrically while - * drawing no electrical power, and an efficiency of 0% means that the motor - * is drawing power but not moving. + * Gets a vector of the current drawn each motor in the motor group in mA. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \return The motor's efficiency in percent or PROS_ERR_F if the operation - * failed, setting errno. + * EDOM - The motor group is empty + * + * + * \return A vector with each motor's current in mA or PROS_ERR if the operation failed, + * setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Efficiency: " << motor.get_efficiency(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Current Draw: " << mg.get_current_draw_all(); * pros::delay(2); * } * } * \endcode */ - double get_efficiency(const std::uint8_t index = 0) const; - std::vector get_efficiency_all(void) const; + std::vector get_current_draw_all(void) const; /** - * Gets the faults experienced by the motor. - * - * Compare this bitfield to the bitmasks in pros::motor_fault_e_t. + * Gets the direction of movement for a motor in the motor group. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 + * EDOM - The motor group is empty * - * \return A bitfield containing the motor's faults. + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 for moving in the positive direction, -1 for moving in the + * negative direction, and PROS_ERR if the operation failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Faults: " << motor.get_faults();pros::delay(2); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * //Print the motor direction for the motor at index 1. (port 3) + * std::cout << "Motor Direction: " << mg.get_direction(); + * pros::delay(2); * } * } * \endcode */ - std::uint32_t get_faults(const std::uint8_t index = 0) const; - std::vector get_faults_all(void) const; + std::int32_t get_direction(const std::uint8_t index = 0) const; /** - * Gets the flags set by the motor's operation. - * - * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. + * Gets a vector of the directions of movement for each motor in the motor group. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 + * EDOM - The motor group is empty * - * \return A bitfield containing the motor's flags. + * \return 1 for moving in the positive direction, -1 for moving in the + * negative direction, and PROS_ERR if the operation failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Faults: " << motor.get_faults(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Direction: " << mg.get_direction_all()[0]; * pros::delay(2); * } * } * \endcode */ - std::uint32_t get_flags(const std::uint8_t index = 0) const; - std::vector get_flags_all(void) const; + std::vector get_direction_all(void) const; /** - * Gets the absolute position of the motor in its encoder units. + * Gets the efficiency of a motor in the motor group in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \return The motor's absolute position in its encoder units or PROS_ERR_F - * if the operation failed, setting errno. + * EDOM - The motor group is empty + * + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's efficiency in percent or PROS_ERR_F if the operation + * failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Position: " << motor.get_position(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * //Prints the efficiency of the motor at index 1 (port 3) + * std::cout << "Motor Efficiency: " << mg.get_efficiency(1); * pros::delay(2); * } * } * \endcode */ - double get_position(const std::uint8_t index = 0) const; - std::vector get_position_all(void) const; - + double get_efficiency(const std::uint8_t index = 0) const; /** - * Gets the power drawn by the motor in Watts. + * Gets a vector of the efficiency of each motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \return The motor's power draw in Watts or PROS_ERR_F if the operation + * EDOM - THe motor group is empty + * + * \return A vector containing each motor's efficiency in percent or PROS_ERR_F if the operation * failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Power: " << motor.get_power(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Efficiency: " << mg.get_efficiency_all()[0]; * pros::delay(2); * } * } * \endcode */ - double get_power(const std::uint8_t index = 0) const; - std::vector get_power_all(void) const; + std::vector get_efficiency_all(void) const; + /** - * Gets the raw encoder count of the motor at a given timestamp. + * Gets the faults experienced by a motor in the motor group. + * + * Compare this bitfield to the bitmasks in pros::motor_fault_e_t. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \param[in] timestamp - * A pointer to a time in milliseconds for which the encoder count - * will be returned. If NULL, the timestamp at which the encoder - * count was read will not be supplied + * EDOM - The motor group is empty * - * \return The raw encoder count at the given timestamp or PROS_ERR if the - * operation failed. + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return A bitfield containing the motor's faults. * * \b Example * \code * void opcontrol() { - * std::uint32_t now = pros::millis(); - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Position: " << motor.get_raw_position(&now); - * pros::delay(2); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Faults: " << mg.get_faults(); + * pros::delay(2); * } * } * \endcode */ - std::int32_t get_raw_position(std::uint32_t* const timestamp, const std::uint8_t index = 0) const; - std::vector get_raw_position_all(std::uint32_t* const timestamp) const; - + std::uint32_t get_faults(const std::uint8_t index = 0) const; /** - * Gets the temperature of the motor in degrees Celsius. + * Gets a vector of the faults experienced by each motor in the motor group. + * + * Compare these bitfields to the bitmasks in pros::motor_fault_e_t. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor * - * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the - * operation failed, setting errno. + * EDOM - The motor group is empty + * + * + * \return A vector containing the bitfields containing each motor's faults. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Temperature: " << motor.get_temperature(); - * pros::delay(2); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Faults: " << mg.get_faults_all(); + * pros::delay(2); * } * } * \endcode */ - double get_temperature(const std::uint8_t index = 0) const; - std::vector get_temperature_all(void) const; + std::vector get_faults_all(void) const; /** - * Gets the torque generated by the motor in Newton Meters (Nm). + * Gets the flags set by a motor in the motor group's operation. + * + * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * - * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, - * setting errno. + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return A bitfield containing the motor's flags. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Torque: " << motor.get_torque(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Faults: " << mg.get_faults(1); * pros::delay(2); * } * } * \endcode */ - double get_torque(const std::uint8_t index = 0) const; - std::vector get_torque_all(void) const; + std::uint32_t get_flags(const std::uint8_t index = 0) const; + /** - * Gets the voltage delivered to the motor in millivolts. + * Gets a vector of the flags set by each motor in the motor groups's operation. + * + * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * - * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, - * setting errno. + * \return A bitfield containing the motor's flags. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Motor Voltage: " << motor.get_voltage(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Faults: " << mg.get_faults_all()[0]; * pros::delay(2); * } * } * \endcode */ - std::int32_t get_voltage(const std::uint8_t index = 0) const; - std::vector get_voltage_all(void) const; + std::vector get_flags_all(void) const; /** - * Checks if the motor is drawing over its current limit. + * Gets the absolute position of a motor in the motor group in its encoder units. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's absolute position in its encoder units or PROS_ERR_F + * if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Position: " << mg.get_position(1); + * pros::delay(2); + * } + * } + * \endcode + */ + double get_position(const std::uint8_t index = 0) const; + /** + * Gets a vector of the absolute position of each motor in its encoder units. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector of the motor's absolute position in its encoder units or PROS_ERR_F + * if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Position: " << mg.get_position_all(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_position_all(void) const; + + /** + * Gets the power drawn by a motor in the motor group in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's power draw in Watts or PROS_ERR_F if the operation + * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Power: " << mg.get_power(); + * pros::delay(2); + * } + * } + * \endcode + */ + double get_power(const std::uint8_t index = 0) const; + /** + * Gets a vector of the power drawn by each motor in the motor group in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector of each motor's power draw in Watts or PROS_ERR_F if the operation + * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Power: " << mg.get_power_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_power_all(void) const; + /** + * Gets the raw encoder count of a motor in the motor group at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * + * \param timestamp + * A pointer to a time in milliseconds for which the encoder count + * will be returned. If NULL, the timestamp at which the encoder + * count was read will not be supplied + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The raw encoder count at the given timestamp or PROS_ERR if the + * operation failed. + * + * \b Example + * \code + * void opcontrol() { + * std::uint32_t now = pros::millis(); + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Position: " << mg.get_raw_position(&now); + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t get_raw_position(std::uint32_t* const timestamp, const std::uint8_t index = 0) const; + /** + * Gets the raw encoder count of each motor at a given timestamp. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param timestamp + * A pointer to a time in milliseconds for which the encoder count + * will be returned. If NULL, the timestamp at which the encoder + * count was read will not be supplied + * + * \return A vector of each raw encoder count at the given timestamp or PROS_ERR if the + * operation failed. + * + * \b Example + * \code + * void opcontrol() { + * std::uint32_t now = pros::millis(); + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Position: " << mg.get_raw_position_all(&now)[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_raw_position_all(std::uint32_t* const timestamp) const; + + /** + * Gets the temperature of a motor in the motor group in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the + * operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Temperature: " << mg.get_temperature(); + * pros::delay(2); + * } + * } + * \endcode + */ + double get_temperature(const std::uint8_t index = 0) const; + /** + * Gets the temperature of each motor in the motor group in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector of each motor's temperature in degrees Celsius or PROS_ERR_F if the + * operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Temperature: " << mg.get_temperature_all()[1]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_temperature_all(void) const; + /** + * Gets the torque generated by a motor in the motor groupin Newton Meters (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Torque: " << mg.get_torque(); + * pros::delay(2); + * } + * } + * \endcode + */ + double get_torque(const std::uint8_t index = 0) const; + /** + * Gets a vector of the torque generated by each motor in Newton Meters (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector containing each motor's torque in Nm or PROS_ERR_F if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Torque: " << mg.get_torque(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_torque_all(void) const; + /** + * Gets the voltage delivered to a motor in the motor group in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Voltage: " << mg.get_voltage(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t get_voltage(const std::uint8_t index = 0) const; + /** + * Gets a vector of the voltage delivered to each motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector of each motor's voltage in mV or PROS_ERR_F if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Voltage: " << mg.get_voltage_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_voltage_all(void) const; + + /** + * Checks if a motor in the motor group is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group * * \return 1 if the motor's current limit is being exceeded and 0 if the * current limit is not exceeded, or PROS_ERR if the operation failed, setting @@ -657,206 +1220,816 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Is the motor over its current limit?: " << motor.is_over_current(); + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Is the motor over its current limit?: " << mg.is_over_current(); * pros::delay(2); * } * } * \endcode */ - std::int32_t is_over_current(const std::uint8_t index = 0) const; - std::vector is_over_current_all(void) const; - + std::int32_t is_over_current(const std::uint8_t index = 0) const; + /** + * Checks if each motor in the motor group is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector containing the following for each motor: 1 if the motor's current limit is being exceeded and 0 if + * the current limit is not exceeded, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Is the motor over its current limit?: " << motor.is_over_current_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector is_over_current_all(void) const; + + /** + * Gets the temperature limit flag for a motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 if the temperature limit is exceeded and 0 if the temperature is + * below the limit, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Is the motor over its temperature limit?: " << motor.is_over_temp(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t is_over_temp(const std::uint8_t index = 0) const; + /** + * Gets a vector with the temperature limit flag for each motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return 1 if the temperature limit is exceeded and 0 if the temperature is + * below the limit, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Is the motor over its temperature limit?: " << motor.is_over_temp(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector is_over_temp_all(void) const; + + ///@} + + /// \name Motor configuration functions + /// These functions allow programmers to configure the behavior of motors + ///@{ + + /** + * Gets the brake mode that was set for a motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return One of MotorBrake, according to what was set for the + * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << mg.get_brake_mode(); + * } + * \endcode + */ + MotorBrake get_brake_mode(const std::uint8_t index = 0) const; + /** + * Gets a vector with the brake mode that was set for each motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector with one of MotorBrake for each motor in the motor group, according to what was set for the + * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << mg.get_brake_mode_all()[0]; + * } + * \endcode + */ + std::vector get_brake_mode_all(void) const; + + /** + * Gets the current limit for a motor in the motor group in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's current limit in mA or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * while (true) { + * std::cout << "Motor Current Limit: " << mg.get_current_limit(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t get_current_limit(const std::uint8_t index = 0) const; + + /** + * Gets a vector of the current limit for each motor in the motor group in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector of each motor's current limit in mA or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * while (true) { + * std::cout << "Motor Current Limit: " << mg.get_current_limit_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_current_limit_all(void) const; + + /** + * Gets the encoder units that were set for a motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return One of MotorUnits according to what is set for the + * motor or E_MOTOR_ENCODER_INVALID if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg ({1,3}, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Encoder Units: " << mg.get_encoder_units(); + * } + * \endcode + */ + MotorUnits get_encoder_units(const std::uint8_t index = 0) const; + + /** + * Gets a vector of the encoder units that were set for each motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector with the following for each motor, One of MotorUnits according to what is set for the + * motor or E_MOTOR_ENCODER_INVALID if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg ({1,3}, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Encoder Units: " << mg.get_encoder_units_all()[0]; + * } + * \endcode + */ + std::vector get_encoder_units_all(void) const; + + /** + * Gets the gearset that was set for a motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + *\param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return One of MotorGears according to what is set for the motor, + * or pros::MotorGears::invalid if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg ({1,3}, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Gearing: " << mg.get_gearing(); + * } + * \endcode + */ + MotorGears get_gearing(const std::uint8_t index = 0) const; + /** + * Gets a vector of the gearset that was set for each motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * + * \return A vector with one of MotorGears according to what is set for the motor, + * or pros::MotorGears::invalid if the operation failed for each motor. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg ({1,3}, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Gearing: " << mg.get_gearing_all()[0]; + * } + * \endcode + */ + std::vector get_gearing_all(void) const; + + /** + * Gets a vector with all the port numbers in the motor group. + * A port will be negative if the motor in the motor group is reversed + * + * @return a vector with all the port numbers for the motor group + */ + std::vector get_port_all(void) const; + + /** + * Gets the voltage limit of a motor in the motor group set by the user. + * + * Default value is 0V, which means that there is no software limitation + * imposed on the voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + *\param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The motor's voltage limit in V or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * std::cout << "Motor Voltage Limit: " << mg.get_voltage_limit(1); + * } + * \endcode + */ + std::int32_t get_voltage_limit(const std::uint8_t index = 0) const; + + /** + * Gets a vector of the voltage limit of each motor in the motor group + * + * Default value is 0V, which means that there is no software limitation + * imposed on the voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The Motor group is empty + * + * \return The motor's voltage limit in V or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * std::cout << "Motor Voltage Limit: " << mg.get_voltage_limit_all()[0]; + * } + * \endcode + */ + std::vector get_voltage_limit_all(void) const; + + /** + * Gets the operation direction of a motor in the motor group as set by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + *\param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 if the motor has been reversed and 0 if the motor was not + * reversed, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * std::cout << "Is the motor reversed? " << motor.is_reversed(); + * // Prints "0" + * } + * \endcode + */ + std::int32_t is_reversed(const std::uint8_t index = 0) const; + /** + * Gets a vector of the operation direction of each motor in the motor group as set by the user. + * + * This function uses the following values of errno when an error state is + * reached: + * EDOM - The motor group is empty + * + * \return A vector conatining the following for each motor: 1 if the motor has been reversed and 0 if the motor was + * not reversed, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * std::cout << "Is the motor reversed? " << motor.is_reversed_all()[0]; + * // Prints "0" + * } + * \endcode + */ + std::vector is_reversed_all(void) const; + + /** + * Gets the type of a motor in the motor group. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + *\param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return One of MotorType according to the type of the motor, + * or pros::MotorType::invalid if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg ({1,3}, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Type: " << mg.get_type(); + * } + * \endcode + */ + MotorType get_type(const std::uint8_t index = 0) const; + /** + * Gets a vector of the type of each motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \return A vector with one of MotorType according to the type of the motor, + * or pros::MotorType::invalid if the operation failed for each motor. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg ({1,3}, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Type: " << mg.get_type_all()[0]; + * } + * \endcode + */ + std::vector get_type_all(void) const; + + /** + * Sets one of MotorBrake to a motor in the motor group. Works with the C enum + * and the C++ enum class. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param mode + * The MotorBrake to set for the motor + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_brake_mode(pros::MotorBrake::brake, 1); + * std::cout << "Brake Mode: " << mg.get_brake_mode(); + * } + * \endcode + */ + std::int32_t set_brake_mode(const MotorBrake mode, const std::uint8_t index = 0) const; + /** + * Sets one of MotorBrake to a motor in the motor group. Works with the C enum + * and the C++ enum class. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param mode + * The MotorBrake to set for the motor + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD, 1); + * std::cout << "Brake Mode: " << mg.get_brake_mode(); + * } + * \endcode + */ + std::int32_t set_brake_mode(const pros::motor_brake_mode_e_t mode, const std::uint8_t index = 0) const; + /** + * Sets one of MotorBrake all the motors in the motor group. Works with the C enum + * and the C++ enum class. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \param mode + * The MotorBrake to set for the motor + * + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_brake_mode_all(pros::MotorBrake:brake); + * std::cout << "Brake Mode: " << mg.get_brake_mode(); + * } + * \endcode + */ + std::int32_t set_brake_mode_all(const MotorBrake mode) const; + /** + * Sets one of MotorBrake to a motor in the motor group. Works with the C enum + * and the C++ enum class. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \param mode + * The MotorBrake to set for the motor + * + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_brake_mode_all(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << mg.get_brake_mode(); + * } + * \endcode + */ + std::int32_t set_brake_mode_all(const pros::motor_brake_mode_e_t mode) const; + /** + * Sets the current limit for one motor in the motor group in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param limit + * The new current limit in mA + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * + * mg.set_current_limit(1000); + * while (true) { + * mg = controller_get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * // The motor will reduce its output at 1000 mA instead of the default 2500 mA + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t set_current_limit(const std::int32_t limit, const std::uint8_t index = 0) const; /** - * Gets the temperature limit flag for the motor. + * Sets the current limit for every motor in the motor group in mA. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group was empty * - * \return 1 if the temperature limit is exceeded and 0 if the temperature is - * below the limit, or PROS_ERR if the operation failed, setting errno. + * \param limit + * The new current limit in mA + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code * void opcontrol() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * std::cout << "Is the motor over its temperature limit?: " << motor.is_over_temp(); - * pros::delay(2); + * + * mg.set_current_limit_all(1000); + * while (true) { + * mg = controller_get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * // The motor will reduce its output at 1000 mA instead of the default 2500 mA + * pros::delay(2); * } * } * \endcode */ - std::int32_t is_over_temp(const std::uint8_t index = 0) const; - std::vector is_over_temp_all(void) const; - - ///@} - - /// \name Motor configuration functions - /// These functions allow programmers to configure the behavior of motors - ///@{ - + std::int32_t set_current_limit_all(const std::int32_t limit) const; /** - * Gets the brake mode that was set for the motor. + * Sets one of MotorUnits for one motor in the motor group's motor encoder. Works with the C + * enum and the C++ enum class. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * - * \return One of Motor_Brake, according to what was set for the - * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + * \param units + * The new motor encoder units + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * motor.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); - * std::cout << "Brake Mode: " << motor.get_brake_mode(); + * pros::MotorGroup mg({1,3}); + * mg.set_encoder_units(E_MOTOR_ENCODER_DEGREES, 1); + * std::cout << "Encoder Units: " << mg.get_encoder_units(); * } * \endcode */ - MotorBrake get_brake_mode(const std::uint8_t index = 0) const; - std::vector get_brake_mode_all(void) const; - + std::int32_t set_encoder_units(const MotorUnits units, const std::uint8_t index = 0) const; /** - * Gets the current limit for the motor in mA. - * - * The default value is 2500 mA. + * Sets one of MotorUnits for one motor in the motor group's motor encoder. Works with the C + * enum and the C++ enum class. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * - * \return The motor's current limit in mA or PROS_ERR if the operation failed, - * setting errno. + * \param units + * The new motor encoder units + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code - * void opcontrol() { - * pros::Motor motor (1); - * while (true) { - * std::cout << "Motor Current Limit: " << motor.get_current_limit(); - * pros::delay(2); - * } + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_encoder_units(E_MOTOR_ENCODER_DEGREES, 1); + * std::cout << "Encoder Units: " << mg.get_encoder_units(); * } * \endcode */ - std::int32_t get_current_limit(const std::uint8_t index = 0) const; - std::vector get_current_limit_all(void) const; - + std::int32_t set_encoder_units(const pros::motor_encoder_units_e_t units, const std::uint8_t index = 0) const; /** - * Gets the encoder units that were set for the motor. + * Sets one of MotorUnits for every motor in the motor group's motor encoder. Works with the C + * enum and the C++ enum class. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * - * \return One of Motor_Units according to what is set for the - * motor or E_MOTOR_ENCODER_INVALID if the operation failed. + * \param units + * The new motor encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code * void initialize() { - * pros::Motor motor (1, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); - * std::cout << "Motor Encoder Units: " << motor.get_encoder_units(); + * pros::MotorGroup mg({1,3}); + * mg.set_encoder_units_all(E_MOTOR_ENCODER_DEGREES); + * std::cout << "Encoder Units: " << mg.get_encoder_units(); * } * \endcode */ - MotorUnits get_encoder_units(const std::uint8_t index = 0) const; - std::vector get_encoder_units_all(void) const; - + std::int32_t set_encoder_units_all(const MotorUnits units) const; /** - * Gets the gearset that was set for the motor. + * Sets one of MotorUnits for every motor in the motor group's motor encoder. Works with the C + * enum and the C++ enum class. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \param units + * The new motor encoder units * - * \return One of Motor_Gears according to what is set for the motor, - * or pros::Motor_Gears::invalid if the operation failed. + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code * void initialize() { - * pros::Motor motor (1, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); - * std::cout << "Motor Gearing: " << motor.get_gearing(); + * pros::MotorGroup mg({1,3}); + * mg.set_encoder_units_all(E_MOTOR_ENCODER_DEGREES); + * std::cout << "Encoder Units: " << mg.get_encoder_units(); * } * \endcode */ - MotorGears get_gearing(const std::uint8_t index = 0) const; - std::vector get_gearing_all(void) const; - - /** - * @brief Gets returns a vector with all the port numbers in the motor group. - * (ALL THE PORTS WILL BE POSITIVE) - * Use get_ports if you want to get the information on reversal. - * - * @return std::vector - */ - std::vector get_port_all(void) const; + std::int32_t set_encoder_units_all(const pros::motor_encoder_units_e_t units) const; /** - * Gets the voltage limit set by the user. - * - * Default value is 0V, which means that there is no software limitation - * imposed on the voltage. + * Sets one of the gear cartridge (red, green, blue) for one motor in the motor group. Usable with + * the C++ enum class and the C enum. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * E2BIG - The size of the vector mismatches the number of motors in the motor group * - * \return The motor's voltage limit in V or PROS_ERR if the operation failed, - * setting errno. + * \note If there are more motors than gearsets passed in, + * only the first n motors will have their gearsets changed where n is the number of gearsets passed in. + * If there are more gearsets passed in than motors, then the only the first m gearsets will be used, + * where m is the number of motors. In either case, errno will be set to E2BIG, but the operation still occurs + * + * + * \param gearset + * The new geatset of the motor + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * std::cout << "Motor Voltage Limit: " << motor.get_voltage_limit(); + * pros::MotorGroup mg({1,3}); + * mg.set_gearing(pros::MotorGears::blue, 1); + * std::cout << "Gearset: " << mg.get_gearing(); * } * \endcode */ - std::int32_t get_voltage_limit(const std::uint8_t index = 0) const; - std::vector get_voltage_limit_all(void) const; - + std::int32_t set_gearing(std::vector gearsets) const; /** - * Gets the operation direction of the motor as set by the user. + * Sets one of the gear cartridge (red, green, blue) for one motor in the motor group. Usable with + * the C++ enum class and the C enum. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * - * \return 1 if the motor has been reversed and 0 if the motor was not - * reversed, or PROS_ERR if the operation failed, setting errno. + * \param gearset + * The new geatset of the motor + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. * * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * std::cout << "Is the motor reversed? " << motor.is_reversed(); - * // Prints "0" + * pros::MotorGroup mg({1,3}); + * mg.set_gearing(E_MOTOR_GEARSET_06, 1); + * std::cout << "Gearset: " << mg.get_gearing(); * } * \endcode */ - std::int32_t is_reversed(const std::uint8_t index = 0) const; - std::vector is_reversed_all(void) const; + std::int32_t set_gearing(const pros::motor_gearset_e_t gearset, const std::uint8_t index = 0) const; /** - * Sets one of Motor_Brake to the motor. Works with the C enum - * and the C++ enum class. + * Sets the gear cartridge (red, green, blue) for each motor in the motor group by taking in a vector of the + * cartridges. Usable with the C++ enum class and the C enum. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * E2BIG - The size of the vector mismatches the number of motors in the motor group * - * \param mode - * The Motor_Brake to set for the motor + * \note If there are more motors than gearsets passed in, + * only the first n motors will have their gearsets changed where n is the number of gearsets passed in. + * If there are more gearsets passed in than motors, then the only the first m gearsets will be used, + * where m is the number of motors. In either case, errno will be set to E2BIG, but the operation still occurs + * + * \param gearset + * The a vector containing the new geatsets of the motors * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -864,56 +2037,54 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * motor.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); - * std::cout << "Brake Mode: " << motor.get_brake_mode(); + * pros::MotorGroup mg({1,3}); + * mg.set_gearing(pros::MotorGears::blue, 1); + * std::cout << "Gearset: " << mg.get_gearing(); * } * \endcode */ - std::int32_t set_brake_mode(const MotorBrake mode, const std::uint8_t index = 0) const; - std::int32_t set_brake_mode(const pros::motor_brake_mode_e_t mode, const std::uint8_t index = 0) const; - std::int32_t set_brake_mode_all(const MotorBrake mode) const; - std::int32_t set_brake_mode_all(const pros::motor_brake_mode_e_t mode) const; + std::int32_t set_gearing(std::vector gearsets) const; + /** - * Sets the current limit for the motor in mA. + * Sets one of the gear cartridge (red, green, blue) for one motor in the motor group. Usable with + * the C++ enum class and the C enum. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * - * \param limit - * The new current limit in mA + * \param gearset + * The new geatset of the motor + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. * * \b Example * \code - * void opcontrol() { - * pros::Motor motor (1); - * pros::Controller master (E_CONTROLLER_MASTER); - * - * motor.set_current_limit(1000); - * while (true) { - * motor = controller_get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * // The motor will reduce its output at 1000 mA instead of the default 2500 mA - * pros::delay(2); - * } + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_gearing(E_MOTOR_GEARSET_06, 1); + * std::cout << "Gearset: " << mg.get_gearing(); * } * \endcode */ - std::int32_t set_current_limit(const std::int32_t limit, const std::uint8_t index = 0) const; - std::int32_t set_current_limit_all(const std::int32_t limit) const; + std::int32_t set_gearing(const MotorGears gearset, const std::uint8_t index = 0) const; /** - * Sets one of Motor_Units for the motor encoder. Works with the C - * enum and the C++ enum class. + * Sets one of the gear cartridge (red, green, blue) for one motor in the motor group. Usable with + * the C++ enum class and the C enum. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * - * \param units - * The new motor encoder units + * \param gearset + * The new geatset of the motor * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -921,26 +2092,24 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * motor.set_encoder_units(E_MOTOR_ENCODER_DEGREES); - * std::cout << "Encoder Units: " << motor.get_encoder_units(); + * pros::MotorGroup mg({1,3}); + * mg.set_gearing_all(E_MOTOR_GEARSET_06); + * std::cout << "Gearset: " << mg.get_gearing(); * } * \endcode */ - std::int32_t set_encoder_units(const MotorUnits units, const std::uint8_t index = 0) const; - std::int32_t set_encoder_units(const pros::motor_encoder_units_e_t units, const std::uint8_t index = 0) const; - std::int32_t set_encoder_units_all(const MotorUnits units) const; - std::int32_t set_encoder_units_all(const pros::motor_encoder_units_e_t units) const; + std::int32_t set_gearing_all(const MotorGears gearset) const; /** - * Sets one of the gear cartridge (red, green, blue) for the motor. Usable with + * Sets one of the gear cartridge (red, green, blue) for every motor in the motor group. Usable with * the C++ enum class and the C enum. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty * * \param gearset - * The new motor gearset + * The new geatset of the motor * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -948,25 +2117,23 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * motor.set_gearing(E_MOTOR_GEARSET_06); - * std::cout << "Gearset: " << motor.get_gearing(); + * pros::MotorGroup mg({1,3}); + * mg.set_gearing_all(E_MOTOR_GEARSET_06); + * std::cout << "Gearset: " << mg.get_gearing(); * } * \endcode */ - std::int32_t set_gearing(const MotorGears gearset, const std::uint8_t index = 0) const; - std::int32_t set_gearing(const pros::motor_gearset_e_t gearset, const std::uint8_t index = 0) const; - std::int32_t set_gearing_all(const MotorGears gearset) const; std::int32_t set_gearing_all(const pros::motor_gearset_e_t gearset) const; /** - * Sets the reverse flag for the motor. + * sets the reversal for a motor in the motor group. * * This will invert its movements and the values returned for its position. * * This function uses the following values of errno when an error state is * reached: - * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * * \param reverse * True reverses the motor, false is default @@ -977,48 +2144,112 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void initialize() { - * pros::Motor motor (1); - * motor.set_reversed(true); - * std::cout << "Is this motor reversed? " << motor.is_reversed(); + * pros::MotorGroup mg({1,3}); + * //reverse the motor at index 1 (port 3) + * mg.set_reversed(true, 1); + * std::cout << "Is this motor reversed? " << motor.is_reversed(1); + * pros::delay(100); + * // unreverse the motor at index 1 (port 3) + * mg.set_reversed(false, 1); + * std::cout << "Is this motor reversed? " << motor.is_reversed(1); * } * \endcode */ std::int32_t set_reversed(const bool reverse, const std::uint8_t index = 0); + /** + * Sets the reversal for all the motors in the motor group. + * + * This will invert its movements and the values returned for its position. + * + * This function uses the following values of errno when an error state is + * reached: + * EDOM - The motor group is empty + * + * \param reverse + * True reverses the motor, false is default + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::MotorGroup mg({1,3}); + * mg.set_reversed_all(true); + * std::cout << "Is this motor reversed? " << motor.is_reversed(); + * } + * \endcode + */ std::int32_t set_reversed_all(const bool reverse); /** - * Sets the voltage limit for the motor in Volts. + * Sets the voltage limit for a motor in the motor group in millivolts. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * * \param limit * The new voltage limit in Volts * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. * * \b Example * \code * void autonomous() { - * pros::Motor motor (1); + * pros::MotorGroup mg({1,3}); * pros::Controller master (E_CONTROLLER_MASTER); * - * motor.set_voltage_limit(10000); + * mg.set_voltage_limit(10000, 1); * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * // The motor will not output more than 10 V + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * // The motor on at index 1 (port 3) will not output more than 10 V * pros::delay(2); * } * } * \endcode */ std::int32_t set_voltage_limit(const std::int32_t limit, const std::uint8_t index = 0) const; + + /** + * Sets the voltage limit for every motor in the motor group in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \param limit + * The new voltage limit in Volts + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::MotorGroup mg({1,3}); + * pros::Controller master (E_CONTROLLER_MASTER); + * + * mg.set_voltage_limit_all(10000); + * while (true) { + * mg = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * // The motor will not output more than 10 V + * pros::delay(2); + * } + * } + * \endcode + */ std::int32_t set_voltage_limit_all(const std::int32_t limit) const; /** - * Sets the position for the motor in its encoder units. + * Sets the position for a motor in the motor group in its encoder units. * * This will be the future reference point for the motor's "absolute" * position. @@ -1026,9 +2257,13 @@ class MotorGroup : public virtual AbstractMotor { * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() * * \param position * The new reference position in its encoder units + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -1036,25 +2271,60 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); // Moves 100 units forward - * motor.move_absolute(100, 100); // This does not cause a movement - * - * motor.set_zero_position(80); - * motor.move_absolute(100, 100); // Moves 80 units forward + * pros::MotorGroup mg({1,3}); + * mg.move_absolute(100, 100); // Moves 100 units forward + * mg.move_absolute(100, 100); // This does not cause a movement + * mg.set_zero_position(80); + * mg.set_zero_position(80, 1); + * mg.move_absolute(100, 100); // Moves 80 units forward * } * \endcode * */ std::int32_t set_zero_position(const double position, const std::uint8_t index = 0) const; + /** + * Sets the position for every motor in the motor group in its encoder units. + * + * This will be the future reference point for the motor's "absolute" + * position. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * + * \param position + * The new reference position in its encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::MotorGroup mg({1,3}); + * mg.move_absolute(100, 100); // Moves 100 units forward + * mg.move_absolute(100, 100); // This does not cause a movement + * + * mg.set_zero_position_all(80); + * mg.move_absolute(100, 100); // Moves 80 units forward + * } + * \endcode + * + */ std::int32_t set_zero_position_all(const double position) const; /** - * Sets the "absolute" zero position of the motor to its current position. + * Sets the "absolute" zero position of a motor in the motor group to its current position. * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EDOM - The motor group is empty + * EOVERFLOW - The index is greater than or equal to MotorGroup::size() + * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -1062,58 +2332,89 @@ class MotorGroup : public virtual AbstractMotor { * \b Example * \code * void autonomous() { - * pros::Motor motor (1); - * motor.move_absolute(100, 100); // Moves 100 units forward - * motor.move_absolute(100, 100); // This does not cause a movement + * pros::MotorGroup mg({1,3}); + * mg.move_absolute(100, 100); // Moves 100 units forward + * mg.move_absolute(100, 100); // This does not cause a movement * - * motor.tare_position(); - * motor.move_absolute(100, 100); // Moves 100 units forward + * mg.tare_position(); + * mg.tare_position(1); + * + * mg.move_absolute(100, 100); // Moves 100 units forward * } * \endcode */ std::int32_t tare_position(const std::uint8_t index = 0) const; + + /** + * Sets the "absolute" zero position of every motor in the motor group to its current position. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::MotorGroup mg({1,3}); + * mg.move_absolute(100, 100); // Moves 100 units forward + * mg.move_absolute(100, 100); // This does not cause a movement + * mg.tare_position_all(); + * mg.move_absolute(100, 100); // Moves 100 units forward + * } + * \endcode + */ std::int32_t tare_position_all(void) const; /** - * @brief Returns the number of objects + * Returns the number of motors in the motor group * - * @return std::int8_t + * \return the number of motors in the motor group */ std::int8_t size(void) const; - std::int8_t get_port(const std::uint8_t index = 0) const; /** - * @brief Appends the other motor group reference to this motor group + * Gets the port of a motor in the motor group via index * + * \param index Optional parameter, 0 by default. + * The zero indexed index of the motor in the motor group + * + * \return The port of the motor at the specified index. + * The return value is negative if the corresponding motor is reversed */ - void operator+=(MotorGroup&); + std::int8_t get_port(const std::uint8_t index = 0) const; /** - * @brief Appends the other motor group reference to this motor group + * Appends all the motors in the other motor group reference to this motor group + * + * Maintains the order of the other motor group * */ - void append(MotorGroup&); + void operator+=(AbstractMotor&); /** - * @brief Removes the port (and it's reversed ) + * Appends all the motors in the other motor group reference to this motor group + * + * Maintains the order of the other motor group * - * @param port */ - void erase_port(std::int8_t port); + void append(AbstractMotor&); /** - * This is the overload for the << operator for printing to streams + * Removes the all motors on the port (regardless of reversal) from the motor group + * + * \param port The port to remove from the motor group * - * Prints in format: - * Motor [port: (motor port), brake mode: (brake mode), current draw: (current draw), - * current limit: (current limit), direction: (direction), efficiency: (efficiency), - * encoder units: (encoder units), gearing: (gearing), is over temp: (over temp), - * position: (position), reversed: (reversed boolean), temperature: (temperature), - * torque: (torque), voltage: (voltage)] */ - friend std::ostream& operator<<(std::ostream& os, pros::MotorGroup& motor); + void erase_port(std::int8_t port); + ///@} private: + /** + * The ordered vector of ports used by the motor group + */ std::vector _ports; mutable pros::Mutex _MotorGroup_mutex; }; diff --git a/include/pros/motors.h b/include/pros/motors.h index 0ef6d3c..bcf3825 100644 --- a/include/pros/motors.h +++ b/include/pros/motors.h @@ -4,13 +4,10 @@ * * Contains prototypes for the V5 Motor-related functions. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/motors.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -50,17 +47,19 @@ namespace c { * * This is designed to map easily to the input from the controller's analog * stick for simple opcontrol use. The actual behavior of the motor is analogous - * to use of motor_move_voltage(), or motorSet() from the PROS 2 API. + * to use of motor_move_voltage(). * * \note This function will not respect brake modes, and simply sets the voltage to the desired value. * + * \note A negative port will negate the input voltage + * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param voltage * The new motor voltage from -127 to 127 * @@ -89,18 +88,22 @@ int32_t motor_move(int8_t port, int32_t voltage); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. * * \b Example - * \code {.language-id} - * code + * \code + * void autonomous() { + * motor_move(1, 127); + * delay(1000); + * motor_break(1); + * } * \endcode */ int32_t motor_brake(int8_t port); @@ -114,13 +117,15 @@ int32_t motor_brake(int8_t port); * \note This function simply sets the target for the motor, it does not block program * execution until the movement finishes. The example code shows how to block until a movement is finished. * + * \note A negative port number will negate the target position + * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21. + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param position * The absolute position to move to in the motor's encoder units * \param velocity @@ -164,13 +169,15 @@ int32_t motor_move_absolute(int8_t port, double position, const int32_t velocity * program execution until the movement finishes. The example code shows how to * block until a movement is finished. * + * \note A negative port will negate the target position + * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param position * The relative position to move to in the motor's encoder units * \param velocity @@ -206,13 +213,15 @@ int32_t motor_move_relative(int8_t port, double position, const int32_t velocity * is held with PID to ensure consistent speed, as opposed to setting the * motor's voltage. * + * \note A negative port will negate the velocity + * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param velocity * The new motor velocity from +-100, +-200, or +-600 depending on the * motor's gearset @@ -232,18 +241,20 @@ int32_t motor_move_relative(int8_t port, double position, const int32_t velocity int32_t motor_move_velocity(int8_t port, const int32_t velocity); /** - * Sets the output voltage for the motor from -12000 to 12000 in millivolts + * Sets the output voltage for the motor from -12000 to 12000 in millivolts. * + * \note A negative port negates the voltage + * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \note This function will not respect brake modes, and simply sets the * voltage to the desired value. * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param voltage * The new voltage value from -12000 to 12000 * @@ -266,13 +277,15 @@ int32_t motor_move_voltage(int8_t port, const int32_t voltage); * motor_move_relative). This will have no effect if the motor is not following * a profiled movement. * + * \note A negative port negates the velocity + * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param velocity * The new motor velocity from +-100, +-200, or +-600 depending on the * motor's gearset @@ -294,13 +307,15 @@ int32_t motor_modify_profiled_velocity(int8_t port, const int32_t velocity); /** * Gets the target position set for the motor by the user. * + * \note A negative port negates the return 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The target position in its encoder units or PROS_ERR_F if the * operation failed, setting errno. @@ -319,13 +334,15 @@ double motor_get_target_position(int8_t port); /** * Gets the velocity commanded to the motor by the user. * + * \note A negative port negates the return 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The commanded motor velocity from +-100, +-200, or +-600, or PROS_ERR * if the operation failed, setting errno. @@ -352,13 +369,15 @@ int32_t motor_get_target_velocity(int8_t port); /** * Gets the actual velocity of the motor. * + * \note A negative port negates the return 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's actual velocity in RPM or PROS_ERR_F if the operation * failed, setting errno. @@ -381,11 +400,11 @@ double motor_get_actual_velocity(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's current in mA or PROS_ERR if the operation failed, * setting errno. @@ -406,13 +425,15 @@ int32_t motor_get_current_draw(int8_t port); /** * Gets the direction of movement for the motor. * + * \note A negative port number negates the return 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return 1 for moving in the positive direction, -1 for moving in the * negative direction, or PROS_ERR if the operation failed, setting errno. @@ -439,11 +460,11 @@ int32_t motor_get_direction(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's efficiency in percent or PROS_ERR_F if the operation * failed, setting errno. @@ -466,11 +487,11 @@ double motor_get_efficiency(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return 1 if the motor's current limit is being exceeded and 0 if the current * limit is not exceeded, or PROS_ERR if the operation failed, setting errno. @@ -493,11 +514,11 @@ int32_t motor_is_over_current(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return 1 if the temperature limit is exceeded and 0 if the the temperature * is below the limit, or PROS_ERR if the operation failed, setting errno. @@ -515,31 +536,6 @@ int32_t motor_is_over_current(int8_t port); */ int32_t motor_is_over_temp(int8_t port); -/** - * Checks if the motor is stopped. - * - * \note Although this function forwards data from the motor, the motor - * presently does not provide any value. This function returns PROS_ERR with - * errno set to ENOSYS. - * - * \param port - * The V5 port number from 1-21 - * - * \return 1 if the motor is not moving, 0 if the motor is moving, or PROS_ERR - * if the operation failed, setting errno - * - * \b Example - * \code - * void opcontrol() { - * while (true) { - * motor_move(1, controller_get_analog(E_CONTROLLER_MASTER, E_CONTROLLER_ANALOG_LEFT_Y)); - * printf("Is the motor stopped? %d\n", motor_is_stopped(1)); - * delay(2); - * } - * } - * \endcode - */ -int32_t motor_is_stopped(int8_t port); #ifdef __cplusplus @@ -654,11 +650,11 @@ namespace c { * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return A bitfield containing the motor's flags. * @@ -678,13 +674,15 @@ uint32_t motor_get_flags(int8_t port); /** * Gets the raw encoder count of the motor at a given timestamp. * + * \note A negative port value negates the return 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param[in] timestamp * A pointer to a time in milliseconds for which the encoder count * will be returned. If NULL, the timestamp at which the encoder @@ -710,13 +708,15 @@ int32_t motor_get_raw_position(int8_t port, uint32_t* const timestamp); /** * Gets the absolute position of the motor in its encoder units. * + * \note A negative port value negates the return 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's absolute position in its encoder units or PROS_ERR_F * if the operation failed, setting errno. @@ -739,11 +739,11 @@ double motor_get_position(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's power draw in Watts or PROS_ERR_F if the operation * failed, setting errno. @@ -767,11 +767,11 @@ double motor_get_power(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the * operation failed, setting errno. @@ -794,11 +794,11 @@ double motor_get_temperature(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, * setting errno. @@ -825,7 +825,7 @@ double motor_get_torque(int8_t port); * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, * setting errno. @@ -900,6 +900,16 @@ typedef enum motor_gearset_e { E_MOTOR_GEARSET_INVALID = INT32_MAX, // Error: Invalid Gearset } motor_gearset_e_t; +/** + * \enum motor_type_e_t + * Indicates the type of a motor + */ +typedef enum motor_type_e { + E_MOTOR_TYPE_V5 = 0, // 11 watt V5 motor + E_MOTOR_TYPE_EXP = 1, // 5.5 watt EXP motor + E_MOTOR_TYPE_INVALID = INT32_MAX, // Error: invalid type +} motor_type_e_t; + #ifdef PROS_USE_SIMPLE_NAMES #ifdef __cplusplus #define MOTOR_BRAKE_COAST pros::E_MOTOR_BRAKE_COAST @@ -921,6 +931,9 @@ typedef enum motor_gearset_e { #define MOTOR_GEAR_BLUE pros::E_MOTOR_GEAR_BLUE #define MOTOR_GEAR_600 pros::E_MOTOR_GEAR_600 #define MOTOR_GEARSET_INVALID pros::E_MOTOR_GEARSET_INVALID +#define MOTOR_TYPE_V5 pros::E_MOTOR_TYPE_V5 +#define MOTOR_TYPE_EXP pros::E_MOTOR_TYPE_EXP +#define MOTOR_TYPE_INVALID pros::E_MOTOR_TYPE_INVALID #else #define MOTOR_BRAKE_COAST E_MOTOR_BRAKE_COAST #define MOTOR_BRAKE_BRAKE E_MOTOR_BRAKE_BRAKE @@ -941,6 +954,9 @@ typedef enum motor_gearset_e { #define MOTOR_GEAR_BLUE E_MOTOR_GEAR_BLUE #define MOTOR_GEAR_600 E_MOTOR_GEAR_600 #define MOTOR_GEARSET_INVALID E_MOTOR_GEARSET_INVALID +#define MOTOR_TYPE_V5 E_MOTOR_TYPE_V5 +#define MOTOR_TYPE_EXP E_MOTOR_TYPE_EXP +#define MOTOR_TYPE_INVALID E_MOTOR_TYPE_INVALID #endif #endif @@ -1001,11 +1017,11 @@ namespace c { * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param position * The new reference position in its encoder units * @@ -1041,11 +1057,11 @@ int32_t motor_set_zero_position(int8_t port, const double position); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -1078,11 +1094,11 @@ int32_t motor_tare_position(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param mode * The motor_brake_mode_e_t to set for the motor * @@ -1104,11 +1120,11 @@ int32_t motor_set_brake_mode(int8_t port, const motor_brake_mode_e_t mode); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param limit * The new current limit in mA * @@ -1134,11 +1150,11 @@ int32_t motor_set_current_limit(int8_t port, const int32_t limit); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param units * The new motor encoder units * @@ -1160,11 +1176,11 @@ int32_t motor_set_encoder_units(int8_t port, const motor_encoder_units_e_t units * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param gearset * The new motor gearset * @@ -1186,11 +1202,11 @@ int32_t motor_set_gearing(int8_t port, const motor_gearset_e_t gearset); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * \param limit * The new voltage limit in Volts * @@ -1216,11 +1232,11 @@ int32_t motor_set_voltage_limit(int8_t port, const int32_t limit); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return One of motor_brake_mode_e_t, according to what was set for the motor, * or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. @@ -1242,11 +1258,11 @@ motor_brake_mode_e_t motor_get_brake_mode(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's current limit in mA or PROS_ERR if the operation failed, * setting errno. @@ -1266,11 +1282,11 @@ int32_t motor_get_current_limit(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return One of motor_encoder_units_e_t according to what is set for the motor * or E_MOTOR_ENCODER_INVALID if the operation failed. @@ -1282,11 +1298,11 @@ motor_encoder_units_e_t motor_get_encoder_units(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return One of motor_gearset_e_t according to what is set for the motor, * or E_GEARSET_INVALID if the operation failed. @@ -1309,11 +1325,11 @@ motor_gearset_e_t motor_get_gearing(int8_t port); * * 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). + * ENXIO - The given value is not within the range of V5 ports |1-21|. * ENODEV - The port cannot be configured as a motor * * \param port - * The V5 port number from 1-21 + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors * * \return The motor's voltage limit in V or PROS_ERR if the operation failed, * setting errno. @@ -1328,6 +1344,30 @@ motor_gearset_e_t motor_get_gearing(int8_t port); */ int32_t motor_get_voltage_limit(int8_t port); +/** + * Get the type of the motor + * + * 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 a motor + * + * \param port + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors + * + * \return One of motor_type_e_t according to the type of the motor, or + * E_MOTOR_TYPE_INVALID if the operation failed. + * + * \b Example + * \code + * void initialize() { + * printf("Motor Type: %d\n", motor_get_type(1)); + * // Prints the type of the motor + * } + * \endcode + */ +motor_type_e_t motor_get_type(int8_t port); + ///@} ///@} diff --git a/include/pros/motors.hpp b/include/pros/motors.hpp index f895846..a0782bd 100644 --- a/include/pros/motors.hpp +++ b/include/pros/motors.hpp @@ -4,13 +4,10 @@ * * Contains prototypes for the V5 Motor-related functions. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/motors.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -36,54 +33,59 @@ inline namespace v5 { class Motor : public AbstractMotor, public Device { public: - explicit Motor(const std::int8_t port, const pros::v5::MotorGears gearset = pros::v5::MotorGears::green, - const pros::v5::MotorUnits encoder_units = pros::v5::MotorUnits::degrees); - /** * \addtogroup cpp-motors * @{ */ - /// \name Motor movement functions - /// These functions allow programmers to make motors move - ///@{ /** - * Sets the voltage for the motor from -128 to 127. - * - * This is designed to map easily to the input from the controller's analog - * stick for simple opcontrol use. The actual behavior of the motor is - * analogous to use of pros::Motor::move(), or motorSet from the PROS 2 API. + * Constructs a new Motor object. * * 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 a motor * - * \param voltage - * The new motor voltage from -127 to 127 + * \param port + * The V5 port number from 1 to 21, or from -21 to -1 for reversed motors. + * A reversed motor will reverse the input or output movement functions and movement related + * telemetry in order to produce consistant behavior with non-reversed motors * - * \return 1 if the operation was successful or PROS_ERR if the operation - * failed, setting errno. + * \param gearset = pros::v5::MotorGears::green + * Optional parameter for the gearset for the motor. + * Does not explicitly set the gearset if not specified or if the gearset is invalid + * + * \param encoder_units = pros::v5::MotorUnits::degrees + * Optional parameter for the encoder units of the motor + * Does not explicitly set the gearset if not specified or if the gearset is invalid * * \b Example * \code * void opcontrol() { - * pros::MotorGroup MotorGroup ({1}, E_MOTOR_GEARSET_18); - * pros::Controller master (E_CONTROLLER_MASTER); - * while (true) { - * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); - * pros::delay(2); - * } + * Motor first_motor(1); //Creates a motor on port 1 without altering gearset or encoder units + * Motor reversed_motor(-2); //Creates a reversed motor on port 1 port 1 without altering gearset or encoder units + * Motor blue_motor(3, pros::v5::MotorGears::blue); //Creates a motor on port 3 with blue gear set + * Motor rotations_motor(4, pros::v5::MotorGears::green, pros::v5::MotorUnits::rotations); //port 4 w/ rotations + * * } * \endcode + * */ - std::int32_t operator=(std::int32_t voltage) const; + Motor(const std::int8_t port, const pros::v5::MotorGears gearset = pros::v5::MotorGears::invalid, + const pros::v5::MotorUnits encoder_units = pros::v5::MotorUnits::invalid); + + Motor(const Device& device) : Motor(device.get_port()){}; + + /// \name Motor movement functions + /// These functions allow programmers to make motors move + ///@{ /** * Sets the voltage for the motor from -127 to 127. * * This is designed to map easily to the input from the controller's analog * stick for simple opcontrol use. The actual behavior of the motor is - * analogous to use of motor_move(), or motorSet() from the PROS 2 API. + * analogous to use of motor_move(). * * This function uses the following values of errno when an error state is * reached: @@ -98,7 +100,7 @@ class Motor : public AbstractMotor, public Device { * \b Example * \code * void opcontrol() { - * pros::MotorGroup MotorGroup ({1}); + * pros::Motor Motor (1); * pros::Controller master (E_CONTROLLER_MASTER); * while (true) { * motor.move(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); @@ -119,6 +121,7 @@ class Motor : public AbstractMotor, public Device { * \note This function simply sets the target for the motor, it does not block * program execution until the movement finishes. * + * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor @@ -159,8 +162,8 @@ class Motor : public AbstractMotor, public Device { * * This movement is relative to the current position of the motor as given in * pros::Motor::motor_get_position(). Providing 10.0 as the position parameter - * would result in the motor moving clockwise 10 units, no matter what the - * current position is. + * would result in the motor moving clockwise 10 units (counter clockwise if reversed), + * no matter what the current position is. * * \note This function simply sets the target for the motor, it does not block * program execution until the movement finishes. @@ -253,17 +256,82 @@ class Motor : public AbstractMotor, public Device { */ std::int32_t move_voltage(const std::int32_t voltage) const; + /** + * Stops the motor using the currently configured brake mode. + * + * This function sets motor velocity to zero, which will cause it to act + * according to the set brake mode. If brake mode is set to MOTOR_BRAKE_HOLD, + * this function may behave differently than calling move_absolute(0) + * or motor_move_relative(0). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * Motor motor(1); + * motor.move_voltage(12000); + * pros::delay(1000); // Move at max voltage for 1 second + * motor.brake(); + * } + * \endcode + */ std::int32_t brake(void) const; + + /** + * Changes the output velocity for a profiled movement (motor_move_absolute or + * motor_move_relative). This will have no effect if the motor is not following + * a profiled movement. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param velocity + * The new motor velocity from +-100, +-200, or +-600 depending on the + * motor's gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::Motor motor (1); + * motor.move_absolute(100, 100); + * pros::delay(100); + * motor.modify_profiled_velocity(0); // Stop the motor early + * } + * \endcode + */ std::int32_t modify_profiled_velocity(const std::int32_t velocity) const; + + ///@} + + /// \name Motor telemetry functions + /// These functions allow programmers to collect telemetry from motors + ///@{ + /** - * Gets the target position set for the motor by the user, with a parameter - * for the motor index. + * Gets the target position set for the motor by the user + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EOVERFLOW - The index is non 0 * - * \param index The index of the motor to get the target position of. + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return The target position in its encoder units or PROS_ERR_F if the * operation failed, setting errno. @@ -279,14 +347,22 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_target_position(const std::uint8_t index = 0) const; - std::vector get_target_position_all(void) const; /** - * Gets the velocity commanded to the motor by the user. + * Gets the velocity commanded to the motor by the user at the index specified. + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return The commanded motor velocity from +-100, +-200, or +-600, or * PROS_ERR if the operation failed, setting errno. @@ -306,20 +382,22 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_target_velocity(const std::uint8_t index = 0) const; - std::vector get_target_velocity_all(void) const; - - ///@} - - /// \name Motor telemetry functions - /// These functions allow programmers to collect telemetry from motors - ///@{ /** * Gets the actual velocity of the motor. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: * ENODEV - The port cannot be configured as a motor + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return The motor's actual velocity in RPM or PROS_ERR_F if the operation * failed, setting errno. @@ -337,15 +415,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_actual_velocity(const std::uint8_t index = 0) const; - std::vector get_actual_velocity_all(void) const; /** * Gets the current drawn by the motor in mA. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's current in mA or PROS_ERR if the operation failed, * setting errno. * @@ -363,15 +451,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_current_draw(const std::uint8_t index = 0) const; - std::vector get_current_draw_all(void) const; /** * Gets the direction of movement for the motor. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return 1 for moving in the positive direction, -1 for moving in the * negative direction, and PROS_ERR if the operation failed, setting errno. * @@ -389,7 +487,6 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_direction(const std::uint8_t index = 0) const; - std::vector get_direction_all(void) const; /** * Gets the efficiency of the motor in percent. @@ -398,10 +495,22 @@ class Motor : public AbstractMotor, public Device { * drawing no electrical power, and an efficiency of 0% means that the motor * is drawing power but not moving. * + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's efficiency in percent or PROS_ERR_F if the operation * failed, setting errno. * @@ -419,19 +528,27 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_efficiency(const std::uint8_t index = 0) const; - std::vector get_efficiency_all(void) const; /** * Gets the faults experienced by the motor. * * Compare this bitfield to the bitmasks in pros::motor_fault_e_t. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * * \return A bitfield containing the motor's faults. * @@ -448,18 +565,26 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::uint32_t get_faults(const std::uint8_t index = 0) const; - std::vector get_faults_all(void) const; + /** * Gets the flags set by the motor's operation. * * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \param port - * The V5 port number from 1-21 + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return A bitfield containing the motor's flags. * @@ -477,15 +602,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::uint32_t get_flags(const std::uint8_t index = 0) const; - std::vector get_flags_all(void) const; /** * Gets the absolute position of the motor in its encoder units. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's absolute position in its encoder units or PROS_ERR_F * if the operation failed, setting errno. * @@ -503,15 +638,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_position(const std::uint8_t index = 0) const; - std::vector get_position_all(void) const; /** * Gets the power drawn by the motor in Watts. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's power draw in Watts or PROS_ERR_F if the operation * failed, setting errno. * @@ -529,19 +674,33 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_power(const std::uint8_t index = 0) const; - std::vector get_power_all(void) const; + /** * Gets the raw encoder count of the motor at a given timestamp. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \param[in] timestamp + * EOVERFLOW - The index is non 0 + * + * + * \param timestamp * A pointer to a time in milliseconds for which the encoder count * will be returned. If NULL, the timestamp at which the encoder * count was read will not be supplied * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * + * * \return The raw encoder count at the given timestamp or PROS_ERR if the * operation failed. * @@ -560,15 +719,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_raw_position(std::uint32_t* const timestamp, const std::uint8_t index = 0) const; - std::vector get_raw_position_all(std::uint32_t* const timestamp) const; /** * Gets the temperature of the motor in degrees Celsius. + + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's temperature in degrees Celsius or PROS_ERR_F if the * operation failed, setting errno. * @@ -586,14 +755,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_temperature(const std::uint8_t index = 0) const; - std::vector get_temperature_all(void) const; + /** * Gets the torque generated by the motor in Newton Meters (Nm). * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's torque in Nm or PROS_ERR_F if the operation failed, * setting errno. * @@ -611,14 +791,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ double get_torque(const std::uint8_t index = 0) const; - std::vector get_torque_all(void) const; + /** * Gets the voltage delivered to the motor in millivolts. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's voltage in mV or PROS_ERR_F if the operation failed, * setting errno. * @@ -636,15 +827,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_voltage(const std::uint8_t index = 0) const; - std::vector get_voltage_all(void) const; /** * Checks if the motor is drawing over its current limit. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return 1 if the motor's current limit is being exceeded and 0 if the * current limit is not exceeded, or PROS_ERR if the operation failed, setting * errno. @@ -663,15 +864,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t is_over_current(const std::uint8_t index = 0) const; - std::vector is_over_current_all(void) const; /** * Gets the temperature limit flag for the motor. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return 1 if the temperature limit is exceeded and 0 if the temperature is * below the limit, or PROS_ERR if the operation failed, setting errno. * @@ -689,7 +900,6 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t is_over_temp(const std::uint8_t index = 0) const; - std::vector is_over_temp_all(void) const; ///@} @@ -700,11 +910,22 @@ class Motor : public AbstractMotor, public Device { /** * Gets the brake mode that was set for the motor. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \return One of Motor_Brake, according to what was set for the + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * \return One of MotorBrake, according to what was set for the * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. * * \b Example @@ -717,17 +938,25 @@ class Motor : public AbstractMotor, public Device { * \endcode */ MotorBrake get_brake_mode(const std::uint8_t index = 0) const; - std::vector get_brake_mode_all(void) const; /** * Gets the current limit for the motor in mA. * - * The default value is 2500 mA. + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return The motor's current limit in mA or PROS_ERR if the operation failed, * setting errno. * @@ -743,56 +972,68 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_current_limit(const std::uint8_t index = 0) const; - std::vector get_current_limit_all(void) const; /** * Gets the encoder units that were set for the motor. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \return One of Motor_Units according to what is set for the + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * \return One of MotorUnits according to what is set for the * motor or E_MOTOR_ENCODER_INVALID if the operation failed. * * \b Example * \code * void initialize() { - * pros::Motor motor (1, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * pros::Motor motor (1, E_MOTOR_GEARSET_06, E_MOTOR_ENCODER_COUNTS); * std::cout << "Motor Encoder Units: " << motor.get_encoder_units(); * } * \endcode */ MotorUnits get_encoder_units(const std::uint8_t index = 0) const; - std::vector get_encoder_units_all(void) const; /** * Gets the gearset that was set for the motor. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \return One of Motor_Gears according to what is set for the motor, - * or pros::Motor_Gears::invalid if the operation failed. + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * \return One of MotorGears according to what is set for the motor, + * or pros::MotorGears::invalid if the operation failed. * * \b Example * \code * void initialize() { - * pros::Motor motor (1, E_MOTOR_GEARSET_06, false, E_MOTOR_ENCODER_COUNTS); + * pros::Motor motor (1, E_MOTOR_GEARSET_06, E_MOTOR_ENCODER_COUNTS); * std::cout << "Motor Gearing: " << motor.get_gearing(); * } * \endcode */ MotorGears get_gearing(const std::uint8_t index = 0) const; - std::vector get_gearing_all(void) const; - - /** - * @brief Gets returns a vector with all the port numbers in the motor group. - * - * @return std::vector - */ - std::vector get_port_all(void) const; /** * Gets the voltage limit set by the user. @@ -800,12 +1041,20 @@ class Motor : public AbstractMotor, public Device { * Default value is 0V, which means that there is no software limitation * imposed on the voltage. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * - * \return The motor's voltage limit in V or PROS_ERR if the operation failed, - * setting errno. + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \b Example * \code @@ -816,14 +1065,22 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t get_voltage_limit(const std::uint8_t index = 0) const; - std::vector get_voltage_limit_all(void) const; /** - * Gets the operation direction of the motor as set by the user. + * Gets whether the motor is reversed or not + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups * * This function uses the following values of errno when an error state is * reached: - * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return 1 if the motor has been reversed and 0 if the motor was not * reversed, or PROS_ERR if the operation failed, setting errno. @@ -838,18 +1095,58 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t is_reversed(const std::uint8_t index = 0) const; - std::vector is_reversed_all(void) const; + + /** + * Gets the type of the motor + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the type of. + * By default index is 0, and will return an error for a non-zero index + * + * \return One of MotorType according to the type of the motor, + * or pros::MotorType::invalid if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1, E_MOTOR_GEARSET_06, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Type: " << motor.get_type(); + * } + * \endcode + */ + MotorType get_type(const std::uint8_t index = 0) const; /** - * Sets one of Motor_Brake to the motor. Works with the C enum - * and the C++ enum class. + * Sets one of Motor_Brake to the motor. + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * * \param mode - * The Motor_Brake to set for the motor + * The MotorBrake to set for the motor + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -864,19 +1161,61 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t set_brake_mode(const MotorBrake mode, const std::uint8_t index = 0) const; + /** + * Sets one of MotorBrake to the motor. + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * + * \param mode + * The MotorBrake to set for the motor + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << motor.get_brake_mode(); + * } + * \endcode + */ std::int32_t set_brake_mode(const pros::motor_brake_mode_e_t mode, const std::uint8_t index = 0) const; - std::int32_t set_brake_mode_all(const MotorBrake mode) const; - std::int32_t set_brake_mode_all(const pros::motor_brake_mode_e_t mode) const; /** * Sets the current limit for the motor in mA. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * * \param limit * The new current limit in mA * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. * @@ -896,9 +1235,9 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t set_current_limit(const std::int32_t limit, const std::uint8_t index = 0) const; - std::int32_t set_current_limit_all(const std::int32_t limit) const; + /** - * Sets one of Motor_Units for the motor encoder. Works with the C + * Sets one of MotorUnits for the motor encoder. Works with the C * enum and the C++ enum class. * * This function uses the following values of errno when an error state is @@ -921,17 +1260,59 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t set_encoder_units(const MotorUnits units, const std::uint8_t index = 0) const; - std::int32_t set_encoder_units(const pros::motor_encoder_units_e_t units, const std::uint8_t index = 0) const; - std::int32_t set_encoder_units_all(const MotorUnits units) const; - std::int32_t set_encoder_units_all(const pros::motor_encoder_units_e_t units) const; + /** + * Sets one of MotorUnits for the motor encoder. Works with the C + * enum and the C++ enum class. + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * * \param units + * The new motor encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_encoder_units(E_MOTOR_ENCODER_DEGREES); + * std::cout << "Encoder Units: " << motor.get_encoder_units(); + * } + * \endcode + */ + std::int32_t set_encoder_units(const pros::motor_encoder_units_e_t units, const std::uint8_t index = 0) const; /** * Sets one of the gear cartridge (red, green, blue) for the motor. Usable with * the C++ enum class and the C enum. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * \param gearset * The new motor gearset * @@ -948,22 +1329,64 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t set_gearing(const MotorGears gearset, const std::uint8_t index = 0) const; - std::int32_t set_gearing(const pros::motor_gearset_e_t gearset, const std::uint8_t index = 0) const; - std::int32_t set_gearing_all(const MotorGears gearset) const; - std::int32_t set_gearing_all(const pros::motor_gearset_e_t gearset) const; + /** + * Sets one of the gear cartridge (red, green, blue) for the motor. Usable with + * the C++ enum class and the C enum. + + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * \param gearset + * The new motor gearset + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_gearing(E_MOTOR_GEARSET_06); + * std::cout << "Gearset: " << motor.get_gearing(); + * } + * \endcode + */ + std::int32_t set_gearing(const pros::motor_gearset_e_t gearset, const std::uint8_t index = 0) const; /** * Sets the reverse flag for the motor. * * This will invert its movements and the values returned for its position. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: - * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 * * \param reverse - * True reverses the motor, false is default + * True reverses the motor, false is default direction + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. @@ -978,7 +1401,6 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t set_reversed(const bool reverse, const std::uint8_t index = 0); - std::int32_t set_reversed_all(const bool reverse); /** * Sets the voltage limit for the motor in Volts. @@ -1009,7 +1431,6 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t set_voltage_limit(const std::int32_t limit, const std::uint8_t index = 0) const; - std::int32_t set_voltage_limit_all(const std::int32_t limit) const; /** * Sets the position for the motor in its encoder units. @@ -1017,13 +1438,25 @@ class Motor : public AbstractMotor, public Device { * This will be the future reference point for the motor's "absolute" * position. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * * \param position * The new reference position in its encoder units * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. * @@ -1041,15 +1474,25 @@ class Motor : public AbstractMotor, public Device { * */ std::int32_t set_zero_position(const double position, const std::uint8_t index = 0) const; - std::int32_t set_zero_position_all(const double position) const; /** * Sets the "absolute" zero position of the motor to its current position. * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * * This function uses the following values of errno when an error state is * reached: + * * ENODEV - The port cannot be configured as a motor * + * EOVERFLOW - The index is non 0 + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. * @@ -1066,22 +1509,967 @@ class Motor : public AbstractMotor, public Device { * \endcode */ std::int32_t tare_position(const std::uint8_t index = 0) const; - std::int32_t tare_position_all(void) const; /** - * @brief Returns the number of objects + * Gets the number of motors. + * + * \return Always returns 1 * - * @return std::int8_t */ std::int8_t size(void) const; + /** + * Gets all motors. + * + * \return A vector of Motor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector motor_all = pros::Motor::get_all_devices(); // All motors that are connected + * } + * \endcode + */ + static std::vector get_all_devices(); + + /** + * gets the port number of the motor + * + * \return The signed port of the motor. (negative if the motor is reversed) + * + */ std::int8_t get_port(const std::uint8_t index = 0) const; - private: - std::int8_t _port; -}; -namespace literals { -const pros::Motor operator"" _mtr(const unsigned long long int m); + ///@} + + /// \name Additional motor functions + /// These functions allow for motors and motor groups to be used interchangeably + ///@{ + /** + * Gets a vector containing the target position set for the motor by the user + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing the target position in its encoder units or PROS_ERR_F if the + * operation failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::Motor motor (1); + * motor.move_absolute(100, 100); + * std::cout << "Motor Target: " << motor.get_target_position_all()[0]; + * // Prints 100 + * } + * \endcode + */ + std::vector get_target_position_all(void) const; + + /** + * Gets a vector containing the velocity commanded to the motor by the user + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the commanded motor velocity from +-100, + * +-200, or +-600, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor.move_velocity(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); + * std::cout << "Motor Velocity: " << motor.get_target_velocity_all()[0]; + * // Prints the value of E_CONTROLLER_ANALOG_LEFT_Y + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_target_velocity_all(void) const; + + /** + * Gets a vector containing the actual velocity commanded of the motor + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's actual velocity in RPM or PROS_ERR_F + * if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor.move_velocity(master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y)); + * std::cout << "Motor Velocity: " << motor.get_actual_velocity_all()[0]; + * // Prints the value of E_CONTROLLER_ANALOG_LEFT_Y + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_actual_velocity_all(void) const; + + /** + * Gets a vector containing the current drawn by the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing the motor's current in mA or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Current Draw: " << motor.get_current_draw_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_current_draw_all(void) const; + + /** + * Gets a vector containing the direction of movement for the motor. + * + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing 1 for moving in the positive direction, -1 for moving in the + * negative direction, and PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Direction: " << motor.get_direction_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_direction_all(void) const; + + /** + * Gets a vector containing the efficiency of the motor in percent. + * + * An efficiency of 100% means that the motor is moving electrically while + * drawing no electrical power, and an efficiency of 0% means that the motor + * is drawing power but not moving. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector containing The motor's efficiency in percent or PROS_ERR_F if the operation + * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Efficiency: " << motor.get_efficiency(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_efficiency_all(void) const; + + /** + * Gets a vector of the faults experienced by the motor. + * + * Compare this bitfield to the bitmasks in pros::motor_fault_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * \return A bitfield containing the motor's faults. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Faults: " << motor.get_faults_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_faults_all(void) const; + + /** + * Gets a vector of the flags set by the motor's operation. + * + * Compare this bitfield to the bitmasks in pros::motor_flag_e_t. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * + * \return A bitfield containing the motor's flags. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Faults: " << motor.get_faults_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_flags_all(void) const; + + /** + * Gets a vector containing the absolute position of the motor in its encoder units. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + + * + * \return A vector containing the motor's absolute position in its encoder units or PROS_ERR_F + * if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Position: " << motor.get_position_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_position_all(void) const; + + /** + * Gets a vector containing the power drawn by the motor in Watts. + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's power draw in Watts or PROS_ERR_F if the operation + * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Power: " << motor.get_power_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_power_all(void) const; + + /** + * Gets a vector of the raw encoder count of the motor at a given timestamp. + * + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * \param timestamp + * A pointer to a time in milliseconds for which the encoder count + * will be returned. If NULL, the timestamp at which the encoder + * count was read will not be supplied + * + * \return A vector containing the raw encoder count at the given timestamp or PROS_ERR if the + * operation failed. + * + * \b Example + * \code + * void opcontrol() { + * std::uint32_t now = pros::millis(); + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Position: " << motor.get_raw_position(&now); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_raw_position_all(std::uint32_t* const timestamp) const; + + /** + * Gets a vector of the temperature of the motor in degrees Celsius. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector contaioning the motor's temperature in degrees Celsius + * or PROS_ERR_F if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Temperature: " << motor.get_temperature_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_temperature_all(void) const; + + /** + * Gets a vector of the torque generated by the motor in Newton Meters (Nm). + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's torque in Nm or PROS_ERR_F if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Torque: " << motor.get_torque(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_torque_all(void) const; + + /** + * Gets a vector of the voltage delivered to the motor in millivolts. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * + * \return A vector of the motor's voltage in mV or PROS_ERR_F if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Motor Voltage: " << motor.get_voltage_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_voltage_all(void) const; + + /** + * Checks if the motor is drawing over its current limit. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing 1 if the motor's current limit is being exceeded and 0 if the + * current limit is not exceeded, or PROS_ERR if the operation failed, setting + * errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Is the motor over its current limit?: " << motor.is_over_current_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector is_over_current_all(void) const; + + /** + * Gets the temperature limit flag for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing 1 if the temperature limit is exceeded and 0 if the temperature is + * below the limit, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * std::cout << "Is the motor over its temperature limit?: " << motor.is_over_temp_all(); + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector is_over_temp_all(void) const; + + /** + * Gets a vector containing the brake mode that was set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return One of Motor_Brake, according to what was set for the + * motor, or E_MOTOR_BRAKE_INVALID if the operation failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_brake_mode(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << motor.get_brake_mode(); + * } + * \endcode + */ + std::vector get_brake_mode_all(void) const; + + /** + * Gets a vector containing the current limit for the motor in mA. + * + * The default value is 2500 mA. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's current limit in mA or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * while (true) { + * std::cout << "Motor Current Limit: " << motor.get_current_limit_all()[0]; + * pros::delay(2); + * } + * } + * \endcode + */ + std::vector get_current_limit_all(void) const; + + /** + * Gets a vector containing the encoder units that were set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing One of Motor_Units according to what is set for the + * motor or E_MOTOR_ENCODER_INVALID if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1, E_MOTOR_GEARSET_06, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Encoder Units: " << motor.get_encoder_units_all()[0]; + * } + * \endcode + */ + std::vector get_encoder_units_all(void) const; + + /** + * Gets a vector containing the gearset that was set for the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing one of Motor_Gears according to what is set for the motor, + * or pros::Motor_Gears::invalid if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1, E_MOTOR_GEARSET_06, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Gearing: " << motor.get_gearing_all()[0]; + * } + * \endcode + */ + std::vector get_gearing_all(void) const; + + /** + * Gets returns a vector with all the port numbers in the motor group. + * + * \return A vector containing the signed port of the motor. (negative if the motor is reversed) + */ + std::vector get_port_all(void) const; + + /** + * Gets a vector of the voltage limit set by the user. + * + * Default value is 0V, which means that there is no software limitation + * imposed on the voltage. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing the motor's voltage limit in V or PROS_ERR if the operation failed, + * setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * std::cout << "Motor Voltage Limit: " << motor.get_voltage_limit_all()[0]; + * } + * \endcode + */ + std::vector get_voltage_limit_all(void) const; + + /** + * Gets a vector containg whether the motor is reversed or not + * + * \return A vector containing 1 if the motor has been reversed and 0 if the motor was not + * reversed, or PROS_ERR if the operation failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * std::cout << "Is the motor reversed? " << motor.is_reversed_all()[0]; + * // Prints "0" + * } + * \endcode + */ + std::vector is_reversed_all(void) const; + + /** + * Gets a vector containing the type of the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return A vector containing one of MotorType according to the type of the motor, + * or pros::MotorType::invalid if the operation failed. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1, E_MOTOR_GEARSET_06, E_MOTOR_ENCODER_COUNTS); + * std::cout << "Motor Type: " << motor.get_type_all()[0]; + * } + * \endcode + */ + std::vector get_type_all(void) const; + + /** + * Sets one of Motor_Brake to the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param mode + * The Motor_Brake to set for the motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_brake_mode_all(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << motor.get_brake_mode(); + * } + * \endcode + */ + std::int32_t set_brake_mode_all(const MotorBrake mode) const; + + /** + * Sets one of Motor_Brake to the motor. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param mode + * The Motor_Brake to set for the motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_brake_mode_all(pros::E_MOTOR_BRAKE_HOLD); + * std::cout << "Brake Mode: " << motor.get_brake_mode(); + * } + * \endcode + */ + std::int32_t set_brake_mode_all(const pros::motor_brake_mode_e_t mode) const; + + /** + * Sets the current limit for the motor in mA. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param limit + * The new current limit in mA + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * + * motor.set_current_limit_all(1000); + * while (true) { + * motor = controller_get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * // The motor will reduce its output at 1000 mA instead of the default 2500 mA + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t set_current_limit_all(const std::int32_t limit) const; + + /** + * Sets one of Motor_Units for the motor encoder. Works with the C + * enum and the C++ enum class. + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * * \param units + * The new motor encoder units + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_encoder_units_all(E_MOTOR_ENCODER_DEGREES); + * std::cout << "Encoder Units: " << motor.get_encoder_units(); + * } + * \endcode + */ + std::int32_t set_encoder_units_all(const MotorUnits units) const; + + /** + * Sets one of Motor_Units for the motor encoder. Works with the C + * enum and the C++ enum class. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param units + * The new motor encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_encoder_units_all(E_MOTOR_ENCODER_DEGREES); + * std::cout << "Encoder Units: " << motor.get_encoder_units(); + * } + * \endcode + */ + std::int32_t set_encoder_units_all(const pros::motor_encoder_units_e_t units) const; + + /** + * Sets one of the gear cartridge (red, green, blue) for the motor. Usable with + * the C++ enum class and the C enum. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param gearset + * The new motor gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_gearing_all(E_MOTOR_GEARSET_06); + * std::cout << "Gearset: " << motor.get_gearing(); + * } + * \endcode + */ + std::int32_t set_gearing_all(const MotorGears gearset) const; + + /** + * Sets one of the gear cartridge (red, green, blue) for the motor. Usable with + * the C++ enum class and the C enum. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param gearset + * The new motor gearset + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_gearing_all(E_MOTOR_GEARSET_06); + * std::cout << "Gearset: " << motor.get_gearing(); + * } + * \endcode + */ + std::int32_t set_gearing_all(const pros::motor_gearset_e_t gearset) const; + + /** + * Sets the reverse flag for the motor. + * + * This will invert its movements and the values returned for its position. + * + * + * \param reverse + * True reverses the motor, false is default direction + * + * \return 1 + * + * \b Example + * \code + * void initialize() { + * pros::Motor motor (1); + * motor.set_reversed_all(true); + * std::cout << "Is this motor reversed? " << motor.is_reversed(); + * } + * \endcode + */ + std::int32_t set_reversed_all(const bool reverse); + + /** + * Sets the voltage limit for the motor in Volts. + * + * \note This is one of many Motor functions that takes in an optional index parameter. + * This parameter can be ignored by most users but exists to give a shared base class + * for motors and motor groups + * + * This function uses the following values of errno when an error state is + * reached: + * + * ENODEV - The port cannot be configured as a motor + * + * EOVERFLOW - The index is non 0 + * + * \param limit + * The new voltage limit in Volts + * + * \param index Optional parameter. + * The zero-indexed index of the motor to get the target position of. + * By default index is 0, and will return an error for a non-zero index + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::Motor motor (1); + * pros::Controller master (E_CONTROLLER_MASTER); + * + * motor.set_voltage_limit_all(10000); + * while (true) { + * motor = master.get_analog(E_CONTROLLER_ANALOG_LEFT_Y); + * // The motor will not output more than 10 V + * pros::delay(2); + * } + * } + * \endcode + */ + std::int32_t set_voltage_limit_all(const std::int32_t limit) const; + + /** + * Sets the position for the motor in its encoder units. + * + * This will be the future reference point for the motor's "absolute" + * position. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \param position + * The new reference position in its encoder units + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::Motor motor (1); + * motor.move_absolute(100, 100); // Moves 100 units forward + * motor.move_absolute(100, 100); // This does not cause a movement + * + * motor.set_zero_position_all(80); + * motor.move_absolute(100, 100); // Moves 80 units forward + * } + * \endcode + * + */ + std::int32_t set_zero_position_all(const double position) const; + + /** + * Sets the "absolute" zero position of the motor to its current position. + * + * This function uses the following values of errno when an error state is + * reached: + * ENODEV - The port cannot be configured as a motor + * + * \return 1 if the operation was successful or PROS_ERR if the operation + * failed, setting errno. + * + * \b Example + * \code + * void autonomous() { + * pros::Motor motor (1); + * motor.move_absolute(100, 100); // Moves 100 units forward + * motor.move_absolute(100, 100); // This does not cause a movement + * + * motor.tare_position_all(); + * motor.move_absolute(100, 100); // Moves 100 units forward + * } + * \endcode + */ + std::int32_t tare_position_all(void) const; + + ///@} + + private: + /** + * The port of the motor. Negative ports indicate that the motor is reversed + */ + std::int8_t _port; +}; +namespace literals { +/** + * Constructs a Motor from a literal ending in _mtr + * + * \return a pros::Motor for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Motor motor = 2_mtr; //Makes an Motor object on port 2 + * } + * \endcode + */ +const pros::Motor operator"" _mtr(const unsigned long long int m); +/** + * Constructs a reversed Motor from a literal ending in _rmtr + * + * \return a pros::Motor for the corresponding port that is reversed + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::motor motor = 2_rmtr; //Makes an reversed Motor object on port 2 + * } + * \endcode + */ const pros::Motor operator"" _rmtr(const unsigned long long int m); } // namespace literals } // namespace v5 diff --git a/include/pros/optical.h b/include/pros/optical.h index daf3924..bc12491 100644 --- a/include/pros/optical.h +++ b/include/pros/optical.h @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the VEX Optical sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/imu.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -463,6 +460,39 @@ int32_t optical_enable_gesture(uint8_t port); */ int32_t optical_disable_gesture(uint8_t port); +/** + * Get integration time (update rate) of the optical sensor in milliseconds, with + * minimum time being + * + * 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 Optical Sensor + * + * \param port + * The V5 Optical Sensor port number from 1-21 + * \return Integration time in milliseconds if the operation is successful + * or PROS_ERR_F if the operation failed, setting errno. + */ +double optical_get_integration_time(uint8_t port); + +/** + * Set integration time (update rate) of the optical sensor in milliseconds. + * + * 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 Optical Sensor + * + * \param port + * The V5 Optical Sensor port number from 1-21 + * \param time + * The desired integration time in milliseconds + * \return 1 if the operation is successful or PROS_ERR if the operation failed, + * setting errno. + */ +int32_t optical_set_integration_time(uint8_t port, double time); + ///@} ///@} diff --git a/include/pros/optical.hpp b/include/pros/optical.hpp index 4ab66b3..3cb55d9 100644 --- a/include/pros/optical.hpp +++ b/include/pros/optical.hpp @@ -4,18 +4,15 @@ * * Contains prototypes for functions related to the VEX Optical sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/imu.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-optical VEX Optical Sensor C++ API */ @@ -27,8 +24,8 @@ #include #include -#include "pros/optical.h" #include "pros/device.hpp" +#include "pros/optical.h" namespace pros { inline namespace v5 { @@ -51,8 +48,30 @@ class Optical : public Device { * * \param port * The V5 port number from 1-21 + * + * \b Example: + * \code{.cpp} + * pros::Optical optical(1); + * \endcode + */ + Optical(const std::uint8_t port); + + Optical(const Device& device) : Optical(device.get_port()){}; + + + /** + * Gets all optical sensors. + * + * \return A vector of Optical sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector optical_all = pros::Optical::get_all_devices(); // All optical sensors that are connected + * } + * \endcode */ - explicit Optical(const std::uint8_t port); + static std::vector get_all_devices(); /** * Get the detected color hue @@ -67,6 +86,14 @@ class Optical : public Device { * * \return hue value if the operation was successful or PROS_ERR_F if the operation * failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * std::cout << "Hue: " << optical.get_hue() << std::endl; + * } + * \endcode */ virtual double get_hue(); @@ -83,6 +110,14 @@ class Optical : public Device { * * \return saturation value if the operation was successful or PROS_ERR_F if * the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * std::cout << "Saturation: " << optical.get_saturation() << std::endl; + * } + * \endcode */ virtual double get_saturation(); @@ -99,6 +134,14 @@ class Optical : public Device { * * \return brightness value if the operation was successful or PROS_ERR_F if * the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * std::cout << "Brightness: " << optical.get_brightness() << std::endl; + * } + * \endcode */ virtual double get_brightness(); @@ -113,8 +156,16 @@ class Optical : public Device { * ENXIO - The given value is not within the range of V5 ports (1-21). * ENODEV - The port cannot be configured as an Optical Sensor * - * \return poximity value if the operation was successful or PROS_ERR if + * \return Proximity value if the operation was successful or PROS_ERR if * the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * std::cout << "Proximity: " << optical.get_proximity() << std::endl; + * } + * \endcode */ virtual std::int32_t get_proximity(); @@ -128,7 +179,15 @@ class Optical : public Device { * ENXIO - The given value is not within the range of V5 ports (1-21). * ENODEV - The port cannot be configured as an Optical Sensor * - * \return The Error code encountered + * \return The Error code encountered or PROS_SUCCESS. + * + * \b Example: + * \code{.cpp} + * void initialize() { + * pros::Optical optical(1); + * optical.set_led_pwm(100); + * } + * \endcode */ virtual std::int32_t set_led_pwm(uint8_t value); @@ -144,6 +203,15 @@ class Optical : public Device { * * \return LED pwm value if the operation was successful or PROS_ERR if * the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * optical.set_led_pwm(100); + * std::cout << "LED PWM: " << optical.get_led_pwm() << std::endl; + * } + * \endcode */ virtual std::int32_t get_led_pwm(); @@ -155,8 +223,23 @@ class Optical : public Device { * ENXIO - The given value is not within the range of V5 ports (1-21). * ENODEV - The port cannot be configured as an Optical Sensor * - * \return rgb value if the operation was successful or an optical_rgb_s_t + * \return rgb value if the operation was successful or an optical_rgb_s_t * with all fields set to PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * pros::c::optical_rgb_s_t rgb = optical.get_rgb(); + * while(1) { + * std::cout << "Red: " << rgb.red << std::endl; + * std::cout << "Green: " << rgb.green << std::endl; + * std::cout << "Blue: " << rgb.blue << std::endl; + * std::cout << "Brightness: " << rgb.brightness << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ virtual pros::c::optical_rgb_s_t get_rgb(); @@ -168,8 +251,23 @@ class Optical : public Device { * ENXIO - The given value is not within the range of V5 ports (1-21). * ENODEV - The port cannot be configured as an Optical Sensor * - * \return raw rgb value if the operation was successful or an optical_raw_s_t + * \return raw rgb value if the operation was successful or an optical_raw_s_t * with all fields set to PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * pros::c::optical_raw_s_t raw = optical.get_raw(); + * while (1) { + * std::cout << "Red: " << raw.red << std::endl; + * std::cout << "Green: " << raw.green << std::endl; + * std::cout << "Blue: " << raw.blue << std::endl; + * std::cout << "Clear: " << raw.clear << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ virtual pros::c::optical_raw_s_t get_raw(); @@ -177,10 +275,12 @@ class Optical : public Device { * Get the most recent gesture data from the sensor * * Gestures will be cleared after 500mS - * 0 = no gesture - * 1 = up (towards cable) - * 2 = down - * 3 = right + * + * + * 0 = no gesture, + * 1 = up (towards cable), + * 2 = down, + * 3 = right, * 4 = left * * This function uses the following values of errno when an error state is @@ -190,6 +290,17 @@ class Optical : public Device { * * \return gesture value if the operation was successful or PROS_ERR if * the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * while(1) { + * std::cout << "Gesture: " << optical.get_gesture() << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ virtual pros::c::optical_direction_e_t get_gesture(); @@ -201,8 +312,28 @@ class Optical : public Device { * ENXIO - The given value is not within the range of V5 ports (1-21). * ENODEV - The port cannot be configured as an Optical Sensor * - * \return gesture value if the operation was successful or an optical_gesture_s_t + * \return gesture value if the operation was successful or an optical_gesture_s_t * with all fields set to PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * optical.enable_gesture(); + * while(1) { + * pros::c::optical_gesture_s_t gesture = optical.get_gesture_raw(); + * std::cout << "Gesture raw data: " << std::endl; + * std::cout << "Up data: " << gesture.udata << std::endl; + * std::cout << "Down data: " << gesture.ddata << std::endl; + * std::cout << "Left data: " << gesture.ldata << std::endl; + * std::cout << "Right data: " << gesture.rdata << std::endl; + * std::cout << "Type: " << gesture.type << std::endl; + * std::cout << "Count: " << gesture.count << std::endl; + * std::cout << "Time: " << gesture.time << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ virtual pros::c::optical_gesture_s_t get_gesture_raw(); @@ -215,7 +346,27 @@ class Optical : public Device { * ENODEV - The port cannot be configured as an Optical Sensor * * \return 1 if the operation is successful or PROS_ERR if the operation failed, - * setting errno. + * setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * optical.enable_gesture(); + * while(1) { + * pros::c::optical_gesture_s_t gesture = optical.get_gesture_raw(); + * std::cout << "Gesture raw data: " << std::endl; + * std::cout << "Up data: " << gesture.udata << std::endl; + * std::cout << "Down data: " << gesture.ddata << std::endl; + * std::cout << "Left data: " << gesture.ldata << std::endl; + * std::cout << "Right data: " << gesture.rdata << std::endl; + * std::cout << "Type: " << gesture.type << std::endl; + * std::cout << "Count: " << gesture.count << std::endl; + * std::cout << "Time: " << gesture.time << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ virtual std::int32_t enable_gesture(); @@ -228,28 +379,90 @@ class Optical : public Device { * ENODEV - The port cannot be configured as an Optical Sensor * * \return 1 if the operation is successful or PROS_ERR if the operation failed, - * setting errno. + * setting errno. + * + * \b Example: + * \code{.cpp} + * void opcontrol() { + * pros::Optical optical(1); + * optical.enable_gesture(); + * while(1) { + * if(optical.get_gesture() != 0) { + * std::cout << "Gesture detected!"<< std::endl; + * optical.disable_gesture(); + * } + * pros::delay(20); + * } + * } + * \endcode */ virtual std::int32_t disable_gesture(); + /** + * Get integration time (update rate) of the optical sensor in milliseconds. + * + * 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 Optical Sensor + * + * \return Integration time in milliseconds if the operation is successful + * or PROS_ERR_F if the operation failed, setting errno. + */ + double get_integration_time(); + + /** + * Set integration time (update rate) of the optical sensor in milliseconds, with + * minimum time being 3 ms and maximum time being 712 ms. Default is 100 ms, with the + * optical sensor communciating with the V5 brain every 20 ms. + * + * 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 Optical Sensor + * + * \param time The desired integration time in milliseconds + * \return 1 if the operation is successful or PROS_ERR if the operation failed, + * setting errno. + */ + std::int32_t set_integration_time(double time); /** - * This is the overload for the << operator for printing to streams - * - * Prints in format(this below is all in one line with no new line): - * Optical [port: (port number), hue: (hue), saturation: (saturation), + * This is the overload for the << operator for printing to streams + * + * Prints in format(this below is all in one line with no new line): + * Optical [port: (port number), hue: (hue), saturation: (saturation), * brightness: (brightness), proximity: (proximity), rgb: {red, green, blue}] + * + * \b Example: + * \code{.cpp} + * pros::Optical optical(1); + * std::cout << optical << std::endl; + * \endcode */ friend std::ostream& operator<<(std::ostream& os, pros::Optical& optical); - + private: ///@} }; namespace literals { +/** + * Constructs a Optical sensor from a literal ending in _opt + * + * \return a pros::Optical for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Optical opt = 2_opt; //Makes an Optical object on port 2 + * } + * \endcode + */ const pros::Optical operator"" _opt(const unsigned long long int o); } // namespace literals -} +} // namespace v5 } // namespace pros #endif diff --git a/include/pros/rotation.h b/include/pros/rotation.h index c4e90bf..5a90441 100644 --- a/include/pros/rotation.h +++ b/include/pros/rotation.h @@ -4,13 +4,10 @@ * * Contains prototypes for functions related to the VEX Rotation Sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/rotation.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -135,7 +132,7 @@ int32_t rotation_set_data_rate(uint8_t port, uint32_t rate); * } * \endcode */ -int32_t rotation_set_position(uint8_t port, uint32_t position); +int32_t rotation_set_position(uint8_t port, int32_t position); /** * Reset the Rotation Sensor position to 0 @@ -187,7 +184,7 @@ int32_t rotation_reset_position(uint8_t port); * * void opcontrol() { * while (true) { - * printf("Position: %d Ticks \n", rotation_get_position(ROTATION_PORT)); + * printf("Position: %d centidegrees \n", rotation_get_position(ROTATION_PORT)); * delay(20); * } * } @@ -214,7 +211,7 @@ int32_t rotation_get_position(uint8_t port); * * void opcontrol() { * while (true) { - * printf("Velocity: %d Ticks \n", rotation_get_velocity(ROTATION_PORT)); + * printf("Velocity: %d centidegrees per second \n", rotation_get_velocity(ROTATION_PORT)); * delay(20); * } * } @@ -241,7 +238,7 @@ int32_t rotation_get_velocity(uint8_t port); * * void opcontrol() { * while (true) { - * printf("Angle: %d Ticks \n", rotation_get_angle(ROTATION_PORT)); + * printf("Angle: %d centidegrees \n", rotation_get_angle(ROTATION_PORT)); * delay(20); * } * } @@ -274,7 +271,7 @@ int32_t rotation_get_angle(uint8_t port); * while (true) { * * if(controller_get_digital(CONTROLLER_MASTER, E_CONTROLLER_DIGITAL_X)){ - * rotation_set_reversed(ROTATION_PORT); + * rotation_set_reversed(ROTATION_PORT, true); // Reverses the Rotation Sensor on ROTATION_PORT * } * delay(20); * } @@ -333,7 +330,19 @@ int32_t rotation_reverse(uint8_t port); * * \b Example * \code + * #define ROTATION_PORT 1 + * + * void opcontrol() { + * Rotation rotation_sensor(ROTATION_PORT); + * bool reverse_flag = true; + * while (true) { * + * if(controller_get_digital(CONTROLLER_MASTER, E_CONTROLLER_DIGITAL_X)){ + * rotation_init_reverse(ROTATION_PORT, reverse_flag); + * } + * delay(20); + * } + * } * \endcode */ int32_t rotation_init_reverse(uint8_t port, bool reverse_flag); diff --git a/include/pros/rotation.hpp b/include/pros/rotation.hpp index b82e81b..1e6dda9 100644 --- a/include/pros/rotation.hpp +++ b/include/pros/rotation.hpp @@ -4,18 +4,15 @@ * * Contains prototypes for functions related to the VEX Rotation Sensor. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/rotation.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-rotation VEX Rotation Sensor C++ API */ #ifndef _PROS_ROTATION_HPP_ @@ -24,24 +21,42 @@ #include #include -#include "pros/rotation.h" #include "pros/device.hpp" +#include "pros/rotation.h" namespace pros { inline namespace v5 { /** - * \addtogroup cpp-rotation + * \ingroup cpp-rotation */ class Rotation : public Device { /** - * \ingroup cpp-rotation - * @{ + * \addtogroup cpp-rotation + * @{ */ public: - explicit Rotation(const std::uint8_t port) : Device(port, DeviceType::rotation) {}; + /** + * Constructs a new Rotation Sensor object + * + * ENXIO - The given value is not within the range of V5 ports |1-21|. + * ENODEV - The port cannot be configured as a Rotation Sensor + * + * \param port + * The V5 port number from 1 to 21, or from -21 to -1 for reversed Rotation Sensors. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); //Creates a Rotation Sensor on port 1 + * pros::Rotation reversed_rotation_sensor(-2); //Creates a reversed Rotation Sensor on port 2 + * } + * \endcode + */ + Rotation(const std::int8_t port); + + Rotation(const Device& device) : Rotation(device.get_port()){}; - explicit Rotation(const std::uint8_t port, const bool reverse_flag); /** * Reset the Rotation Sensor @@ -56,6 +71,20 @@ class Rotation : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * if(master.get_analog(E_CONTROLLER_DIGITAL_X) { + * rotation_sensor.reset(); + * } + * pros::delay(20); + * } + * } + * \endcode */ virtual std::int32_t reset(); @@ -79,6 +108,14 @@ class Rotation : public Device { * \param rate The data refresh interval in milliseconds * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Rotation rotation_sensor(1); + * rotation_sensor.set_data_rate(5); + * } + * \endcode */ virtual std::int32_t set_data_rate(std::uint32_t rate) const; @@ -94,11 +131,25 @@ class Rotation : public Device { * The position in terms of ticks * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * if(master.get_analog(E_CONTROLLER_DIGITAL_X) { + * rotation_sensor.set_position(600); + * } + * pros::delay(20); + * } + * } + * \endcode */ - virtual std::int32_t set_position(std::uint32_t position) const; + virtual std::int32_t set_position(std::int32_t position) const; /** - * Reset the Rotation Sensor to a desired rotation value + * Reset the Rotation Sensor position to 0 * * This function uses the following values of errno when an error state is * reached: @@ -109,9 +160,37 @@ class Rotation : public Device { * The position in terms of ticks * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * if(master.get_analog(E_CONTROLLER_DIGITAL_X) { + * rotation_sensor.reset_position(); + * } + * pros::delay(20); + * } + * } + * \endcode */ virtual std::int32_t reset_position(void) const; + /** + * Gets all rotation sensors. + * + * \return A vector of Rotation sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector rotation_all = pros::Rotation::get_all_devices(); // All rotation sensors that are connected + * } + * \endcode + */ + static std::vector get_all_devices(); + /** * Get the Rotation Sensor's current position in centidegrees * @@ -122,6 +201,17 @@ class Rotation : public Device { * * \return The position value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * while (true) { + * printf("Position: %d Ticks \n", rotation_sensor.get_position()); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get_position() const; @@ -135,9 +225,19 @@ class Rotation : public Device { * * \param port * The V5 Rotation Sensor port number from 1-21 - * \return The - value or PROS_ERR_F if the operation failed, setting + * \return The velocity value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * while (true) { + * printf("Velocity: %d centidegrees per second \n", rotation_sensor.get_velocity)); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get_velocity() const; @@ -151,6 +251,17 @@ class Rotation : public Device { * * \return The angle value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * while (true) { + * printf("Angle: %d centidegrees \n", rotation_sensor.get_angle()); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get_angle() const; @@ -168,6 +279,20 @@ class Rotation : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * if(master.get_analog(E_CONTROLLER_DIGITAL_X) { + * rotation_sensor.set_reversed(true); // Reverses the Rotation Sensor + * } + * pros::delay(20); + * } + * } + * \endcode */ virtual std::int32_t set_reversed(bool value) const; @@ -181,6 +306,20 @@ class Rotation : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * pros::Controller master (E_CONTROLLER_MASTER); + * while (true) { + * if(master.get_analog(E_CONTROLLER_DIGITAL_X) { + * rotation_sensor.reverse(); + * } + * pros::delay(20); + * } + * } + * \endcode */ virtual std::int32_t reverse() const; @@ -194,25 +333,62 @@ class Rotation : public Device { * * \return Reversed value or PROS_ERR if the operation failed, setting * errno. + * + * \b Example + * \code + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * while (true) { + * printf("Reversed: %d \n", rotation_sensor.get_reversed()); + * delay(20); + * } + * } + * \endcode */ virtual std::int32_t get_reversed() const; - ///@} /** * This is the overload for the << operator for printing to streams - * + * * Prints in format(this below is all in one line with no new line): - * Rotation [port: rotation._port, position: (rotation position), velocity: (rotation velocity), + * Rotation [port: rotation._port, position: (rotation position), velocity: (rotation velocity), * angle: (rotation angle), reversed: (reversed boolean)] + * + * \b Example + * \code + * #define ROTATION_PORT 1 + * + * void opcontrol() { + * pros::Rotation rotation_sensor(1); + * while(true) { + * std::cout << rotation_sensor << std::endl; + * pros::delay(20); + * } + * } + * \endcode */ friend std::ostream& operator<<(std::ostream& os, const pros::Rotation& rotation); + ///@} }; namespace literals { +/** + * Constructs a Rotation sensor from a literal ending in _rot + * + * \return a pros::Rotation for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Rotation rotation = 2_rot; //Makes an Motor object on port 2 + * } + * \endcode + */ const pros::Rotation operator"" _rot(const unsigned long long int r); } // namespace literals -} +} // namespace v5 } // namespace pros #endif diff --git a/include/pros/rtos.h b/include/pros/rtos.h index 9c36c9f..bf87661 100644 --- a/include/pros/rtos.h +++ b/include/pros/rtos.h @@ -5,13 +5,10 @@ * Contains declarations for the PROS RTOS kernel for use by typical VEX * programmers. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html to - * learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public @@ -20,7 +17,7 @@ * * \defgroup c-rtos RTOS Facilities C API * \note Additional example code for this module can be found in its [Tutorial.](@ref multitasking) - */ + */ #ifndef _PROS_RTOS_H_ #define _PROS_RTOS_H_ @@ -33,92 +30,117 @@ extern "C" { namespace pros { #endif -/** - * \ingroup c-rtos - */ +/// \ingroup c-rtos -/** - * \addtogroup c-rtos - * @{ - */ +/// \addtogroup c-rtos +/// @{ -/// \name Macros -///@{ +/// \name Macros +/// @{ -/// The highest priority that can be assigned to a task. Beware of deadlock. +/** + * The highest priority that can be assigned to a task. + * + * A task with this priority will always run if it is available to. Beware of + * deadlocks when using this priority. + */ #define TASK_PRIORITY_MAX 16 -/// The lowest priority that can be assigned to a task. -/// This may cause severe performance problems and is generally not recommended. +/** + * The lowest priority that can be assigned to a task. + * + * This can cause severe performance problems and is generally not recommended + * that users use this priority. + */ #define TASK_PRIORITY_MIN 1 -/// The default task priority, which should be used for most tasks. -/// Default tasks such as autonomous() inherit this priority. +/** + * The default task priority, which should be used for most tasks unless you + * have a specific need for a higher or lower priority task. + * + * The default tasks, such as autonomous(), are run with this priority + */ #define TASK_PRIORITY_DEFAULT 8 -/// The recommended stack size for a new task. This stack size is used for -/// default tasks such as autonomous(). This equates to 32,768 bytes, or 128 -/// times the default stack size for a task in PROS 2. +/** + * The recommended stack size for a new task. + * + * This stack size is used for the default tasks such as autonomous(). This + * size is 8,192 words, or 32,768 bytes. This should be enough for the majority + * of tasks + */ #define TASK_STACK_DEPTH_DEFAULT 0x2000 -/// The minimal stack size for a task. This equates to 2048 bytes, or 8 times the -/// default stack size for a task in PROS 2. +/** + * The minimal stack size for a task. + * + * This equates to 512 words, or 2,048 bytes. + */ #define TASK_STACK_DEPTH_MIN 0x200 -/// The maximum number of characters allowed in a task's name. +/** + * The maximum number of characters allowed in a task's name. + */ #define TASK_NAME_MAX_LEN 32 -/// The maximum timeout value that can be given to, for instance, a mutex grab. +/** + * The maximum timeout value that can be given to, for instance, a mutex grab. + */ #define TIMEOUT_MAX ((uint32_t)0xffffffffUL) -///@} +/// @} Name: Macros + +/// \name Typedefs +/// @{ /** - * \typedef - * Points to a task handle. Used for referencing a task. + * An opaque type that pontis to a task handle. This is used for referencing a + * task. */ typedef void* task_t; /** - * \typedef - * Points to the function associated with a task. + * A pointer to a task's function. + * + * Such a function is called when a task starts, and exiting said function will + * terminate the task. */ typedef void (*task_fn_t)(void*); +/// @} Name: Typedefs + + +/// \name Enumerations +/// @{ + /** - * \enum task_state_e_t + * The state of a task. */ typedef enum { - ///The task is actively executing. - E_TASK_STATE_RUNNING = 0, - ///The task exists and is available to run, but is not currently running. - E_TASK_STATE_READY, - ///The task is delayed or blocked by a mutex, semaphore, or I/O operation. - E_TASK_STATE_BLOCKED, - ///The task is supended using task_suspend. - E_TASK_STATE_SUSPENDED, - ///The task has been deleted using task_delete. - E_TASK_STATE_DELETED, - ///The task handle does not point to a current or past task. - E_TASK_STATE_INVALID + E_TASK_STATE_RUNNING = 0, /**< The task is actively executing. */ + E_TASK_STATE_READY, /**< The task exists and is available to run, but is not currently running. */ + E_TASK_STATE_BLOCKED, /**< The task is delayed or blocked by a mutex, semaphore, or I/O operation. */ + E_TASK_STATE_SUSPENDED, /**< The task is supended using task_suspend. */ + E_TASK_STATE_DELETED, /**< The task has been deleted using task_delete. */ + E_TASK_STATE_INVALID /**< The task handle does not point to a current or past task.*/ } task_state_e_t; /** - * \enum + * brief The action to take when a task is notified. */ typedef enum { - ///The task’s notification value will not be touched. - E_NOTIFY_ACTION_NONE, - ///The task’s notification value will be bitwise ORed with the new value. - E_NOTIFY_ACTION_BITS, - ///The task’s notification value will be incremented by one, effectively using it as a notification counter. - E_NOTIFY_ACTION_INCR, - ///The task’s notification value will be unconditionally set to the new value. - E_NOTIFY_ACTION_OWRITE, - ///The task’s notification value will be set to the new value if the task does not already have a pending notification. - E_NOTIFY_ACTION_NO_OWRITE + E_NOTIFY_ACTION_NONE, /**< The task’s notification value will not be touched.*/ + E_NOTIFY_ACTION_BITS, /**< The task’s notification value will be bitwise ORed with the new value.*/ + E_NOTIFY_ACTION_INCR, /**< The task’s notification value will be incremented by one, effectively using it as a notification counter.*/ + E_NOTIFY_ACTION_OWRITE, /**< The task’s notification value will be unconditionally set to the new value.*/ + E_NOTIFY_ACTION_NO_OWRITE /**< The task’s notification value will be set to the new value if the task does not already have a pending notification.*/ } notify_action_e_t; +/// @} Name: Enumerations + +/// \name Simple enum names +/// @{ + #ifdef PROS_USE_SIMPLE_NAMES #ifdef __cplusplus #define TASK_STATE_RUNNING pros::E_TASK_STATE_RUNNING @@ -147,13 +169,24 @@ typedef enum { #endif #endif +/// @} Name: Simple enum names + +/// \name Typedefs + /** - * \typedef A [mutex.](@ref multitasking) + * A [mutex.](@ref multitasking) + * + * A mutex is a synchronization object that can be used to protect a shared + * resource from being accessed by multiple tasks at the same time. A mutex can + * be claimed by a task, which will prevent other tasks from claiming it until + * that task releases it. */ typedef void* mutex_t; +/// @} Name: Typedefs + /** - * \def Refers to the current task handle + * The task handle of the currently running task. */ #ifdef __cplusplus #define CURRENT_TASK ((pros::task_t)NULL) @@ -161,11 +194,14 @@ typedef void* mutex_t; #define CURRENT_TASK ((task_t)NULL) #endif +/// @} (add to group: c-rtos) + #ifdef __cplusplus namespace c { #endif -/// \name Functions +/// \ingroup c-rtos +/// \addtogroup c-rtos /// @{ /** @@ -276,7 +312,7 @@ task_t task_create(task_fn_t function, void* const parameters, uint32_t prio, co void task_delete(task_t task); /** - * Delays a task for a given number of milliseconds. + * Delays the current task for a given number of milliseconds. * * This is not the best method to have a task execute code at predefined * intervals, as the delay time is measured from when the delay is requested. @@ -288,20 +324,40 @@ void task_delete(task_t task); * \b Example * \code * void opcontrol() { - * while (true) { - * // Do opcontrol things - * task_delay(2); + * while (true) { + * // Do opcontrol things + * task_delay(2); * } * } * \endcode */ void task_delay(const uint32_t milliseconds); +/** + * Delays the current task for a given number of milliseconds. + * + * This is not the best method to have a task execute code at predefined + * intervals, as the delay time is measured from when the delay is requested. + * To delay cyclically, use task_delay_until(). + * + * \param milliseconds + * The number of milliseconds to wait (1000 milliseconds per second) + * + * \b Example + * \code + * void opcontrol() { + * while (true) { + * // Do opcontrol things + * delay(2); + * } + * } + * \endcode + */ void delay(const uint32_t milliseconds); /** - * Delays a task until a specified time. This function can be used by periodic - * tasks to ensure a constant execution frequency. + * Delays the current task until a specified time. This function can be used + * by periodic tasks to ensure a constant execution frequency. * * The task will be woken up at the time *prev_time + delta, and *prev_time will * be updated to reflect the time at which the task will unblock. @@ -408,17 +464,29 @@ task_state_e_t task_get_state(task_t task); * * \b Example * \code - * void my_task_fn(void* ign) { - * // Do things + * mutex_t counter_mutex; + * int counter = 0; + * + * void my_task_fn(void* param) { + * while(true) { + * mutex_take(counter_mutex, TIMEOUT_MAX);// Mutexes are used for protecting shared resources + * counter++; + * mutex_give(counter_mutex); + * pros::delay(10); + * } * } * * void opcontrol() { - * task_t my_task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT, - * TASK_STACK_DEPTH_DEFAULT, "Notify me! Task"); - * // Do things - * task_suspend(my_task); // The task will no longer execute - * // Do other things - * task_resume(my_task); // The task will resume execution + * task_t task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT,; + * + * while(true) { + * mutex_take(counter_mutex, TIMEOUT_MAX); + * if(counter > 100) { + * task_suspepend(task); + * } + * mutex_give(counter_mutex); + * pros::delay(10); + * } * } * \endcode */ @@ -432,18 +500,35 @@ void task_suspend(task_t task); * * \b Example * \code - * void my_task_fn(void* ign) { - * // Do things + * void my_task_fn(void* param) { + * while(true) { + * // Do stuff + * delay(10); + * } + * } + * + * task_t task; + * + * void initialize() { + * task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "My Task"); + * } + * + * void autonomous() { + * task_resume(task); + * + * // Run autonomous , then suspend the task so it doesn't interfere run + * + * // outside of autonomous or opcontrol + * task_suspend(task); * } * * void opcontrol() { - * task_t my_task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT, - * TASK_STACK_DEPTH_DEFAULT, "Example Task"); - * // Do things - * task_suspend(my_task); // The task will no longer execute - * // Do other things - * task_resume(my_task); // The task will resume execution + * task_resume(task); + * // Opctonrol code here + * task_suspend(task); * } + * * \endcode */ void task_resume(task_t task); @@ -550,9 +635,6 @@ task_t task_get_current(); /** * Sends a simple notification to task and increments the notification counter. * - * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for - * details. - * * \param task * The task to notify * @@ -561,9 +643,10 @@ task_t task_get_current(); * \b Example * \code * void my_task_fn(void* ign) { - * while(task_notify_take(true, TIMEOUT_MAX)) { - * puts("I was unblocked!"); + * while(task_notify_take(true) == 0) { + * // Code while waiting * } + * puts("I was unblocked!"); * } * * void opcontrol() { @@ -571,7 +654,7 @@ task_t task_get_current(); * TASK_STACK_DEPTH_DEFAULT, "Notify me! Task"); * while(true) { * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { - * task_notify(my_task); + * task_notify(my_task); * } * } * } @@ -583,9 +666,6 @@ uint32_t task_notify(task_t task); * * Utilizes task notifications to wait until specified task is complete and deleted, * then continues to execute the program. Analogous to std::thread::join in C++. - * - * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for - * details. * * \param task * The handle of the task to wait on. @@ -616,9 +696,6 @@ void task_join(task_t task); * retrieve the value of the notification in the target task before modifying * the notification value. * - * See https://pros.cs.purdue.edu/v5/tutorials/topical/notifications.html for - * details. - * * \param task * The task to notify * \param value @@ -637,7 +714,33 @@ void task_join(task_t task); * * \b Example * \code + * void my_task_fn(void* param) { + * while(true) { + * // Wait until we have been notified 20 times before running the code + * if(task_notify_take(false, TIMEOUT_MAX) == 20) { + * // ... Code to do stuff here ... * + * // Reset the notification counter + * task_notify_take(true, TIMEOUT_MAX); + * } + * delay(10); + * } + * } + * + * void opcontrol() { + * task_t task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "My Task"); + * + * int count = 0; + * + * while(true) { + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * task_notify_ext(task, 1, NOTIFY_ACTION_INCREMENT, &count); + * } + * + * delay(20); + * } + * } * \endcode */ uint32_t task_notify_ext(task_t task, uint32_t value, notify_action_e_t action, uint32_t* prev_value); @@ -661,8 +764,9 @@ uint32_t task_notify_ext(task_t task, uint32_t value, notify_action_e_t action, * \b Example * \code * void my_task_fn(void* ign) { - * while(task_notify_take(true, TIMEOUT_MAX)) { - * puts("I was unblocked!"); + * task_t current_task = task_get_current(); + * while(task_notify_take(current_task, true, TIMEOUT_MAX)) { + * puts("I was unblocked!"); * } * } * @@ -670,8 +774,8 @@ uint32_t task_notify_ext(task_t task, uint32_t value, notify_action_e_t action, * task_t my_task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT, * TASK_STACK_DEPTH_DEFAULT, "Notify me! Task"); * while(true) { - * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { - * task_notify(my_task); + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * task_notify(my_task); * } * } * } @@ -692,7 +796,28 @@ uint32_t task_notify_take(bool clear_on_exit, uint32_t timeout); * * \b Example * \code + * void my_task_fn(void* param) { + * task_t task = task_get_current(); + * while(true) { + * printf("Waiting for notification...\n"); + * printf("Got a notification: %d\n", task_notify_take(task, false, TIMEOUT_MAX)); + * + * task_notify_clear(task); + * delay(10): + * } + * } + * + * void opcontrol() { + * task_t task = task_create(my_task_fn, NULL, TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "My Task"); * + * while(true) { + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * task_notify(task); + * } + * delay(10); + * } + * } * \endcode */ bool task_notify_clear(task_t task); @@ -708,14 +833,71 @@ bool task_notify_clear(task_t task); * * \b Example * \code - * mutex_t mutex = mutex_create(); - * // Acquire the mutex; other tasks using this command will wait until the mutex is released - * // timeout can specify the maximum time to wait, or MAX_DELAY to wait forever - * // If the timeout expires, "false" will be returned, otherwise "true" - * mutex_take(mutex, MAX_DELAY); - * // do some work - * // Release the mutex for other tasks - * mutex_give(mutex); + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * mutex_t odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * mutex_take(odom_mutex, MAX_DELAY); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * mutex_give(odom_mutex); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * mutex_take(odom_mutex, MAX_DELAY); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * mutex_give(odom_mutex); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * mutex_take(odom_mutex, MAX_DELAY); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * mutex_give(odom_mutex); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = mutex_create(); + * + * task_create(odom_task, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Odometry Task"); + * task_create(chassis_task, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Chassis Task"); + * } * \endcode */ mutex_t mutex_create(void); @@ -740,14 +922,71 @@ mutex_t mutex_create(void); * * \b Example * \code - * mutex_t mutex = mutex_create(); - * // Acquire the mutex; other tasks using this command will wait until the mutex is released - * // timeout can specify the maximum time to wait, or MAX_DELAY to wait forever - * // If the timeout expires, "false" will be returned, otherwise "true" - * mutex_take(mutex, timeout); - * // do some work - * // Release the mutex for other tasks - * mutex_give(mutex); + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * mutex_t odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * mutex_take(odom_mutex, MAX_DELAY); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * mutex_give(odom_mutex); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * mutex_take(odom_mutex, MAX_DELAY); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * mutex_give(odom_mutex); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * mutex_take(odom_mutex, MAX_DELAY); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * mutex_give(odom_mutex); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = mutex_create(); + * + * task_create(odom_task, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Odometry Task"); + * task_create(chassis_task, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Chassis Task"); + * } * \endcode */ bool mutex_take(mutex_t mutex, uint32_t timeout); @@ -767,20 +1006,157 @@ bool mutex_take(mutex_t mutex, uint32_t timeout); * * \b Example * \code - * mutex_t mutex = mutex_create(); - * // Acquire the mutex; other tasks using this command will wait until the mutex is released - * // timeout can specify the maximum time to wait, or MAX_DELAY to wait forever - * // If the timeout expires, "false" will be returned, otherwise "true" - * mutex_take(mutex, timeout); - * // do some work - * // Release the mutex for other tasks - * mutex_give(mutex); + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * mutex_t odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * mutex_take(odom_mutex, MAX_DELAY); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * mutex_give(odom_mutex); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * mutex_take(odom_mutex, MAX_DELAY); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * mutex_give(odom_mutex); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * mutex_take(odom_mutex, MAX_DELAY); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * mutex_give(odom_mutex); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = mutex_create(); + * + * task_create(odom_task, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Odometry Task"); + * task_create(chassis_task, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Chassis Task"); + * } * \endcode */ bool mutex_give(mutex_t mutex); /** - * Deletes a mutex + * Creates a recursive mutex which can be locked recursively by the owner. + * + * \return A newly created recursive mutex. + * + * \b Example: + * \code + * mutex_t mutex = mutex_recursive_create(); + * + * void task_fn(void* param) { + * while(1) { + * mutex_recursive_take(mutex, 1000); + * // critical section + * mutex_recursive_give(mutex); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * \endcode + */ +mutex_t mutex_recursive_create(void); + +/** + * Takes a recursive mutex. + * + * \param mutex + * A mutex handle created by mutex_recursive_create + * \param wait_time + * Amount of time to wait before timing out + * + * \return 1 if the mutex was obtained, 0 otherwise + * + * \b Example: + * \code + * mutex_t mutex = mutex_recursive_create(); + * + * void task_fn(void* param) { + * while(1) { + * mutex_recursive_take(mutex, 1000); + * // critical section + * mutex_recursive_give(mutex); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * \endcode + */ +bool mutex_recursive_take(mutex_t mutex, uint32_t timeout); + +/** + * Gives a recursive mutex. + * + * \param mutex + * A mutex handle created by mutex_recursive_create + * + * \return 1 if the mutex was obtained, 0 otherwise + * + * \b Example: + * \code + * mutex_t mutex = mutex_recursive_create(); + * + * void task_fn(void* param) { + * while(1) { + * mutex_recursive_take(mutex, 1000); + * // critical section + * mutex_recursive_give(mutex); + * task_delay(1000); + * } + * } + * task_create(task_fn, (void*)"PROS", TASK_PRIORITY_DEFAULT, + * TASK_STACK_DEPTH_DEFAULT, "task_fn"); + * + * \endcode + */ +bool mutex_recursive_give(mutex_t mutex); + +/** + * Deletes a mutex or recursive mutex * * \param mutex * Mutex to unlock. @@ -801,9 +1177,7 @@ bool mutex_give(mutex_t mutex); */ void mutex_delete(mutex_t mutex); -///@} - -///@} +/// @} Add to group: c-rtos #ifdef __cplusplus } // namespace c diff --git a/include/pros/rtos.hpp b/include/pros/rtos.hpp index 551a5f2..d6c2d89 100644 --- a/include/pros/rtos.hpp +++ b/include/pros/rtos.hpp @@ -5,20 +5,17 @@ * Contains declarations for the PROS RTOS kernel for use by typical VEX * programmers. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html to - * learn more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * - * \defgroup cpp-rtos RTOS Facilities C API + * \defgroup cpp-rtos RTOS Facilities C++ API * \note Additional example code for this module can be found in its [Tutorial.](@ref multitasking) */ @@ -27,6 +24,7 @@ #include "pros/rtos.h" #undef delay +#include #include #include #include @@ -69,7 +67,18 @@ class Task { * \param name * A descriptive name for the task. This is mainly used to facilitate * debugging. The name may be up to 32 characters long. - * + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, (void*)"PROS"); + * } + * \endcode */ Task(task_fn_t function, void* parameters = nullptr, std::uint32_t prio = TASK_PRIORITY_DEFAULT, std::uint16_t stack_depth = TASK_STACK_DEPTH_DEFAULT, const char* name = ""); @@ -91,7 +100,18 @@ class Task { * \param name * A descriptive name for the task. This is mainly used to facilitate * debugging. The name may be up to 32 characters long. - * + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, (void*)"PROS", "My Task"); + * } + * \endcode */ Task(task_fn_t function, void* parameters, const char* name); @@ -113,7 +133,18 @@ class Task { * \param name * A descriptive name for the task. This is mainly used to facilitate * debugging. The name may be up to 32 characters long. - * + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::c::task_t my_task = pros::Task::create(my_task_fn, (void*)"PROS"); + * } + * \endcode */ template static task_t create(F&& function, std::uint32_t prio = TASK_PRIORITY_DEFAULT, @@ -139,7 +170,18 @@ class Task { * \param name * A descriptive name for the task. This is mainly used to facilitate * debugging. The name may be up to 32 characters long. - * + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::c::task_t my_task = pros::Task::create(my_task_fn, "My Task"); + * } + * \endcode */ template static task_t create(F&& function, const char* name) { @@ -164,7 +206,19 @@ class Task { * \param name * A descriptive name for the task. This is mainly used to facilitate * debugging. The name may be up to 32 characters long. - * + * + * \b Example + * \code + * + * void initialize() { + * // Create a task function using lambdas + * auto task_fn = [](void* param) { + * printf("Hello %s\n", (char*)param); + * } + * + * pros::Task my_task(task_fn, (void*)"PROS", "My Task"); + * } + * \endcode */ template explicit Task(F&& function, std::uint32_t prio = TASK_PRIORITY_DEFAULT, @@ -191,6 +245,22 @@ class Task { * A descriptive name for the task. This is mainly used to facilitate * debugging. The name may be up to 32 characters long. * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task( + * [](void* param) { + * printf("Inside the task!\n"); + * }, + * "My Task" + * ); + * } + * \endcode */ template Task(F&& function, const char* name) @@ -202,20 +272,60 @@ class Task { * \param task * A task handle from task_create() for which to create a pros::Task * object. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::c::task_t my_task = pros::Task::create(my_task_fn, "My Task"); + * + * pros::Task my_task_cpp(my_task); + * } + * \endcode */ explicit Task(task_t task); /** * Get the currently running Task + * + * @return The currently running Task. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("The name of this task is \"%s\"\n", pros::Task::current().get_name() + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, pros::TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "My Task"); + * } + * \endcode */ static Task current(); /** - * Creates a new task and add it to the list of tasks that are ready to run. + * Creates a task object from the passed task handle. * * \param in * A task handle from task_create() for which to create a pros::Task * object. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("The name of this task is \"%s\"\n", pros::Task::current().get_name() + * } + * + * void initialize() { + * pros::c::task_t my_task = pros::Task::create(my_task_fn, "My Task"); + * + * pros::Task my_task_cpp = my_task; + * } + * \endcode */ Task& operator=(task_t in); @@ -225,6 +335,20 @@ class Task { * * Memory dynamically allocated by the task is not automatically freed, and * should be freed before the task is deleted. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, "My Task"); + * + * my_task.remove(); + * } + * \endcode */ void remove(); @@ -232,6 +356,20 @@ class Task { * Gets the priority of the specified task. * * \return The priority of the task + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, "My Task"); + * + * printf("Task Priority: %d\n", my_task.get_priority()); + * } + * \endcode */ std::uint32_t get_priority(); @@ -244,6 +382,20 @@ class Task { * * \param prio * The new priority of the task + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, "My Task"); + * + * Task.set_priority(pros::DEFAULT_PRIORITY + 1); + * } + * \endcode */ void set_priority(std::uint32_t prio); @@ -251,11 +403,53 @@ class Task { * Gets the state of the specified task. * * \return The state of the task + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, "My Task"); + * + * printf("Task State: %d\n", my_task.get_state()); + * } + * \endcode */ std::uint32_t get_state(); /** * Suspends the specified task, making it ineligible to be scheduled. + * + * \b Example + * \code + * pros::Mutex counter_mutex; + * int counter = 0; + * + * void my_task_fn(void* param) { + * while(true) { + * counter_mutex.take(); // Mutexes are used for protecting shared resources + * counter++; + * counter_mutex.give(); + * pros::delay(10); + * } + * } + * + * void opcontrol() { + * pros::Task task(my_task_fn, "My Task"); + * + * while(true) { + * counter_mutex.take(); + * if(counter > 100) { + * task_suspepend(task); + * } + * counter_mutex.give(); + * pros::delay(10); + * } + * } + * \endcode */ void suspend(); @@ -264,6 +458,33 @@ class Task { * * \param task * The task to resume + * + * \b Example + * \code + * void my_task_fn(void* param) { + * while(true) { + * // Do stuff + * pros::delay(10); + * } + * } + * + * pros::Task task(my_task_fn); + * + * void autonomous() { + * task.resume(); + * + * // Run autonomous , then suspend the task so it doesn't interfere run + * // outside of autonomous or opcontrol + * task.suspend(); + * } + * + * void opcontrol() { + * task.resume(); + * // Opctonrol code here + * task.suspend(); + * } + * + * \endcode */ void resume(); @@ -271,11 +492,38 @@ class Task { * Gets the name of the specified task. * * \return A pointer to the name of the task + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, "My Task"); + * printf("Number of Running Tasks: %d\n", my_task.get_name()); + * } + * \endcode */ const char* get_name(); /** * Convert this object to a C task_t handle + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void initialize() { + * pros::Task my_task(my_task_fn, "My Task"); + * + * pros::c::task_t my_task_c = (pros::c::task_t)my_task; + * } + * \endcode */ explicit operator task_t() { return task; @@ -289,6 +537,26 @@ class Task { * details. * * \return Always returns true. + * + * \b Example + * \code + * void my_task_fn(void* ign) { + * while(pros::Task::current_task().notify_take(true) == 0) { + * // Code while waiting + * } + * puts("I was unblocked!"); + * } + * + * void opcontrol() { + * pros::Task my_task(my_task_fn); + * + * while(true) { + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * my_task.notify(); + * } + * } + * } + * \endcode */ std::uint32_t notify(); @@ -300,6 +568,22 @@ class Task { * details. * * \return void + * + * \b Example + * \code + * void my_task_fn(void* ign) { + * lcd_print(1, "%s running", pros::Task::current_task().get_name()); + * task_delay(1000); + * lcd_print(2, "End of %s", pros::Task::current_task().get_name()); + * } + * + * void opcontrol() { + * pros::Task my_task(my_task_fn); + * pros::lcd::set_text(0, "Running task."); + * my_task.join(); + * pros::lcd::lcd_set_text(3, "Task completed."); + * } + * \endcode */ void join(); @@ -324,6 +608,38 @@ class Task { * For NOTIFY_ACTION_NO_WRITE: return 0 if the value could be written without * needing to overwrite, 1 otherwise. * For all other NOTIFY_ACTION values: always return 0 + * + * \b Example + * \code + * void my_task_fn(void* param) { + * pros::Task task = pros::Task::current(); + * + * while(true) { + * // Wait until we have been notified 20 times before running the code + * if(task.notify_take(false, TIMEOUT_MAX) == 20) { + * // ... Code to do stuff here ... + * + * // Reset the notification counter + * task.notify_clear(); + * } + * delay(10); + * } + * } + * + * void opcontrol() { + * pros::Task task(my_task_fn); + * + * int count = 0; + * + * while(true) { + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * task.notify_ext(1, NOTIFY_ACTION_INCREMENT, &count); + * } + * + * delay(20); + * } + * } + * \endcode */ std::uint32_t notify_ext(std::uint32_t value, notify_action_e_t action, std::uint32_t* prev_value); @@ -342,6 +658,25 @@ class Task { * * \return The value of the task's notification value before it is decremented * or cleared + * + * \b Example + * \code + * void my_task_fn(void* ign) { + * pros::Task task = pros::task::current(); + * while(task.notify_take(true, TIMEOUT_MAX)) { + * puts("I was unblocked!"); + * } + * } + * + * void opcontrol() { + * pros::Task task(my_task_fn); + * while(true) { + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * task.notify(my_task); + * } + * } + * } + * \endcode */ static std::uint32_t notify_take(bool clear_on_exit, std::uint32_t timeout); @@ -352,11 +687,34 @@ class Task { * details. * * \return False if there was not a notification waiting, true if there was + * \b Example + * \code + * void my_task_fn(void* param) { + * pros::Task task = pros::Task::current(); + * while(true) { + * printf("Waiting for notification...\n"); + * printf("Got a notification: %d\n", task.notify_take(false, TIMEOUT_MAX)); + * + * tasK_notify(task); + * delay(10): + * } + * } + * + * void opcontrol() { + * pros::Task task(my_task_fn); + * while(true) { + * if(controller_get_digital(CONTROLLER_MASTER, DIGITAL_L1)) { + * task.notify(); + * } + * delay(10); + * } + * } + * \endcode */ bool notify_clear(); /** - * Delays a task for a given number of milliseconds. + * Delays the current task for a specified number of milliseconds. * * This is not the best method to have a task execute code at predefined * intervals, as the delay time is measured from when the delay is requested. @@ -364,11 +722,20 @@ class Task { * * \param milliseconds * The number of milliseconds to wait (1000 milliseconds per second) + * + * \b Example + * \code + * void opcontrol() { + * while (true) { + * // Do opcontrol things + * pros::Task::delay(2); + * } + * \endcode */ static void delay(const std::uint32_t milliseconds); /** - * Delays a task until a specified time. This function can be used by + * Delays the current Task until a specified time. This function can be used by * periodic tasks to ensure a constant execution frequency. * * The task will be woken up at the time *prev_time + delta, and *prev_time @@ -379,6 +746,16 @@ class Task { * typically be initialized to the return value from pros::millis(). * \param delta * The number of milliseconds to wait (1000 milliseconds per second) + * + * \b Example + * \code + * void opcontrol() { + * while (true) { + * // Do opcontrol things + * pros::Task::delay(2); + * } + * } + * \endcode */ static void delay_until(std::uint32_t* const prev_time, const std::uint32_t delta); @@ -389,6 +766,19 @@ class Task { * Tasks recently created may take one context switch to be counted. * * \return The number of tasks that are currently being managed by the kernel. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * printf("Hello %s\n", (char*)param); + * // ... + * } + * + * void opcontrol() { + * pros::Task my_task(my_task_fn); + * printf("There are %d tasks running\n", pros::Task::get_count()); + * } + * \endcode */ static std::uint32_t get_count(); @@ -410,15 +800,36 @@ struct Clock { * Effectively a wrapper around pros::millis() * * \return The current time + * + * \b Example + * \code + * void opcontrol() { + * pros::Clock::time_point start = pros::Clock::now(); + * pros::Clock::time_point end = pros::Clock::now(); + * pros::Clock::duration duration = end - start; + * printf("Duration: %d\n", duration.count()); + * + * if(duration.count() == 500) { + * // If you see this comment in the DOCS, ping @pros in VTOW. + * // If you are the first person to do so, you will receive a free PROS + * // holo! + * printf("Duration is 500 milliseconds\n"); + * } + * } + * \endcode */ static time_point now(); }; class Mutex { - std::shared_ptr> mutex; - + std::atomic mutex{nullptr}; + mutex_t lazy_init(); public: - Mutex(); + constexpr Mutex() { + if (!std::is_constant_evaluated()) { + lazy_init(); + } + } // disable copy and move construction and assignment per Mutex requirements // (see https://en.cppreference.com/w/cpp/named_req/Mutex) @@ -437,7 +848,76 @@ class Mutex { * * \return True if the mutex was successfully taken, false otherwise. If false * is returned, then errno is set with a hint about why the the mutex - * couldn't be taken. + * couldn't be taken + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::Mutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.take(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.give(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.take(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.give(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.take(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.give(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::Mutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. */ bool take(); @@ -457,6 +937,75 @@ class Mutex { * \return True if the mutex was successfully taken, false otherwise. If false * is returned, then errno is set with a hint about why the the mutex * couldn't be taken. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::Mutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.take(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.give(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.take(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.give(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.take(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.give(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::Mutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. */ bool take(std::uint32_t timeout); @@ -470,6 +1019,75 @@ class Mutex { * \return True if the mutex was successfully returned, false otherwise. If * false is returned, then errno is set with a hint about why the mutex * couldn't be returned. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::Mutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.take(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.give(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.take(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.give(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.take(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.give(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::Mutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. */ bool give(); @@ -487,6 +1105,75 @@ class Mutex { * * \exception std::system_error Mutex could not be locked within TIMEOUT_MAX * milliseconds. see errno for details. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::Mutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.lock(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.unlock(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.lock(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.unlock(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.lock(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.unlock(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::Mutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. */ void lock(); @@ -500,6 +1187,75 @@ class Mutex { * * \note Consider using a std::unique_lock, std::lock_guard, or * std::scoped_lock instead of interacting with the Mutex direcly. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::Mutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.lock(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.unlock(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.lock(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.unlock(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.lock(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.unlock(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::Mutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. */ void unlock(); @@ -512,8 +1268,22 @@ class Mutex { * \see https://en.cppreference.com/w/cpp/named_req/Lockable * * \return True when lock was acquired succesfully, or false otherwise. + * + * pros::Mutex mutex; + * + * void my_task_fn(void* param) { + * while (true) { + * if(mutex.try_lock()) { + * printf("Mutex aquired successfully!\n"); + * // Do stuff that requires the protected resource here + * } + * else { + * printf("Mutex not aquired!\n"); + * } + * } + * } */ - bool try_lock(); + [[nodiscard]] bool try_lock(); /** * Takes and locks a mutex, waiting for a specified duration. @@ -526,9 +1296,558 @@ class Mutex { * * \param rel_time Time to wait before the mutex becomes available. * \return True if the lock was acquired succesfully, otherwise false. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * while (true) { + * if(mutex.try_lock_for(std::chrono::milliseconds(100))) { + * printf("Mutex aquired successfully!\n"); + * // Do stuff that requires the protected resource here + * } + * else { + * printf("Mutex not aquired after 100 milliseconds!\n"); + * } + * } + * } + * \endcode + */ + template + [[nodiscard]] bool try_lock_for(const std::chrono::duration& rel_time) { + return take(std::chrono::duration_cast(rel_time).count()); + } + + /** + * Takes and locks a mutex, waiting until a specified time. + * + * Conforms to named requirement TimedLockable + * \see https://en.cppreference.com/w/cpp/named_req/TimedLockable + * + * \param abs_time Time point until which to wait for the mutex. + * \return True if the lock was acquired succesfully, otherwise false. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * while (true) { + * // Get the current time point + * auto now = std::chrono::system_clock::now(); + * + * // Calculate the time point 100 milliseconds from now + * auto abs_time = now + std::chrono::milliseconds(100); + * + * if(mutex.try_lock_until(abs_time)) { + * printf("Mutex aquired successfully!\n"); + * // Do stuff that requires the protected resource here + * } + * else { + * printf("Mutex not aquired after 100 milliseconds!\n"); + * } + * } + * } + * \endcode + */ + template + bool try_lock_until(const std::chrono::time_point& abs_time) { + return take(std::max(static_cast(0), (abs_time - Clock::now()).count())); + } + ~Mutex(); + ///@} +}; + +class RecursiveMutex { + std::atomic mutex{nullptr}; + mutex_t lazy_init(); + public: + constexpr RecursiveMutex() { + if (!std::is_constant_evaluated()) { + lazy_init(); + } + } + + // disable copy and move construction and assignment per Mutex requirements + // (see https://en.cppreference.com/w/cpp/named_req/Mutex) + RecursiveMutex(const RecursiveMutex&) = delete; + RecursiveMutex(RecursiveMutex&&) = delete; + + RecursiveMutex& operator=(const RecursiveMutex&) = delete; + RecursiveMutex& operator=(RecursiveMutex&&) = delete; + + /** + * Takes and locks a mutex indefinetly. + * + * See + * https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \return True if the mutex was successfully taken, false otherwise. If false + * is returned, then errno is set with a hint about why the the mutex + * couldn't be taken + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::RecursiveMutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.take(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.give(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.take(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.give(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.take(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.give(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::RecursiveMutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. + */ + bool take(); + + /** + * Takes and locks a mutex, waiting for up to a certain number of milliseconds + * before timing out. + * + * See + * https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \param timeout + * Time to wait before the mutex becomes available. A timeout of 0 can + * be used to poll the mutex. TIMEOUT_MAX can be used to block + * indefinitely. + * + * \return True if the mutex was successfully taken, false otherwise. If false + * is returned, then errno is set with a hint about why the the mutex + * couldn't be taken. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::RecursiveMutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.take(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.give(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.take(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.give(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.take(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.give(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::RecursiveMutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. + */ + bool take(std::uint32_t timeout); + + /** + * Unlocks a mutex. + * + * See + * https://pros.cs.purdue.edu/v5/tutorials/topical/multitasking.html#mutexes + * for details. + * + * \return True if the mutex was successfully returned, false otherwise. If + * false is returned, then errno is set with a hint about why the mutex + * couldn't be returned. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::RecursiveMutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.take(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.give(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.take(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.give(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.take(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.give(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::RecursiveMutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. + */ + bool give(); + + /** + * Takes and locks a mutex, waiting for up to TIMEOUT_MAX milliseconds. + * + * Effectively equivalent to calling pros::RecursiveMutex::take with TIMEOUT_MAX as + * the parameter. + * + * Conforms to named requirment BasicLockable + * \see https://en.cppreference.com/w/cpp/named_req/BasicLockable + * + * \note Consider using a std::unique_lock, std::lock_guard, or + * std::scoped_lock instead of interacting with the Mutex directly. + * + * \exception std::system_error Mutex could not be locked within TIMEOUT_MAX + * milliseconds. see errno for details. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::RecursiveMutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.lock(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.unlock(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.lock(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.unlock(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.lock(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.unlock(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::RecursiveMutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. + */ + void lock(); + + /** + * Unlocks a mutex. + * + * Equivalent to calling pros::RecursiveMutex::give. + * + * Conforms to named requirement BasicLockable + * \see https://en.cppreference.com/w/cpp/named_req/BasicLockable + * + * \note Consider using a std::unique_lock, std::lock_guard, or + * std::scoped_lock instead of interacting with the Mutex direcly. + * + * \b Example + * \code + * // Global variables for the robot's odometry, which the rest of the robot's + * // subsystems will utilize + * double odom_x = 0.0; + * double odom_y = 0.0; + * double odom_heading = 0.0; + * + * // This mutex protects the odometry data. Whenever we read or write to the + * // odometry data, we should make copies into the local variables, and read + * // all 3 values at once to avoid errors. + * pros::RecursiveMutex odom_mutex; + * + * void odom_task(void* param) { + * while(true) { + * // First we fetch the odom coordinates from the previous iteration of the + * // odometry task. These are put into local variables so that we can + * // keep the size of the critical section as small as possible. This lets + * // other tasks that need to use the odometry data run until we need to + * // update it again. + * odom_mutex.lock(); + * double x_old = odom_x; + * double y_old = odom_y; + * double heading_old = odom_heading; + * odom_mutex.unlock(); + * + * double x_new = 0.0; + * double y_new = 0.0; + * double heading_new = 0.0; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * odom_mutex.lock(); + * odom_x = x_new; + * odom_y = y_new; + * odom_heading = heading_new; + * odom_mutex.unlock(); + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * // Here we copy the current odom values into local variables so that + * // we can use them without worrying about the odometry task changing say, + * // the y value right after we've read the x. This ensures our values are + * // sound. + * odom_mutex.lock(); + * double current_x = odom_x; + * double current_y = odom_y; + * double current_heading = odom_heading; + * odom_mutex.unlock(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::RecursiveMutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * \endcode. + */ + void unlock(); + + /** + * Try to lock a mutex. + * + * Returns immediately if unsucessful. + * + * Conforms to named requirement Lockable + * \see https://en.cppreference.com/w/cpp/named_req/Lockable + * + * \return True when lock was acquired succesfully, or false otherwise. + * + * pros::RecursiveMutex mutex; + * + * void my_task_fn(void* param) { + * while (true) { + * if(mutex.try_lock()) { + * printf("Mutex aquired successfully!\n"); + * // Do stuff that requires the protected resource here + * } + * else { + * printf("Mutex not aquired!\n"); + * } + * } + * } + */ + [[nodiscard]] bool try_lock(); + + /** + * Takes and locks a mutex, waiting for a specified duration. + * + * Equivalent to calling pros::RecursiveMutex::take with a duration specified in + * milliseconds. + * + * Conforms to named requirement TimedLockable + * \see https://en.cppreference.com/w/cpp/named_req/TimedLockable + * + * \param rel_time Time to wait before the mutex becomes available. + * \return True if the lock was acquired succesfully, otherwise false. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * while (true) { + * if(mutex.try_lock_for(std::chrono::milliseconds(100))) { + * printf("Mutex aquired successfully!\n"); + * // Do stuff that requires the protected resource here + * } + * else { + * printf("Mutex not aquired after 100 milliseconds!\n"); + * } + * } + * } + * \endcode */ template - bool try_lock_for(const std::chrono::duration& rel_time) { + [[nodiscard]] bool try_lock_for(const std::chrono::duration& rel_time) { return take(std::chrono::duration_cast(rel_time).count()); } @@ -540,11 +1859,34 @@ class Mutex { * * \param abs_time Time point until which to wait for the mutex. * \return True if the lock was acquired succesfully, otherwise false. + * + * \b Example + * \code + * void my_task_fn(void* param) { + * while (true) { + * // Get the current time point + * auto now = std::chrono::system_clock::now(); + * + * // Calculate the time point 100 milliseconds from now + * auto abs_time = now + std::chrono::milliseconds(100); + * + * if(mutex.try_lock_until(abs_time)) { + * printf("Mutex aquired successfully!\n"); + * // Do stuff that requires the protected resource here + * } + * else { + * printf("Mutex not aquired after 100 milliseconds!\n"); + * } + * } + * } + * \endcode */ template bool try_lock_until(const std::chrono::time_point& abs_time) { return take(std::max(static_cast(0), (abs_time - Clock::now()).count())); } + + ~RecursiveMutex(); ///@} }; @@ -591,7 +1933,57 @@ class MutexVar { * constructor arguments. * * \param args - The arguments to provide to the Var constructor. + * The arguments to provide to the Var constructor. + * + * \b Example + * \code + * // We create a pose class to contain all our odometry data in a single + * // variable that can be protected by a MutexVar. Otherwise, we would have + * // three seperate variables which could not be protected in a single + * // MutexVar + * struct Pose { + * double x; + * double y; + * double heading; + * } + * + * pros::MutexVar odom_pose(0.0, 0.0, 0.0); + * + * void odom_task(void* param) { + * while(true) { + * Pose old_pose = *odom_pose.lock(); + * + * Pose new_pose{0.0, 0.0, 0.0}; + * + * // --- Calculate new pose for the robot here --- + * + * // Now that we have the new pose, we can update the global variables + * + * *odom_pose.take() = new_pose; + * + * delay(10); + * } + * } + * + * void chassis_task(void* param) { + * while(true) { + * + * Pose cur_pose = *odom_pose.take(); + * + * // ---- Move the robot using the current locations goes here ---- + * + * delay(10); + * } + * } + * + * void initialize() { + * odom_mutex = pros::Mutex(); + * + * pros::Task odom_task(odom_task, "Odometry Task"); + * pros::Task chassis_task(odom_task, "Chassis Control Task"); + * } + * + * \endcode */ template MutexVar(Args&&... args) : mutex(), var(std::forward(args)...) {} @@ -605,6 +1997,26 @@ class MutexVar { * * \return A std::optional which contains a MutexVarLock providing access to * the protected variable if locking is successful. + * + * \b Example + * \code + * pros::MutexVar odom_pose; + * + * void my_task(void* param) { + * while(true) { + * std::optional> cur_pose_opt = odom_pose.try_lock(100); + * + * if(cur_pose_opt.has_value()) { + * Pose* cur_pose = **cur_pose_opt; + * } + * else { + * printf("Could not lock the mutex var!"); + * } + * + * pros::delay(10); + * } + * } + * \endcode */ std::optional> try_lock(std::uint32_t timeout) { if (mutex.take(timeout)) { @@ -623,6 +2035,27 @@ class MutexVar { * * \return A std::optional which contains a MutexVarLock providing access to * the protected variable if locking is successful. + * + * \b Example + * \code + * pros::MutexVar odom_pose; + * + * void my_task(void* param) { + * while(true) { + * std::chrono::duration timeout(100); + * std::optional> cur_pose_opt = odom_pose.try_lock(timeout); + * + * if(cur_pose_opt.has_value()) { + * Pose* cur_pose = **cur_pose_opt; + * } + * else { + * printf("Could not lock the mutex var!"); + * } + * + * pros::delay(10); + * } + * } + * \endcode */ template std::optional> try_lock(const std::chrono::duration& rel_time) { @@ -633,6 +2066,22 @@ class MutexVar { * Lock the mutex-protected variable, waiting indefinitely. * * \return A MutexVarLock providing access to the protected variable. + * + * \b Example + * \code + * pros::MutexVar odom_pose; + * + * void my_task(void* param) { + * while(true) { + * pros::delay(10); + * + * pros::MutexVarLock cur_pose = odom_pose.lock(); + * Pose cur_pose = *cur_pose; + * + * // do stuff with cur_pose + * } + * } + * \endcode */ MutexVarLock lock() { while (!mutex.take(TIMEOUT_MAX)) diff --git a/include/pros/screen.h b/include/pros/screen.h index 4370017..c1e567b 100644 --- a/include/pros/screen.h +++ b/include/pros/screen.h @@ -6,7 +6,7 @@ * * Contains user calls to the v5 screen for touching and displaying graphics. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -79,16 +79,11 @@ typedef enum { * Struct representing screen touch status, screen last x, screen last y, press count, release count. */ typedef struct screen_touch_status_s { - /// Represents if the screen is being held, released, or pressed. - last_touch_e_t touch_status; - /// Represents the x value of the location of the touch. - int16_t x; - /// Represents the y value of the location of the touch. - int16_t y; - /// Represents how many times the screen has be pressed. - int32_t press_count; - /// Represents how many times the user released after a touch on the screen. - int32_t release_count; + last_touch_e_t touch_status; ///< Represents if the screen is being held, released, or pressed. + int16_t x; ///< Represents the x value of the location of the touch. + int16_t y; ///< Represents the y value of the location of the touch. + int32_t press_count; ///< Represents how many times the screen has be pressed. + int32_t release_count; ///< Represents how many times the user released after a touch on the screen. } screen_touch_status_s_t; #ifdef PROS_USE_SIMPLE_NAMES @@ -97,7 +92,7 @@ typedef struct screen_touch_status_s { #define TEXT_MEDIUM pros::E_TEXT_MEDIUM #define TEXT_LARGE pros::E_TEXT_LARGE #define TEXT_MEDIUM_CENTER pros::E_TEXT_MEDIUM_CENTER -#define TEXT_LARGE_CENTER pros::E_LARGE_CENTER +#define TEXT_LARGE_CENTER pros::E_TEXT_LARGE_CENTER #define TOUCH_RELEASED pros::E_TOUCH_RELEASED #define TOUCH_PRESSED pros::E_TOUCH_PRESSED #define TOUCH_HELD pros::E_TOUCH_HELD @@ -146,7 +141,7 @@ namespace c { * int iter = 0; * while(1){ * // This should print in red. - * screen_print_line(TEXT_MEDIUM, 1, "%d", iter++); + * screen_print(TEXT_MEDIUM, 1, "%d", iter++); * } * } * \endcode @@ -223,7 +218,7 @@ uint32_t screen_get_pen(void); * \b Example * \code * void initialize() { - * screen_set_pen(COLOR_RED); + * screen_set_eraser(COLOR_RED); * } * * void opcontrol() { @@ -311,7 +306,7 @@ uint32_t screen_scroll(int16_t start_line, int16_t lines); * void opcontrol() { * screen_print(TEXT_MEDIUM, 1, "Line Here"); * // Scrolls area of screen upwards slightly. including line of text - * screen_scroll(0,0, 400, 200, 3); + * screen_scroll_area(0,0, 400, 200, 3); * } * \endcode */ @@ -356,8 +351,7 @@ uint32_t screen_copy_area(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32 * reached: * EACCESS - Another resource is currently trying to access the screen mutex. * - * \param x The (x,y) coordinates of the pixel - * \param y The (x,y) coordinates of the pixel + * \param x, y The (x,y) coordinates of the pixel * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. @@ -421,6 +415,7 @@ uint32_t screen_erase_pixel(int16_t x, int16_t y); * \b Example * \code * void opcontrol() { + * screen_set_pen(COLOR_RED); * // Draw line down the screen at x = 100 * screen_draw_line(100,0,100,200); * } @@ -470,7 +465,6 @@ uint32_t screen_erase_line(int16_t x0, int16_t y0, int16_t x1, int16_t y1); * \b Example * \code * void opcontrol() { - * // Color the Screen in Red * screen_set_pen(COLOR_RED); * screen_draw_rect(1,1,480,200); * } @@ -690,6 +684,7 @@ uint32_t screen_print_at(text_format_e_t txt_fmt, const int16_t x, const int16_t * \return 1 if there were no errors, or PROS_ERR if an error occured * while taking or returning the screen mutex. * + * */ uint32_t screen_vprintf(text_format_e_t txt_fmt, const int16_t line, const char* text, va_list args); diff --git a/include/pros/screen.hpp b/include/pros/screen.hpp index bd8231f..cbfe2fc 100644 --- a/include/pros/screen.hpp +++ b/include/pros/screen.hpp @@ -6,7 +6,7 @@ * * Contains user calls to the v5 screen for touching and displaying graphics. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -68,6 +68,22 @@ const char* convert_args(const std::string& arg) { * * \return Returns 1 if the mutex was successfully returned, or PROS_ERR if * there was an error either taking or returning the screen mutex. + * + * \b Example + * \code + * void initialize() { + * pros::screen::set_pen(red); + * } + * + * void opcontrol() { + * int iter = 0; + * while(1){ + * // This should print in red. + * pros::screen::print(TEXT_MEDIUM, 1, "%d", iter++); + * } + * } + * + * \endcode */ std::uint32_t set_pen(pros::Color color); @@ -82,6 +98,23 @@ const char* convert_args(const std::string& arg) { * * \return Returns 1 if the mutex was successfully returned, or PROS_ERR if * there was an error either taking or returning the screen mutex. + * + * \b Example + * \code + * void initialize() { + * //set pen color to red + * pros::screen::set_pen(0x00FF0000); + * } + * + * void opcontrol() { + * int iter = 0; + * while(1){ + * // This should print in red. + * pros::screen::print(TEXT_MEDIUM, 1, "%d", iter++); + * } + * } + * + * \endcode */ std::uint32_t set_pen(std::uint32_t color); @@ -97,6 +130,23 @@ const char* convert_args(const std::string& arg) { * * \return Returns 1 if the mutex was successfully returned, or PROS_ERR * if there was an error either taking or returning the screen mutex. + * + * \b Example + * \code + * void initialize() { + * //set eraser color to red + * set_eraser(red); + * } + * + * void opcontrol() { + * int iter = 0; + * while(1){ + * // This should print in red. + * pros::screen::print(TEXT_MEDIUM, 1, "%d", iter++); + * } + * } + * + * \endcode */ std::uint32_t set_eraser(pros::Color color); @@ -111,6 +161,21 @@ const char* convert_args(const std::string& arg) { * * \return Returns 1 if the mutex was successfully returned, or PROS_ERR * if there was an error either taking or returning the screen mutex. + * + * \b Example + * \code + * void initialize() { + * //set eraser color to red + * pros::screen::set_eraser(0x00FF0000); + * } + * + * void opcontrol() { + * while(1){ + * // This should turn the screen red. + * pros::screen::erase(); + * } + * } + * \endcode */ std::uint32_t set_eraser(std::uint32_t color); @@ -124,6 +189,20 @@ const char* convert_args(const std::string& arg) { * \return The current pen color in the form of a value from the enum * defined in colors.h, or PROS_ERR if there was an error taking or * returning the screen mutex. + * + * \b Example + * \code + * void initialize() { + * pros::screen::set_pen(red); + * } + * + * void opcontrol() { + * while(1){ + * // Should print number equivalent to red defined in colors.hpp. + * pros::screen::print(TEXT_MEDIUM, 1, "%d", get_pen()); + * } + * } + * \endcode */ std::uint32_t get_pen(); @@ -137,6 +216,20 @@ const char* convert_args(const std::string& arg) { * \return The current eraser color in the form of a value from the enum * defined in colors.h, or PROS_ERR if there was an error taking or * returning the screen mutex. + * + * \b Example + * \code + * void initialize() { + * pros::screen::set_eraser(red); + * } + * + * void opcontrol() { + * while(1){ + * // Should print number equivalent to red defined in colors.h. + * pros::screen::print(TEXT_MEDIUM, 1, "%d", get_eraser()); + * } + * } + * \endcode */ std::uint32_t get_eraser(); @@ -149,6 +242,20 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * * \b Example + * \code + * void initialize() { + * pros::screen::set_eraser(red); + * } + * + * void opcontrol() { + * while(1){ + * // This should turn the screen red. + * pros::screen::erase(); + * } + * } + * \endcode */ std::uint32_t erase(); @@ -164,6 +271,15 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * pros::screen::print(TEXT_MEDIUM, 4, "Line Here"); + * // Scroll 3 lines + * pros::screen::scroll(4, 3); + * } + * \endcode */ std::uint32_t scroll(const std::int16_t start_line, const std::int16_t lines); @@ -186,6 +302,15 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * pros::screen::print(TEXT_MEDIUM, 1, "Line Here"); + * // Scrolls area of screen upwards slightly. including line of text + * pros::screen::scroll_area(0,0, 400, 200, 3); + * } + * \endcode */ std::uint32_t scroll_area(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1, std::int16_t lines); @@ -207,6 +332,17 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured taking * or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * uint32_t* buf = malloc(sizeof(uint32_t) * 400 * 200); + * pros::screen::print(TEXT_MEDIUM, 1, "Line Here"); + * // Copies area of the screen including text + * pros::screen::copy_area(0, 0, 400, 200, (uint32_t*)buf, 400 + 1); + * // Equation for stride is x2 - x1 + 1 + * } + * \endcode */ std::uint32_t copy_area(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1, uint32_t* buf, const std::int32_t stride); @@ -221,6 +357,18 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * int i = 0; + * void opcontrol() { + * while(i < 200){ + * pros::screen::draw_pixel(100,i++); + * // Draws a line at x = 100 gradually down the screen, pixel by pixel + * pros::delay(200); + * } + * } + * \endcode */ std::uint32_t draw_pixel(const std::int16_t x, const std::int16_t y); @@ -235,6 +383,21 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * // Color the Screen in Red + * pros::screen::set_pen(red); + * pros::screen::fill_rect(0,0,400,200); + * int i = 0; + * while(i < 200){ + * pros::screen::erase_pixel(100,i++); + * // Erases a line at x = 100 gradually down the screen, pixel by pixel + * pros::delay(200); + * } + * } + * \endcode */ std::uint32_t erase_pixel(const std::int16_t x, const std::int16_t y); @@ -250,6 +413,15 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * pros::screen::set_pen(red); + * // Draw line down the screen at x = 100 + * pros::screen::draw_line(100,0,100,200); + * } + * \endcode */ std::uint32_t draw_line(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1); @@ -265,6 +437,17 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * // Color the Screen in Red + * pros::screen::set_pen(red); + * pros::screen::fill_rect(0,0,400,200); + * // Erase line down the screen at x = 100 + * pros::screen::erase_line(100,0,100,200); + * } + * \endcode */ std::uint32_t erase_line(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1); @@ -280,6 +463,14 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * pros::screen::set_pen(red); + * pros::screen::draw_rect(1,1,480,200); + * } + * \endcode */ std::uint32_t draw_rect(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1); @@ -295,6 +486,15 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * // Draw Box Around Half the Screen in Red + * pros::screen::set_eraser(red); + * pros::screen::erase_rect(5,5,240,200); + * } + * \endcode */ std::uint32_t erase_rect(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1); @@ -311,6 +511,15 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * // Fill Around Half the Screen in Red + * pros::screen::set_pen(red); + * pros::screen::fill_rect(5,5,240,200); + * } + * \endcode */ std::uint32_t fill_rect(const std::int16_t x0, const std::int16_t y0, const std::int16_t x1, const std::int16_t y1); @@ -326,6 +535,15 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * // Draw a circle with radius of 100 in red + * pros::screen::set_pen(red); + * pros::screen::draw_circle(240, 200, 100); + * } + * \endcode */ std::uint32_t draw_circle(const std::int16_t x, const std::int16_t y, const std::int16_t radius); @@ -341,6 +559,17 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * pros::screen::set_pen(red); + * pros::screen::fill_rect(5,5,240,200); + * // Erase a circle with radius of 100 in blue + * pros::screen::set_pen(blue); + * pros::screen::erase_circle(240, 200, 100); + * } + * \endcode */ std::uint32_t erase_circle(const std::int16_t x, const std::int16_t y, const std::int16_t radius); @@ -357,6 +586,17 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * taking or returning the screen mutex. + * + * \b Example + * \code + * void opcontrol() { + * pros::screen::set_pen(red); + * pros::screen::fill_rect(5,5,240,200); + * // Fill a circlular area with radius of 100 in blue + * pros::screen::set_pen(blue); + * pros::screen::fill_circle(240, 200, 100); + * } + * \endcode */ std::uint32_t fill_circle(const std::int16_t x, const std::int16_t y, const std::int16_t radius); @@ -377,6 +617,18 @@ const char* convert_args(const std::string& arg) { * \param y The (x,y) coordinates of the top left corner of the string * \param fmt Format string * \param ... Optional list of arguments for the format string + * + * \b Example + * \code + * void opcontrol() { + * int i = 0; + * pros::screen::set_pen(blue); + * while(1){ + * // Will print seconds started since program started on line 3 + * pros::screen::print(pros::TEXT_MEDIUM, 3, "Seconds Passed: %3d", i++); + * pros::delay(1000); + * } + * } */ template void print(pros::text_format_e_t txt_fmt, const std::int16_t line, const char* text, Params... args){ @@ -402,6 +654,25 @@ const char* convert_args(const std::string& arg) { * This will be released by default if no action was taken. * If an error occured, the screen_touch_status_s_t will have its * last_touch_e_t enum specifier set to E_TOUCH_ERR, and other values set to -1. + * + * \b Example + * \code + * void opcontrol() { + * int i = 0; + * pros::screen_touch_status_s_t status; + * while(1){ + * status = pros::touch_status(); + * + * // Will print various information about the last touch + * pros::screen::print(TEXT_MEDIUM, 1, "Touch Status (Type): %d", status.touch_status); + * pros::screen::print(TEXT_MEDIUM, 2, "Last X: %d", status.x); + * pros::screen::print(TEXT_MEDIUM, 3, "Last Y: %d", status.y); + * pros::screen::print(TEXT_MEDIUM, 4, "Press Count: %d", status.press_count); + * pros::screen::print(TEXT_MEDIUM, 5, "Release Count: %d", status.release_count); + * pros::delay(20); + * } + * } + * \endcode */ screen_touch_status_s_t touch_status(); @@ -417,6 +688,22 @@ const char* convert_args(const std::string& arg) { * * \return 1 if there were no errors, or PROS_ERR if an error occured * while taking or returning the screen mutex. + * + * \b Example + * \code + * touch_event_cb_fn_t changePixel(){ + * pros::screen_touch_status_s_t status = pros::screen::touch_status(); + * pros::screen::draw_pixel(status.x,status.y); + * return NULL; + * } + * + * void opcontrol() { + * pros::screen::touch_callback(changePixel(), TOUCH_PRESSED); + * while(1) { + * pros::delay(20); + * } + * } + * \endcode */ std::uint32_t touch_callback(touch_event_cb_fn_t cb, last_touch_e_t event_type); diff --git a/include/pros/serial.h b/include/pros/serial.h index ae91d47..4bda606 100644 --- a/include/pros/serial.h +++ b/include/pros/serial.h @@ -4,13 +4,10 @@ * * Contains prototypes for the V5 Generic Serial related functions. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/serial.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -60,6 +57,14 @@ namespace c { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * } + * \endcode */ int32_t serial_enable(uint8_t port); @@ -78,6 +83,18 @@ int32_t serial_enable(uint8_t port); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * serial_write(1, "Hello World!", 12); + * delay(100); + * } + * } + * \endcode */ int32_t serial_set_baudrate(uint8_t port, int32_t baudrate); @@ -103,6 +120,19 @@ int32_t serial_set_baudrate(uint8_t port, int32_t baudrate); * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * serial_flush(1); + * serial_write(1, "Hello World!", 12); + * delay(100); + * } + * } + * \endcode */ int32_t serial_flush(uint8_t port); @@ -123,6 +153,23 @@ int32_t serial_flush(uint8_t port); * * \return The number of bytes avaliable to be read or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_get_read_avail(1) >= 12) { + * char buffer[12]; + * serial_read(1, buffer, 12); + * printf("%s", buffer); + * } + * delay(100); + * } + * } + * \endcode + */ int32_t serial_get_read_avail(uint8_t port); @@ -142,6 +189,20 @@ int32_t serial_get_read_avail(uint8_t port); * * \return The number of bytes free or PROS_ERR if the operation failed, * setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_get_write_free(1) >= 12) { + * serial_write(1, "Hello World!", 12); + * } + * delay(100); + * } + * } + * \endcode */ int32_t serial_get_write_free(uint8_t port); @@ -158,6 +219,22 @@ int32_t serial_get_write_free(uint8_t port); * * \return The next byte avaliable to be read, -1 if none are available, or * PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_peek_byte(1) == 'H') { + * char buffer[12]; + * serial_read(1, buffer, 12); + * printf("%s", buffer); + * } + * delay(100); + * } + * } + * \endcode */ int32_t serial_peek_byte(uint8_t port); @@ -174,6 +251,22 @@ int32_t serial_peek_byte(uint8_t port); * * \return The next byte avaliable to be read, -1 if none are available, or * PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_read_byte(1) == 'H') { + * char buffer[12]; + * serial_read(1, buffer, 12); + * printf("%s", buffer); + * } + * delay(100); + * } + * } + * \endcode */ int32_t serial_read_byte(uint8_t port); @@ -198,6 +291,22 @@ int32_t serial_read_byte(uint8_t port); * * \return The number of bytes read or PROS_ERR if the operation failed, setting * errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_get_read_avail(1) >= 12) { + * char buffer[12]; + * serial_read(1, buffer, 12); + * printf("%s", buffer); + * } + * delay(100); + * } + * } + * \endcode */ int32_t serial_read(uint8_t port, uint8_t* buffer, int32_t length); @@ -220,6 +329,32 @@ int32_t serial_read(uint8_t port, uint8_t* buffer, int32_t length); * * \return The number of bytes written or PROS_ERR if the operation failed, * setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_get_write_free(1) >= 12) { + * serial_write_byte(1, 'H'); + * serial_write_byte(1, 'e'); + * serial_write_byte(1, 'l'); + * serial_write_byte(1, 'l'); + * serial_write_byte(1, 'o'); + * serial_write_byte(1, ' '); + * serial_write_byte(1, 'W'); + * serial_write_byte(1, 'o'); + * serial_write_byte(1, 'r'); + * serial_write_byte(1, 'l'); + * serial_write_byte(1, 'd'); + * serial_write_byte(1, '!'); + * serial_write_byte(1, '\n'); + * } + * delay(100); + * } + * } + * \endcode */ int32_t serial_write_byte(uint8_t port, uint8_t buffer); @@ -245,6 +380,20 @@ int32_t serial_write_byte(uint8_t port, uint8_t buffer); * * \return The number of bytes written or PROS_ERR if the operation failed, * setting errno. + * + * \b Example: + * \code{.c} + * void opcontrol() { + * serial_enable(1); + * serial_set_baudrate(1, 9600); + * while (true) { + * if (serial_get_write_free(1) >= 12) { + * serial_write(1, "Hello World!\n", 12); + * } + * delay(100); + * } + * } + * \endcode */ int32_t serial_write(uint8_t port, uint8_t* buffer, int32_t length); diff --git a/include/pros/serial.hpp b/include/pros/serial.hpp index 95b20c1..1996aef 100644 --- a/include/pros/serial.hpp +++ b/include/pros/serial.hpp @@ -4,18 +4,15 @@ * * Contains prototypes for the V5 Generic Serial related functions. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/serial.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * + * * \defgroup cpp-serial Generic Serial C++ API */ @@ -23,8 +20,9 @@ #define _PROS_SERIAL_HPP_ #include -#include "pros/serial.h" + #include "pros/device.hpp" +#include "pros/serial.h" namespace pros { /** @@ -49,9 +47,30 @@ class Serial : public Device { * The V5 port number from 1-21 * \param baudrate * The baudrate to run the port at + * + * \b Example: + * \code + * pros::Serial serial(1, 9600); + * \endcode */ explicit Serial(std::uint8_t port, std::int32_t baudrate); + /** + * Creates a Serial object for the given port without a set baudrate. + * + * This function uses the following values of errno when an error state is + * reached: + * EINVAL - The given value is not within the range of V5 ports (1-21). + * EACCES - Another resource is currently trying to access the port. + * + * \param port + * The V5 port number from 1-21 + * + * \b Example: + * \code + * pros::Serial serial(1); + * \endcode + */ explicit Serial(std::uint8_t port); /******************************************************************************/ @@ -73,6 +92,12 @@ class Serial : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code + * pros::Serial serial(1); + * serial.set_baudrate(9600); + * \endcode */ virtual std::int32_t set_baudrate(std::int32_t baudrate) const; @@ -95,6 +120,12 @@ class Serial : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code + * pros::Serial serial(1); + * serial.flush(); + * \endcode */ virtual std::int32_t flush() const; @@ -112,6 +143,16 @@ class Serial : public Device { * * \return The number of bytes avaliable to be read or PROS_ERR if the operation * failed, setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * if(serial.get_read_avail() > 0) { + * std::uint8_t byte = serial.read_byte(); + * } + * } + * \endcode */ virtual std::int32_t get_read_avail() const; @@ -128,6 +169,17 @@ class Serial : public Device { * * \return The number of bytes free or PROS_ERR if the operation failed, * setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * if(serial.get_write_free() > 0) { + * serial.write_byte(0x01); + * pros::delay(10); + * } + * } + * \endcode */ virtual std::int32_t get_write_free() const; @@ -141,6 +193,16 @@ class Serial : public Device { * * \return The next byte avaliable to be read, -1 if none are available, or * PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * if(serial.peek_byte() == 0x01) { + * serial.read_byte(); + * } + * } + * \endcode */ virtual std::int32_t peek_byte() const; @@ -154,6 +216,16 @@ class Serial : public Device { * * \return The next byte avaliable to be read, -1 if none are available, or * PROS_ERR if the operation failed, setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * if(serial.read_byte() == 0x01) { + * // Do something + * } + * } + * \endcode */ virtual std::int32_t read_byte() const; @@ -176,6 +248,15 @@ class Serial : public Device { * * \return The number of bytes read or PROS_ERR if the operation failed, setting * errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * std::uint8_t buffer[10]; + * serial.read(buffer, 10); + * } + * \endcode */ virtual std::int32_t read(std::uint8_t* buffer, std::int32_t length) const; @@ -196,6 +277,14 @@ class Serial : public Device { * * \return The number of bytes written or PROS_ERR if the operation failed, * setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * serial.write_byte(0x01); + * } + * \endcode */ virtual std::int32_t write_byte(std::uint8_t buffer) const; @@ -219,14 +308,36 @@ class Serial : public Device { * * \return The number of bytes written or PROS_ERR if the operation failed, * setting errno. + * + * \b Example: + * \code + * void opcontrol() { + * pros::Serial serial(1); + * std::uint8_t buffer[10]; + * serial.write(buffer, 10); + * } + * \endcode */ virtual std::int32_t write(std::uint8_t* buffer, std::int32_t length) const; - + private: ///@} }; namespace literals { +/** + * Constructs a Serial device from a litteral ending in _ser + * + * \return a pros::Serial for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Serial serial = 2_ser; //Makes an Serial device object on port 2 + * } + * \endcode + */ const pros::Serial operator"" _ser(const unsigned long long int m); } // namespace literals } // namespace pros diff --git a/include/pros/version.h b/include/pros/version.h new file mode 100644 index 0000000..682aee0 --- /dev/null +++ b/include/pros/version.h @@ -0,0 +1,23 @@ +/** +* \file version.h +* +* PROS Version Information +* +* Contains PROS kernel version information +* +* +* \copyright Copyright (c) 2017-2024, Purdue University ACM SIGBots. +* All rights reserved. +* +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#pragma once + +#define PROS_VERSION_MAJOR 4 +#define PROS_VERSION_MINOR 1 + +#define PROS_VERSION_PATCH 0 +#define PROS_VERSION_STRING "4.1.0" \ No newline at end of file diff --git a/include/pros/vision.h b/include/pros/vision.h index ce853e7..6b3f104 100644 --- a/include/pros/vision.h +++ b/include/pros/vision.h @@ -4,13 +4,10 @@ * * Contains prototypes for the VEX Vision Sensor-related functions. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public @@ -378,9 +375,7 @@ vision_object_s_t vision_get_by_sig(uint8_t port, const uint32_t size_id, const vision_object_s_t vision_get_by_code(uint8_t port, const uint32_t size_id, const vision_color_code_t color_code); /** - * Gets the exposure parameter of the Vision Sensor. See - * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting - * for more detials. + * Gets the exposure parameter of the Vision Sensor. * * This function uses the following values of errno when an error state is * reached: @@ -703,9 +698,7 @@ int32_t vision_set_signature(uint8_t port, const uint8_t signature_id, vision_si int32_t vision_set_auto_white_balance(uint8_t port, const uint8_t enable); /** - * Sets the exposure parameter of the Vision Sensor. See - * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting - * for more detials. + * Sets the exposure parameter of the Vision Sensor. * * This function uses the following values of errno when an error state is * reached: diff --git a/include/pros/vision.hpp b/include/pros/vision.hpp index d38c836..0a845f6 100644 --- a/include/pros/vision.hpp +++ b/include/pros/vision.hpp @@ -4,13 +4,10 @@ * * Contains prototypes for the VEX Vision Sensor-related functions in C++. * - * Visit https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html to learn - * more. - * * This file should not be modified by users, since it gets replaced whenever * a kernel upgrade occurs. * - * \copyright (c) 2017-2023, Purdue University ACM SIGBots. + * \copyright (c) 2017-2024, Purdue University ACM SIGBots. * All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public @@ -26,6 +23,7 @@ #include +#include "pros/device.hpp" #include "pros/vision.h" namespace pros { @@ -51,8 +49,17 @@ class Vision : public Device { * The V5 port number from 1-21 * \param zero_point * One of vision_zero_e_t to set the (0,0) coordinate for the FOV + * + * \b Example + * \code + * void opcontrol() { + * pros::Vision vision_sensor(1); // Creates a vision sensor on port one, with the zero point set to top left + * } + * \endcode */ - explicit Vision(std::uint8_t port, vision_zero_e_t zero_point = E_VISION_ZERO_TOPLEFT); + Vision(std::uint8_t port, vision_zero_e_t zero_point = E_VISION_ZERO_TOPLEFT); + + Vision(const Device& device) : Vision(device.get_port()){}; /** * Clears the vision sensor LED color, reseting it back to its default @@ -64,6 +71,14 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * void initialize() { + * pros::Vision vision_sensor(1); + * vision_sensor.clear_led(); + * } + * \endcode */ std::int32_t clear_led(void) const; @@ -90,6 +105,27 @@ class Vision : public Device { * Signature type * * \return A vision_signature_s_t that can be set using Vision::set_signature + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * // values acquired from the vision utility + * vision_signature_s_t RED_SIG = + * vision_signature_from_utility(EXAMPLE_SIG, 8973, 11143, 10058, -2119, -1053, -1586, 5.4, 0); + * vision_sensor.set_signature(EXAMPLE_SIG, &RED_SIG); + * while (true) { + * vision_signature_s_t rtn = vision_sensor.get_by_sig(VISION_PORT, 0, EXAMPLE_SIG); + * // Gets the largest object of the EXAMPLE_SIG signature + * printf("sig: %d", rtn.signature); + * // Prints "sig: 1" + * delay(2); + * } + * } + * \endcode */ static vision_signature_s_t signature_from_utility(const std::int32_t id, const std::int32_t u_min, const std::int32_t u_max, const std::int32_t u_mean, @@ -118,11 +154,37 @@ class Vision : public Device { * The fifth signature id [1-7] to add to the color code * * \return A vision_color_code_t object containing the color code information. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * #define OTHER_SIG 2 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_color_code_t code1 = vision_sensor.create_color_code(EXAMPLE_SIG, OTHER_SIG); + * } + * \endcode */ vision_color_code_t create_color_code(const std::uint32_t sig_id1, const std::uint32_t sig_id2, const std::uint32_t sig_id3 = 0, const std::uint32_t sig_id4 = 0, const std::uint32_t sig_id5 = 0) const; + /** + * Gets all vision sensors. + * + * \return A vector of Vision sensor objects. + * + * \b Example + * \code + * void opcontrol() { + * std::vector vision_all = pros::Vision::get_all_devices(); // All vision sensors that are connected + * } + * \endcode + */ + static std::vector get_all_devices(); + /** * Gets the nth largest object according to size_id. * @@ -138,6 +200,21 @@ class Vision : public Device { * * \return The vision_object_s_t object corresponding to the given size id, or * PROS_ERR if an error occurred. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * while (true) { + * vision_object_s_t rtn = vision_sensor.get_by_size(0); + * // Gets the largest object + * printf("sig: %d", rtn.signature); + * delay(2); + * } + * } + * \endcode */ vision_object_s_t get_by_size(const std::uint32_t size_id) const; @@ -160,6 +237,23 @@ class Vision : public Device { * * \return The vision_object_s_t object corresponding to the given signature * and size_id, or PROS_ERR if an error occurred. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * while (true) { + * vision_object_s_t rtn = vision_sensor.get_by_sig(0, EXAMPLE_SIG); + * // Gets the largest object of the EXAMPLE_SIG signature + * printf("sig: %d", rtn.signature); + * // Prints "sig: 1" + * delay(2); + * } + * } + * \endcode */ vision_object_s_t get_by_sig(const std::uint32_t size_id, const std::uint32_t sig_id) const; @@ -179,13 +273,29 @@ class Vision : public Device { * * \return The vision_object_s_t object corresponding to the given color code * and size_id, or PROS_ERR if an error occurred. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * #define OTHER_SIG 2 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_color_code_t code1 = vision_sensor.create_color_code(EXAMPLE_SIG, OTHER_SIG); + * while (true) { + * vision_object_s_t rtn = vision_sensor.get_by_code(0, code1); + * // Gets the largest object + * printf("sig: %d", rtn.signature); + * delay(2); + * } + * } + * \endcode */ vision_object_s_t get_by_code(const std::uint32_t size_id, const vision_color_code_t color_code) const; /** - * Gets the exposure parameter of the Vision Sensor. See - * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting - * for more detials. + * Gets the exposure parameter of the Vision Sensor. * * This function uses the following values of errno when an error state is * reached: @@ -193,6 +303,17 @@ class Vision : public Device { * * \return The current exposure parameter from [0,150], * PROS_ERR if an error occurred + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * if (vision_sensor.get_exposure() < 50) + * vision_sensor.set_exposure(50); + * } + * \endcode */ std::int32_t get_exposure(void) const; @@ -205,6 +326,19 @@ class Vision : public Device { * * \return The number of objects detected on the specified vision sensor. * Returns PROS_ERR if the port was invalid or an error occurred. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * while (true) { + * printf("Number of Objects Detected: %d\n", vision_sensor.get_object_count()); + * delay(2); + * } + * } + * \endcode */ std::int32_t get_object_count(void) const; @@ -219,6 +353,18 @@ class Vision : public Device { * The signature id to read * * \return A vision_signature_s_t containing information about the signature. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_signature_s_t sig = vision_sensor.get_signature(EXAMPLE_SIG); + * vision_sensor.print_signature(sig); + * } + * \endcode */ vision_signature_s_t get_signature(const std::uint8_t signature_id) const; @@ -230,10 +376,21 @@ class Vision : public Device { * ENODEV - The port cannot be configured as a vision sensor * * \return The current RGB white balance setting of the sensor + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define VISION_WHITE 0xff + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * if (vision_sensor.get_white_balance() != VISION_WHITE) + * vision_sensor.set_white_balance(VISION_WHITE); + * } + * \endcode */ std::int32_t get_white_balance(void) const; - /** * Reads up to object_count object descriptors into object_arr. * @@ -256,6 +413,23 @@ class Vision : public Device { * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects * than size_id were found. All objects in object_arr that were not found are * given VISION_OBJECT_ERR_SIG as their signature. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define NUM_VISION_OBJECTS 4 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_object_s_t object_arr[NUM_VISION_OBJECTS]; + * while (true) { + * vision_sensor.read_by_size(0, NUM_VISION_OBJECTS, object_arr); + * printf("sig: %d", object_arr[0].signature); + * // Prints the signature of the largest object found + * delay(2); + * } + * } + * \endcode */ std::int32_t read_by_size(const std::uint32_t size_id, const std::uint32_t object_count, vision_object_s_t* const object_arr) const; @@ -286,6 +460,24 @@ class Vision : public Device { * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects * than size_id were found. All objects in object_arr that were not found are * given VISION_OBJECT_ERR_SIG as their signature. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * #define NUM_VISION_OBJECTS 4 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_object_s_t object_arr[NUM_VISION_OBJECTS]; + * while (true) { + * vision_sensor.read_by_sig(0, EXAMPLE_SIG, NUM_VISION_OBJECTS, object_arr); + * printf("sig: %d", object_arr[0].signature); + * // Prints "sig: 1" + * delay(2); + * } + * } + * \endcode */ std::int32_t read_by_sig(const std::uint32_t size_id, const std::uint32_t sig_id, const std::uint32_t object_count, vision_object_s_t* const object_arr) const; @@ -314,6 +506,26 @@ class Vision : public Device { * Returns PROS_ERR if the port was invalid, an error occurred, or fewer objects * than size_id were found. All objects in object_arr that were not found are * given VISION_OBJECT_ERR_SIG as their signature. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * #define OTHER_SIG 2 + * #define NUM_VISION_OBJECTS 4 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_object_s_t object_arr[NUM_VISION_OBJECTS]; + * vision_color_code_t code1 = vision_sensor.create_color_code(EXAMPLE_SIG, OTHER_SIG, 0, 0, 0); + * while (true) { + * vision_sensor.read_by_code(0, code1, NUM_VISION_OBJECTS, object_arr); + * printf("sig: %d", object_arr[0].signature); + * // Prints the signature of the largest object found + * delay(2); + * } + * } + * \endcode */ int32_t read_by_code(const std::uint32_t size_id, const vision_color_code_t color_code, const std::uint32_t object_count, vision_object_s_t* const object_arr) const; @@ -325,6 +537,18 @@ class Vision : public Device { * The signature for which the contents will be printed * * \return 1 if no errors occured, PROS_ERR otherwise + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_signature_s_t sig = visionsensor.get_signature(EXAMPLE_SIG); + * vision_print_signature(sig); + * } + * \endcode */ static std::int32_t print_signature(const vision_signature_s_t sig); @@ -340,13 +564,21 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_sensor.set_auto_white_balance(true); + * } + * \endcode */ std::int32_t set_auto_white_balance(const std::uint8_t enable) const; /** - * Sets the exposure parameter of the Vision Sensor. See - * https://pros.cs.purdue.edu/v5/tutorials/topical/vision.html#exposure-setting - * for more detials. + * Sets the exposure parameter of the Vision Sensor. * * This function uses the following values of errno when an error state is * reached: @@ -357,6 +589,17 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * if (vision_sensor.get_exposure() < 50) + * vision_sensor.set_exposure(50); + * } + * \endcode */ std::int32_t set_exposure(const std::uint8_t exposure) const; @@ -372,6 +615,16 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_sensor.set_led(COLOR_BLANCHED_ALMOND); + * } + * \endcode */ std::int32_t set_led(const std::int32_t rgb) const; @@ -392,6 +645,19 @@ class Vision : public Device { * A pointer to the signature to save * * \return 1 if no errors occured, PROS_ERR otherwise + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define EXAMPLE_SIG 1 + * + * void opcontrol() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_signature_s_t sig = vision_sensor.get_signature(EXAMPLE_SIG); + * sig.range = 10.0; + * vision_sensor.set_signature(EXAMPLE_SIG, &sig); + * } + * \endcode */ std::int32_t set_signature(const std::uint8_t signature_id, vision_signature_s_t* const signature_ptr) const; @@ -407,6 +673,17 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define VISION_PORT 1 + * #define VISION_WHITE 0xff + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_sensor.set_white_balance(VISION_WHITE); + * } + * \endcode */ std::int32_t set_white_balance(const std::int32_t rgb) const; @@ -426,6 +703,16 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_sensor.set_zero_point(E_VISION_ZERO_CENTER); + * } + * \endcode */ std::int32_t set_zero_point(vision_zero_e_t zero_point) const; @@ -441,12 +728,60 @@ class Vision : public Device { * * \return 1 if the operation was successful or PROS_ERR if the operation * failed, setting errno. + * + * \b Example + * \code + * #define VISION_PORT 1 + * + * void initialize() { + * pros::Vision vision_sensor(VISION_PORT); + * vision_sensor.set_wifi_mode(0); + * } + * \endcode */ std::int32_t set_wifi_mode(const std::uint8_t enable) const; - + + /** + * Gets a vision sensor that is plugged in to the brain + * + * \note The first time this function is called it returns the vision sensor at the lowest port + * If this function is called multiple times, it will cycle through all the ports. + * For example, if you have 1 vision sensor on the robot + * this function will always return a vision sensor object for that port. + * If you have 2 vision sensors, all the odd numered calls to this function will return objects + * for the lower port number, + * all the even number calls will return vision objects for the higher port number + * + * + * This functions uses the following values of errno when an error state is + * reached: + * ENODEV - No vision sensor is plugged into the brain + * + * \return A vision object corresponding to a port that a vision sensor is connected to the brain + * If no vision sensor is plugged in, it returns a vision sensor on port PROS_ERR_BYTE + * + */ + static Vision get_vision(); + private: ///@} }; } // namespace v5 +namespace literals { +/** + * Constructs a Vision sensor from a litteral ending in _vis + * + * \return a pros::Vision for the corresponding port + * + * \b Example + * \code + * using namespace pros::literals; + * void opcontrol() { + * pros::Vision vision = 2_vis; //Makes an Vision sensor object on port 2 + * } + * \endcode + */ +const pros::Vision operator"" _vis(const unsigned long long int m); +} // namespace literals } // namespace pros #endif // _PROS_VISION_HPP_ diff --git a/project.pros b/project.pros index 0c80632..8235272 100644 --- a/project.pros +++ b/project.pros @@ -5,7 +5,7 @@ "target": "v5", "templates": { "kernel": { - "location": "C:\\Users\\stump\\AppData\\Roaming\\PROS\\templates\\kernel@3.7.2-dirty.127.1c0d925", + "location": "/home/alu/.config/pros/templates/kernel@4.2.0", "metadata": { "cold_addr": "58720256", "cold_output": "bin/cold.package.bin", @@ -18,67 +18,70 @@ "py/object": "pros.conductor.templates.local_template.LocalTemplate", "supported_kernels": null, "system_files": [ - "include\\pros\\distance.hpp", - "firmware\\v5.ld", - "firmware\\libc.a", - "include\\pros\\optical.hpp", - "include\\pros\\link.h", - "include\\pros\\misc.hpp", - "include\\pros\\link.hpp", - "include\\pros\\error.h", + "include/api.h", + "include/pros/device.hpp", + "include/pros/device.h", + "include/pros/colors.hpp", + "include/pros/screen.hpp", + "include/pros/misc.hpp", + "include/pros/version.h", + "include/pros/rotation.h", + "include/pros/distance.h", + "include/pros/error.h", + "include/pros/optical.hpp", + "include/pros/rtos.hpp", "common.mk", - "include\\pros\\screen.h", - "include\\pros\\screen.hpp", - "include\\pros\\motor_group.hpp", - "include\\pros\\device.hpp", - "include\\pros\\optical.h", - "include\\pros\\adi.h", - "firmware\\libpros.a", - "include\\api.h", - "include\\pros\\abstract_motor.hpp", - "firmware\\v5-hot.ld", - "include\\pros\\imu.h", - "include\\pros\\vision.hpp", - "include\\pros\\adi.hpp", - "include\\pros\\llemu.h", - "include\\pros\\rtos.hpp", - "include\\pros\\serial.hpp", - "include\\pros\\rtos.h", - "include\\pros\\gps.hpp", - "include\\pros\\motors.h", - "include\\pros\\apix.h", - "include\\pros\\ext_adi.h", - "include\\pros\\vision.h", - "include\\pros\\colors.h", - "firmware\\libm.a", - "include\\pros\\motors.hpp", - "firmware\\v5-common.ld", - "include\\pros\\distance.h", - "include\\pros\\device.h", - "include\\pros\\llemu.hpp", - "include\\pros\\gps.h", - "include\\pros\\misc.h", - "include\\pros\\rotation.hpp", - "include\\pros\\serial.h", - "include\\pros\\imu.hpp", - "include\\pros\\colors.hpp", - "include\\pros\\rotation.h", - "include\\pros\\api_legacy.h" + "include/pros/optical.h", + "firmware/v5.ld", + "include/pros/distance.hpp", + "include/pros/ai_vision.h", + "include/pros/colors.h", + "include/pros/screen.h", + "firmware/v5-hot.ld", + "include/pros/abstract_motor.hpp", + "firmware/libm.a", + "include/pros/serial.h", + "include/pros/imu.hpp", + "include/pros/adi.hpp", + "include/pros/serial.hpp", + "include/pros/apix.h", + "include/pros/rtos.h", + "include/pros/gps.h", + "include/pros/adi.h", + "include/pros/vision.h", + "include/pros/rotation.hpp", + "include/pros/vision.hpp", + "include/pros/motor_group.hpp", + "include/pros/imu.h", + "include/pros/gps.hpp", + "include/pros/ext_adi.h", + "firmware/v5-common.ld", + "include/pros/motors.h", + "include/pros/llemu.hpp", + "include/pros/misc.h", + "include/pros/ai_vision.hpp", + "include/pros/link.h", + "include/pros/llemu.h", + "firmware/libc.a", + "include/pros/link.hpp", + "firmware/libpros.a", + "include/pros/motors.hpp" ], "target": "v5", "user_files": [ - "src\\main.cc", + "include/main.h", + "include/main.hh", ".gitignore", - "include\\main.h", - "include\\main.hpp", - "src\\main.cpp", - "Makefile", - "include\\main.hh", - "src\\main.c" + "src/main.c", + "src/main.cc", + "include/main.hpp", + "src/main.cpp", + "Makefile" ], - "version": "3.7.2-dirty.127.1c0d925" + "version": "4.2.0" } }, - "upload_options": {} + "upload_options": {}, + "use_early_access": false } } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index e219b90..a7d7dd8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,9 +86,9 @@ void opcontrol() { int left = master.get_analog(ANALOG_LEFT_Y); int right = master.get_analog(ANALOG_RIGHT_Y); - left_mtr = left; - right_mtr = right; + left_mtr.move(left); + right_mtr.move(right); pros::delay(20); } -} \ No newline at end of file +}