Program Listing for File ref_serial_data.hpp

Return to documentation for file (src/tap/communication/serial/ref_serial_data.hpp)

/*
 * Copyright (c) 2020-2021 Advanced Robotics at the University of Washington <robomstr@uw.edu>
 *
 * This file is part of Taproot.
 *
 * Taproot is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Taproot is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Taproot.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef TAPROOT_REF_SERIAL_DATA_HPP_
#define TAPROOT_REF_SERIAL_DATA_HPP_

#include <cinttypes>

#include <modm/architecture/interface/register.hpp>

#include "modm/architecture/utils.hpp"

#include "dji_serial.hpp"

namespace tap::communication::serial
{
class RefSerialData
{
public:
    enum class RobotId : uint16_t
    {
        INVALID = 0,

        RED_HERO = 1,
        RED_ENGINEER = 2,
        RED_SOLDIER_1 = 3,
        RED_SOLDIER_2 = 4,
        RED_SOLDIER_3 = 5,
        RED_DRONE = 6,
        RED_SENTINEL = 7,
        RED_DART = 8,
        RED_RADAR_STATION = 9,

        BLUE_HERO = 101,
        BLUE_ENGINEER = 102,
        BLUE_SOLDIER_1 = 103,
        BLUE_SOLDIER_2 = 104,
        BLUE_SOLDIER_3 = 105,
        BLUE_DRONE = 106,
        BLUE_SENTINEL = 107,
        BLUE_DART = 108,
        BLUE_RADAR_STATION = 109
    };

    static inline bool isBlueTeam(RobotId id) { return id >= RobotId::BLUE_HERO; }

    class RobotToRobotMessageHandler
    {
    public:
        RobotToRobotMessageHandler() {}
        virtual void operator()(const DJISerial::ReceivedSerialMessage &message) = 0;
    };

    class Rx
    {
    public:
        enum class GameType : uint8_t
        {
            UNKNOWN = 0,
            ROBOMASTER_RMUC = 1,
            ROBOMASTER_RMUTC = 2,
            ROBOMASTER_AI_CHALLENGE = 3,
            ROBOMASTER_RMUL_3V3 = 4,
            ROBOMASTER_RMUL_1V1 = 5,
        };

        enum class GameStage : uint8_t
        {
            PREMATCH = 0,
            SETUP = 1,
            INITIALIZATION = 2,
            COUNTDOWN = 3,
            IN_GAME = 4,
            END_GAME = 5,
        };

        enum class GameWinner : uint8_t
        {
            DRAW = 0,
            RED = 1,
            BLUE = 2,
        };

        enum class SiteDartHit : uint8_t
        {
            NONE = 0,
            OUTPOST = 1,
            BASE_FIXED = 2,
            BASE_RANDOM = 3
        };

        enum class SupplierOutletStatus : uint8_t
        {
            CLOSED = 0,
            PREPARING = 1,
            RELEASING = 2
        };

        enum class DartTarget : uint8_t
        {
            NONE_OR_OUTPOST = 0,
            BASE_FIXED = 1,
            BASE_RANDOM = 2
        };

        enum class ArmorId : uint8_t
        {
            FRONT = 0,
            LEFT = 1,
            REAR = 2,
            RIGHT = 3,
            TOP = 4,
        };

        enum class DamageType : uint8_t
        {
            ARMOR_DAMAGE = 0,
            MODULE_OFFLINE = 1,
            BARREL_OVER_SPEED = 2,
            BARREL_OVERHEAT = 3,
            CHASSIS_POWER_OVERRUN = 4,
            COLLISION = 5,
        };

        enum class SiteData : uint32_t
        {
            RESTORATION_FRONT_OCCUPIED = modm::Bit0,
            RESTORATION_INSIDE_OCCUPIED = modm::Bit1,
            SUPPLIER_OCCUPIED = modm::Bit2,

            POWER_RUNE_OCCUPIED = modm::Bit3,
            SMALL_POWER_RUNE_ACTIVATED = modm::Bit4,
            LARGER_POWER_RUNE_ACTIVIATED = modm::Bit5,

            RING_OCCUPIED_TEAM = modm::Bit6,
            RING_OCCUPIED_OPPONENT = modm::Bit7,

            TRAPEZOID_R3_OCCUPIED_TEAM = modm::Bit8,
            TRAPEZOID_R3_OCCUPIED_OPPONENT = modm::Bit9,

            TRAPEZOID_R4_OCCUPIED_TEAM = modm::Bit10,
            TRAPEZOID_R4_OCCUPIED_OPPONENT = modm::Bit11,

            CENTRAL_BUFF_OCCUPIED_TEAM = modm::Bit30,
            CENTRAL_BUFF_OCCUPIED_OPPONENT = modm::Bit31
        };
        MODM_FLAGS32(SiteData);

        enum class RobotPower : uint8_t
        {
            GIMBAL_HAS_POWER = modm::Bit0,
            CHASSIS_HAS_POWER = modm::Bit1,
            SHOOTER_HAS_POWER = modm::Bit2,
        };
        MODM_FLAGS8(RobotPower);

        enum class RFIDActivationStatus : uint32_t
        {
            BASE_BUFF = modm::Bit0,
            ELEVATED_RING_OWN = modm::Bit1,
            ELEVATED_RING_OPPONENT = modm::Bit2,
            TRAPEZOID_R3_OWN = modm::Bit3,
            TRAPEZOID_R3_OPPONENT = modm::Bit4,
            TRAPEZOID_R4_OWN = modm::Bit5,
            TRAPEZOID_R4_OPPONENT = modm::Bit6,
            POWER_RUNE_ACTIVATION = modm::Bit7,
            LAUNCH_RAMP_FRONT_OWN = modm::Bit8,
            LAUNCH_RAMP_BACK_OWN = modm::Bit9,
            LAUNCH_RAMP_FRONT_OPPONENT = modm::Bit10,
            LAUNCH_RAMP_BACK_OPPONENT = modm::Bit11,
            OUTPOST_BUFF = modm::Bit12,
            RESTORATION_ZONE = modm::Bit13,
            SENTRY_PATROL_OWN = modm::Bit14,
            SENTRY_PATROL_OPPONENT = modm::Bit15,
            LARGE_ISLAND_OWN = modm::Bit16,
            LARGE_ISLAND_OPPONENT = modm::Bit17,
            EXCHANGE_ZONE = modm::Bit18,
            CENTRAL_BUFF = modm::Bit19
        };
        MODM_FLAGS32(RFIDActivationStatus);

        struct DamageEvent
        {
            uint16_t damageAmount;
            uint32_t timestampMs;
        };

        enum BulletType
        {
            AMMO_17 = 1,
            AMMO_42 = 2,
        };

        enum MechanismID
        {
            TURRET_17MM_1 = 1,
            TURRET_17MM_2 = 2,
            TURRET_42MM = 3,
        };

        static constexpr int MAX_LAUNCH_SPEED_17MM = 30;

        static constexpr int MAX_LAUNCH_SPEED_42MM = 16;

        struct RobotHpData
        {
            struct RobotHp
            {
                uint16_t hero1;
                uint16_t engineer2;
                uint16_t standard3;
                uint16_t standard4;
                uint16_t standard5;
                uint16_t sentry7;
                uint16_t outpost;
                uint16_t base;
            };

            RobotHp red;
            RobotHp blue;
        };

        struct EventData
        {
            SiteData_t siteData;
            uint8_t
                virtualShieldRemainingPercent;
            uint8_t timeSinceLastDartHit;
            SiteDartHit lastDartHit;
        };

        struct SupplierAction
        {
            RobotId reloadingRobot;
            SupplierOutletStatus outletStatus;
            uint8_t suppliedProjectiles;
        };

        struct RobotPosition
        {
            float x;
            float y;
        };

        struct ChassisData
        {
            uint16_t volt;
            uint16_t current;
            float power;
            uint16_t powerBuffer;
            RobotPosition position;
            uint16_t powerConsumptionLimit;
        };

        struct TurretData
        {
            BulletType bulletType;
            MechanismID launchMechanismID;
            uint8_t firingFreq;
            uint16_t heat17ID1;
            uint16_t heat17ID2;
            uint16_t heat42;
            uint16_t heatLimit;
            uint16_t coolingRate;
            uint16_t bulletsRemaining17;
            uint16_t bulletsRemaining42;
            float bulletSpeed;
            float yaw;
            uint32_t lastReceivedLaunchingInfoTimestamp;
        };

        struct RobotBuffStatus
        {
            uint8_t recoveryBuff;
            uint8_t coolingBuff;
            uint8_t defenseBuff;
            uint8_t
                vulnerabilityBuff;
            uint16_t attackBuff;
        };

        struct RefereeWarningData
        {
            uint8_t level;
            RobotId foulRobotID;
            uint8_t count;
            uint32_t lastReceivedWarningRobotTime = 0;

            static constexpr uint32_t OFFENDING_OPERATOR_BLIND_TIME = 5'000;
            static constexpr uint32_t NONOFFENDING_OPERATOR_BLIND_TIME = 2'000;
        };

        struct DartInfo
        {
            uint8_t launchCountdown;
            SiteDartHit lastHit;
            uint8_t hits;
            DartTarget selectedTarget;
        };

        enum AirSupportState : uint8_t
        {
            COOLING = 0,
            COOLED = 1,
            IN_AIR = 2
        };

        struct AirSupportData
        {
            AirSupportState state;
            uint8_t remainingStateTime;
        };

        enum DartStationState : uint8_t
        {
            OPEN = 0,
            CLOSED = 1,
            TRANSITION = 2
        };

        struct DartStationInfo
        {
            DartStationState state;
            uint16_t targetChangedTime;
            uint16_t lastLaunchedTime;
        };

        struct GroundRobotPositions
        {
            RobotPosition hero;
            RobotPosition engineer;
            RobotPosition standard3;
            RobotPosition standard4;
            RobotPosition standard5;
        };

        struct RadarMarkProgress
        {
            uint8_t hero;
            uint8_t engineer;
            uint8_t standard3;
            uint8_t standard4;
            uint8_t standard5;
            uint8_t sentry;
        };

        struct SentryInfo
        {
            uint16_t projectileAllowance;
            uint8_t
                remoteProjectileExchanges;
            uint8_t remoteHealthExchanges;
        };

        struct RadarInfo
        {
            uint8_t availableDoubleVulnerablilityEffects;
            bool activeDoubleVulnerabilityEffect;
        };

        struct GameData
        {
            GameType gameType;
            GameStage gameStage;
            uint16_t stageTimeRemaining;
            uint64_t unixTime;
            GameWinner gameWinner;
            EventData eventData;
            SupplierAction supplier;
            DartInfo dartInfo;
            AirSupportData airSupportData;
            DartStationInfo dartStation;
            GroundRobotPositions positions;
            RadarMarkProgress
                radarProgress;
            SentryInfo sentry;
            RadarInfo radar;
        };

        struct RobotData
        {
            RobotId robotId;
            uint8_t robotLevel;
            uint16_t previousHp;
            uint16_t currentHp;
            uint16_t maxHp;
            RobotPower_t robotPower;
            ArmorId damagedArmorId;
            DamageType damageType;
            float receivedDps;
            ChassisData chassis;
            TurretData turret;
            RobotHpData allRobotHp;
            uint16_t remainingCoins;
            RobotBuffStatus robotBuffStatus;
            RFIDActivationStatus_t rfidStatus;
            uint32_t robotDataReceivedTimestamp;
            RefereeWarningData refereeWarningData;
        };
    };

    class Tx
    {
    public:
        enum DeleteGraphicOperation
        {
            DELETE_GRAPHIC_NO_OP = 0,
            DELETE_GRAPHIC_LAYER = 1,
            DELETE_ALL = 2,
        };

        enum GraphicOperation
        {
            GRAPHIC_NO_OP = 0,
            GRAPHIC_ADD = 1,
            GRAPHIC_MODIFY = 2,
            GRAPHIC_DELETE = 3,
        };

        enum class GraphicType : uint8_t
        {
            STRAIGHT_LINE = 0,
            RECTANGLE = 1,
            CIRCLE = 2,
            ELLIPSE = 3,
            ARC = 4,
            FLOATING_NUM = 5,
            INTEGER = 6,
            CHARACTER = 7,
        };

        enum class GraphicColor : uint8_t
        {
            RED_AND_BLUE = 0,
            YELLOW = 1,
            GREEN = 2,
            ORANGE = 3,
            PURPLISH_RED = 4,
            PINK = 5,
            CYAN = 6,
            BLACK = 7,
            WHITE = 8,
        };

        struct InteractiveHeader
        {
            uint16_t dataCmdId;
            uint16_t senderId;
            uint16_t receiverId;
        } modm_packed;

        struct GraphicData
        {
            uint8_t name[3];
            uint32_t operation : 3;
            uint32_t type : 3;
            uint32_t layer : 4;
            uint32_t color : 4;
            uint32_t startAngle : 9;
            uint32_t endAngle : 9;
            uint32_t lineWidth : 10;
            uint32_t startX : 11;
            uint32_t startY : 11;
            union
            {
                struct
                {
                    uint32_t radius : 10;
                    uint32_t endX : 11;
                    uint32_t endY : 11;
                } modm_packed;
                int32_t value : 32;
            } modm_packed;
        } modm_packed;

        struct DeleteGraphicLayerMessage
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            uint8_t deleteOperation;
            uint8_t layer;
            uint16_t crc16;
        } modm_packed;

        struct Graphic1Message
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            GraphicData graphicData;
            uint16_t crc16;
        } modm_packed;

        struct RobotToRobotMessage
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            uint8_t dataAndCRC16[115];
        } modm_packed;

        struct Graphic2Message
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            GraphicData graphicData[2];
            uint16_t crc16;
        } modm_packed;

        struct Graphic5Message
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            GraphicData graphicData[5];
            uint16_t crc16;
        } modm_packed;

        struct Graphic7Message
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            GraphicData graphicData[7];
            uint16_t crc16;
        } modm_packed;

        struct GraphicCharacterMessage
        {
            DJISerial::FrameHeader frameHeader;
            uint16_t cmdId;
            InteractiveHeader interactiveHeader;
            GraphicData graphicData;
            char msg[30];
            uint16_t crc16;
        } modm_packed;

        static constexpr uint32_t MAX_TRANSMIT_SPEED_BYTES_PER_S = 1000;

        template <typename T>
        static constexpr uint32_t getWaitTimeAfterGraphicSendMs(T *)
        {
            // Must be a valid graphic message type
            static_assert(
                std::is_same<T, DeleteGraphicLayerMessage>::value ||
                    std::is_same<T, Graphic1Message>::value ||
                    std::is_same<T, RobotToRobotMessage>::value ||
                    std::is_same<T, Graphic2Message>::value ||
                    std::is_same<T, Graphic5Message>::value ||
                    std::is_same<T, Graphic7Message>::value ||
                    std::is_same<T, GraphicCharacterMessage>::value,
                "Invalid type, getWaitTimeAfterGraphicSendMs only takes in ref serial message "
                "types.");

            return sizeof(T) * 1'000 / MAX_TRANSMIT_SPEED_BYTES_PER_S;
        }
    };
};

inline RefSerialData::RobotId operator+(RefSerialData::RobotId id1, RefSerialData::RobotId id2)
{
    return static_cast<RefSerialData::RobotId>(
        static_cast<uint16_t>(id1) + static_cast<uint16_t>(id2));
}

inline RefSerialData::RobotId operator-(RefSerialData::RobotId id1, RefSerialData::RobotId id2)
{
    return static_cast<RefSerialData::RobotId>(
        static_cast<uint16_t>(id1) - static_cast<uint16_t>(id2));
}
}  // namespace tap::communication::serial

#endif  // TAPROOT_REF_SERIAL_DATA_HPP_