001/*
002 * Copyright (C) Cross The Road Electronics.  All rights reserved.
003 * License information can be found in CTRE_LICENSE.txt
004 * For support and suggestions contact support@ctr-electronics.com or file
005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
006 */
007package com.ctre.phoenixpro.sim;
008
009import com.ctre.phoenixpro.StatusCode;
010import com.ctre.phoenixpro.hardware.core.CoreCANcoder;
011import com.ctre.phoenixpro.hardware.CANcoder;
012import com.ctre.phoenixpro.jni.PlatformJNI;
013
014/**
015 * Class to control the state of a simulated {@link CANcoder}.
016 */
017public class CANcoderSimState {
018        private final DeviceType kDevType = DeviceType.PRO_CANcoderType;
019
020        private final int _id;
021
022        /**
023         * The orientation of the CANcoder relative to the robot chassis.
024         * <p>
025         * This value should not be changed based on the CANcoder invert.
026         * Rather, this value should be changed when the mechanical linkage
027         * between the CANcoder and the robot changes.
028         */
029        public ChassisReference Orientation;
030
031        /**
032         * Creates an object to control the state of the given {@link CANcoder}.
033         * <p>
034         * This constructor defaults to a counter-clockwise positive orientation
035         * relative to the robot chassis.
036         *
037         * @param device
038         *        Device to which this simulation state is attached
039         */
040        public CANcoderSimState(CoreCANcoder device) {
041                this(device, ChassisReference.CounterClockwise_Positive);
042        }
043        /**
044         * Creates an object to control the state of the given {@link CANcoder}.
045         *
046         * @param device
047         *        Device to which this simulation state is attached
048         * @param orientation
049         *        Orientation of the device relative to the robot chassis
050         */
051        public CANcoderSimState(CoreCANcoder device, ChassisReference orientation) {
052                _id = device.getDeviceID();
053                Orientation = orientation;
054        }
055
056        /**
057         * Sets the simulated supply voltage of the CANcoder.
058         * <p>
059         * The minimum allowed supply voltage is 4 V - values below this
060         * will be promoted to 4 V.
061         *
062         * @param volts
063         *        The supply voltage in Volts
064         * @return Status code
065         */
066        public StatusCode setSupplyVoltage(double volts) {
067                return StatusCode.valueOf(PlatformJNI.JNI_SimSetPhysicsInput(kDevType.value, _id, "SupplyVoltage", volts));
068        }
069        /**
070         * Sets the simulated raw position of the CANcoder.
071         * <p>
072         * Inputs to this function over time should be continuous, as user calls of {@link CANcoder#setPosition} will be accounted for in the callee.
073         * <p>
074         * The CANcoder integrates this to calculate the true reported position.
075         * <p>
076         * When using the WPI Sim GUI, you will notice a readonly {@code position} and settable {@code rawPositionInput}.
077         * The readonly signal is the emulated position which will match self-test in Tuner and the hardware API.
078         * Changes to {@code rawPositionInput} will be integrated into the emulated position.
079         * This way a simulator can modify the position without overriding hardware API calls for home-ing the sensor.
080         *
081         * @param rotations
082         *        The raw position in rotations
083         * @return Status code
084         */
085        public StatusCode setRawPosition(double rotations) {
086                if (Orientation == ChassisReference.Clockwise_Positive) {
087                        rotations = -rotations;
088                }
089                return StatusCode.valueOf(PlatformJNI.JNI_SimSetPhysicsInput(kDevType.value, _id, "RawPosition", rotations));
090        }
091        /**
092         * Adds to the simulated position of the CANcoder.
093         *
094         * @param dRotations
095         *        The change in position in rotations
096         * @return Status code
097         */
098        public StatusCode addPosition(double dRotations) {
099                if (Orientation == ChassisReference.Clockwise_Positive) {
100                        dRotations = -dRotations;
101                }
102                return StatusCode.valueOf(PlatformJNI.JNI_SimSetPhysicsInput(kDevType.value, _id, "AddPosition", dRotations));
103        }
104        /**
105         * Sets the simulated velocity of the CANcoder.
106         *
107         * @param rps
108         *        The new velocity in rotations per second
109         * @return Status code
110         */
111        public StatusCode setVelocity(double rps) {
112                if (Orientation == ChassisReference.Clockwise_Positive) {
113                        rps = -rps;
114                }
115                return StatusCode.valueOf(PlatformJNI.JNI_SimSetPhysicsInput(kDevType.value, _id, "Velocity", rps));
116        }
117}