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.phoenix6.controls;
008
009import com.ctre.phoenix6.StatusCode;
010import com.ctre.phoenix6.controls.jni.ControlJNI;
011
012import java.util.HashMap;
013import java.util.Map;
014
015/**
016 * Follow the motor output of another Talon.
017 * <p>
018 * If Talon is in torque control, the torque is copied - which will increase the total torque applied. If
019 * Talon is in percent supply output control, the duty cycle is matched.  Motor direction either matches
020 * master's configured direction or opposes it based on OpposeMasterDirection.
021 */
022public class Follower extends ControlRequest implements Cloneable
023{
024    /**
025     * Device ID of the master to follow.
026     */
027    public int MasterID;
028    /**
029     * Set to false for motor invert to match the master's configured Invert - which
030     * is typical when master and follower are mechanically linked and spin in the
031     * same direction.  Set to true for motor invert to oppose the master's
032     * configured Invert - this is typical where the the master and follower
033     * mechanically spin in opposite directions.
034     */
035    public boolean OpposeMasterDirection;
036
037    /**
038     * The period at which this control will update at.
039     * This is designated in Hertz, with a minimum of 20 Hz
040     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
041     * <p>
042     * If this field is set to 0 Hz, the control request will
043     * be sent immediately as a one-shot frame. This may be useful
044     * for advanced applications that require outputs to be
045     * synchronized with data acquisition. In this case, we
046     * recommend not exceeding 50 ms between control calls.
047     */
048    public double UpdateFreqHz = 20; // Default to 20Hz
049
050    /**
051     * Follow the motor output of another Talon.
052     * <p>
053     * If Talon is in torque control, the torque is copied - which will increase the
054     * total torque applied. If Talon is in percent supply output control, the duty
055     * cycle is matched.  Motor direction either matches master's configured
056     * direction or opposes it based on OpposeMasterDirection.
057     * 
058     * @param MasterID    Device ID of the master to follow.
059     * @param OpposeMasterDirection    Set to false for motor invert to match the
060     *                                 master's configured Invert - which is typical
061     *                                 when master and follower are mechanically
062     *                                 linked and spin in the same direction.  Set
063     *                                 to true for motor invert to oppose the
064     *                                 master's configured Invert - this is typical
065     *                                 where the the master and follower
066     *                                 mechanically spin in opposite directions.
067     */
068    public Follower(int MasterID, boolean OpposeMasterDirection)
069    {
070        super("Follower");
071        this.MasterID = MasterID;
072        this.OpposeMasterDirection = OpposeMasterDirection;
073    }
074
075    @Override
076    public String toString()
077    {
078        String ss = "class: Follower\n";
079        ss += "MasterID: " + MasterID + "\n";
080        ss += "OpposeMasterDirection: " + OpposeMasterDirection + "\n";
081        return ss;
082    }
083
084    @Override
085    public StatusCode sendRequest(String network, int deviceHash, boolean cancelOtherRequests)
086    {
087        return StatusCode.valueOf(ControlJNI.JNI_RequestControlFollower(
088                network, deviceHash, UpdateFreqHz, cancelOtherRequests, MasterID, OpposeMasterDirection));
089    }
090
091    /**
092     * Gets information about this control request.
093     *
094     * @return Map of control parameter names and corresponding applied values
095     */
096    @Override
097    public Map<String, String> getControlInfo()
098    {
099        var controlInfo = new HashMap<String, String>();
100        controlInfo.put("Name", getName());
101        controlInfo.put("MasterID", String.valueOf(this.MasterID));
102        controlInfo.put("OpposeMasterDirection", String.valueOf(this.OpposeMasterDirection));
103        return controlInfo;
104    }
105    
106    /**
107     * Modifies this Control Request's MasterID parameter and returns itself for
108     * method-chaining and easier to use request API.
109     * <p>
110     * Device ID of the master to follow.
111     *
112     * @param newMasterID Parameter to modify
113     * @return Itself
114     */
115    public Follower withMasterID(int newMasterID)
116    {
117        MasterID = newMasterID;
118        return this;
119    }
120    
121    /**
122     * Modifies this Control Request's OpposeMasterDirection parameter and returns itself for
123     * method-chaining and easier to use request API.
124     * <p>
125     * Set to false for motor invert to match the master's configured Invert - which
126     * is typical when master and follower are mechanically linked and spin in the
127     * same direction.  Set to true for motor invert to oppose the master's
128     * configured Invert - this is typical where the the master and follower
129     * mechanically spin in opposite directions.
130     *
131     * @param newOpposeMasterDirection Parameter to modify
132     * @return Itself
133     */
134    public Follower withOpposeMasterDirection(boolean newOpposeMasterDirection)
135    {
136        OpposeMasterDirection = newOpposeMasterDirection;
137        return this;
138    }
139    /**
140     * Sets the period at which this control will update at.
141     * This is designated in Hertz, with a minimum of 20 Hz
142     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
143     * <p>
144     * If this field is set to 0 Hz, the control request will
145     * be sent immediately as a one-shot frame. This may be useful
146     * for advanced applications that require outputs to be
147     * synchronized with data acquisition. In this case, we
148     * recommend not exceeding 50 ms between control calls.
149     *
150     * @param newUpdateFreqHz Parameter to modify
151     * @return Itself
152     */
153    public Follower withUpdateFreqHz(double newUpdateFreqHz)
154    {
155        UpdateFreqHz = newUpdateFreqHz;
156        return this;
157    }
158
159    @Override
160    public Follower clone()
161    {
162        try {
163            return (Follower)super.clone();
164        } catch (CloneNotSupportedException ex) {
165            /* this should never happen */
166            throw new RuntimeException(ex);
167        }
168    }
169}
170