\documentclass[10pt,a4paper]{article} % Packages \usepackage{fancyhdr} % For header and footer \usepackage{multicol} % Allows multicols in tables \usepackage{tabularx} % Intelligent column widths \usepackage{tabulary} % Used in header and footer \usepackage{hhline} % Border under tables \usepackage{graphicx} % For images \usepackage{xcolor} % For hex colours %\usepackage[utf8x]{inputenc} % For unicode character support \usepackage[T1]{fontenc} % Without this we get weird character replacements \usepackage{colortbl} % For coloured tables \usepackage{setspace} % For line height \usepackage{lastpage} % Needed for total page number \usepackage{seqsplit} % Splits long words. %\usepackage{opensans} % Can't make this work so far. Shame. Would be lovely. \usepackage[normalem]{ulem} % For underlining links % Most of the following are not required for the majority % of cheat sheets but are needed for some symbol support. \usepackage{amsmath} % Symbols \usepackage{MnSymbol} % Symbols \usepackage{wasysym} % Symbols %\usepackage[english,german,french,spanish,italian]{babel} % Languages % Document Info \author{turback} \pdfinfo{ /Title (frc-java-basics.pdf) /Creator (Cheatography) /Author (turback) /Subject (FRC Java Basics Cheat Sheet) } % Lengths and widths \addtolength{\textwidth}{6cm} \addtolength{\textheight}{-1cm} \addtolength{\hoffset}{-3cm} \addtolength{\voffset}{-2cm} \setlength{\tabcolsep}{0.2cm} % Space between columns \setlength{\headsep}{-12pt} % Reduce space between header and content \setlength{\headheight}{85pt} % If less, LaTeX automatically increases it \renewcommand{\footrulewidth}{0pt} % Remove footer line \renewcommand{\headrulewidth}{0pt} % Remove header line \renewcommand{\seqinsert}{\ifmmode\allowbreak\else\-\fi} % Hyphens in seqsplit % This two commands together give roughly % the right line height in the tables \renewcommand{\arraystretch}{1.3} \onehalfspacing % Commands \newcommand{\SetRowColor}[1]{\noalign{\gdef\RowColorName{#1}}\rowcolor{\RowColorName}} % Shortcut for row colour \newcommand{\mymulticolumn}[3]{\multicolumn{#1}{>{\columncolor{\RowColorName}}#2}{#3}} % For coloured multi-cols \newcolumntype{x}[1]{>{\raggedright}p{#1}} % New column types for ragged-right paragraph columns \newcommand{\tn}{\tabularnewline} % Required as custom column type in use % Font and Colours \definecolor{HeadBackground}{HTML}{333333} \definecolor{FootBackground}{HTML}{666666} \definecolor{TextColor}{HTML}{333333} \definecolor{DarkBackground}{HTML}{A3A3A3} \definecolor{LightBackground}{HTML}{F3F3F3} \renewcommand{\familydefault}{\sfdefault} \color{TextColor} % Header and Footer \pagestyle{fancy} \fancyhead{} % Set header to blank \fancyfoot{} % Set footer to blank \fancyhead[L]{ \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{C} \SetRowColor{DarkBackground} \vspace{-7pt} {\parbox{\dimexpr\textwidth-2\fboxsep\relax}{\noindent \hspace*{-6pt}\includegraphics[width=5.8cm]{/web/www.cheatography.com/public/images/cheatography_logo.pdf}} } \end{tabulary} \columnbreak \begin{tabulary}{11cm}{L} \vspace{-2pt}\large{\bf{\textcolor{DarkBackground}{\textrm{FRC Java Basics Cheat Sheet}}}} \\ \normalsize{by \textcolor{DarkBackground}{turback} via \textcolor{DarkBackground}{\uline{cheatography.com/210084/cs/45291/}}} \end{tabulary} \end{multicols}} \fancyfoot[L]{ \footnotesize \noindent \begin{multicols}{3} \begin{tabulary}{5.8cm}{LL} \SetRowColor{FootBackground} \mymulticolumn{2}{p{5.377cm}}{\bf\textcolor{white}{Cheatographer}} \\ \vspace{-2pt}turback \\ \uline{cheatography.com/turback} \\ \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Cheat Sheet}} \\ \vspace{-2pt}Not Yet Published.\\ Updated 18th December, 2024.\\ Page {\thepage} of \pageref{LastPage}. \end{tabulary} \vfill \columnbreak \begin{tabulary}{5.8cm}{L} \SetRowColor{FootBackground} \mymulticolumn{1}{p{5.377cm}}{\bf\textcolor{white}{Sponsor}} \\ \SetRowColor{white} \vspace{-5pt} %\includegraphics[width=48px,height=48px]{dave.jpeg} Measure your website readability!\\ www.readability-score.com \end{tabulary} \end{multicols}} \begin{document} \raggedright \raggedcolumns % Set font size to small. Switch to any value % from this page to resize cheat sheet text: % www.emerson.emory.edu/services/latex/latex_169.html \footnotesize % Small font. \begin{tabularx}{17.67cm}{x{6.9167 cm} x{6.9167 cm} x{3.0366 cm} } \SetRowColor{DarkBackground} \mymulticolumn{3}{x{17.67cm}}{\bf\textcolor{white}{Common Device Classes}} \tn % Row 0 \SetRowColor{LightBackground} Talon SRX & \seqsplit{com.ctre.phoenix.motorcontrol.can.WPI\_TalonSRX} & CTRE \seqsplit{(Phoenix} V5) \tn % Row Count 3 (+ 3) % Row 1 \SetRowColor{white} Victor SPX & \seqsplit{com.ctre.phoenix.motorcontrol.can.WPI\_VictorSPX} & CTRE \seqsplit{(Phoenix} V5) \tn % Row Count 6 (+ 3) % Row 2 \SetRowColor{LightBackground} Talon FX & \seqsplit{com.ctre.phoenix6.hardware.TalonFX} & CTRE \seqsplit{(Phoenix} V6) \tn % Row Count 9 (+ 3) % Row 3 \SetRowColor{white} Pigeon 2 & \seqsplit{com.ctre.phoenix6.hardware.Pigeon2} & CTRE \seqsplit{(Phoenix} V6) \tn % Row Count 12 (+ 3) % Row 4 \SetRowColor{LightBackground} CAN Coder & \seqsplit{com.ctre.phoenix6.hardware.CANCoder} & CTRE \seqsplit{(Phoenix} V6) \tn % Row Count 15 (+ 3) % Row 5 \SetRowColor{white} Spark MAX & \seqsplit{com.revrobotics.CANSparkMax} & REV \seqsplit{(REVLib)} \tn % Row Count 17 (+ 2) % Row 6 \SetRowColor{LightBackground} Spark Flex & \seqsplit{com.revrobotics.CANSparkFlex} & REV \seqsplit{(REVLib)} \tn % Row Count 19 (+ 2) % Row 7 \SetRowColor{white} Through-Bore Encoder (RoboRIO, Absolute) & \seqsplit{edu.wpi.first.wpilibj.DutyCycleEncoder} & WPILib \tn % Row Count 22 (+ 3) % Row 8 \SetRowColor{LightBackground} Through-Bore Encoder (RoboRIO, Relative) & \seqsplit{edu.wpi.first.wpilibj.Encoder} & WPILib \tn % Row Count 25 (+ 3) \hhline{>{\arrayrulecolor{DarkBackground}}---} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Motor Basic Control (Talon SRX)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private WPI\_TalonSRX motor; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{WPI\_TalonSRX(RobotMap.MOTOR\_IDENTIFIER);} \newline \seqsplit{motor.configFactoryDefault();} // factory default \newline \} \newline \newline @Override \newline public void teleopInit() \{ \newline motor.set(0.5); \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline \newline \} \newline \newline @Override \newline public void teleopExit() \{ \newline motor.stopMotor() \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Motor Basic Control (Spark MAX)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private CANSparkMax motor; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{CANSparkMax(RobotMap.MOTOR\_IDENTIFIER}, \seqsplit{CANSparkLowLevel.MotorType.kBrushless);} \newline \seqsplit{motor.restoreFactoryDefaults();} // factory default \newline \} \newline \newline @Override \newline public void teleopInit() \{ \newline motor.set(0.5); \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline \newline \} \newline \newline @Override \newline public void teleopExit() \{ \newline motor.stopMotor() \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Motor Basic Control (Talon FX)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private TalonFX motor; \newline private DutyCycleOut dutyCycleControl; \newline private NeutralOut neutralControl; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{TalonFX(RobotMap.MOTOR\_IDENTIFIER);} \newline \seqsplit{motor.getConfigurator().apply(new} TalonFXConfiguration()); // factory default \newline \newline dutyCycleControl = new DutyCycleOut(0); \newline neutralControl = new NeutralOut(); \newline \} \newline \newline @Override \newline public void teleopInit() \{ \newline \seqsplit{motor.setControl(dutyCycleControl.withOutput(0.5));} \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline \newline \} \newline \newline @Override \newline public void teleopExit() \{ \newline \seqsplit{motor.setControl(neutralControl);} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Encoder Access (Talon SRX, SRX Encoder)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private static final int PPR = 4096; \newline private static final double \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO} = 8.0 / 1.0; // driver : driven \newline \newline private WPI\_TalonSRX motor; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{WPI\_TalonSRX(RobotMap.MOTOR\_IDENTIFIER);} \newline \seqsplit{motor.configFactoryDefault();} // factory default \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline double counts = \seqsplit{motor.getSelectedSensorPosition();} \newline double mechanismRotations = counts / PPR / \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO;} \newline \newline double countsPer100ms = \seqsplit{motor.getSelectedSensorVelocity();} \newline double mechanismRpm = countsPer100ms / PPR * 600.0 / \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO;} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Encoder Access (Spark Max, NEO Integrated Encoder)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private static final double \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO} = 8.0 / 1.0; // driver : driven \newline \newline private CANSparkMax motor; \newline private RelativeEncoder encoder; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{CANSparkMax(RobotMap.MOTOR\_IDENTIFIER}, \seqsplit{CANSparkLowLevel.MotorType.kBrushless);} \newline \seqsplit{motor.restoreFactoryDefaults();} // factory default \newline \newline encoder = motor.getEncoder(); \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline double motorRotations = encoder.getPosition(); \newline double mechanismRotations = motorRotations / \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO;} \newline \newline double motorRpm = encoder.getVelocity(); \newline double mechanismRpm = motorRpm / \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO;} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Encoder Access (Spark Max, NEO Integrated Encoder)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private static final double \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO} = 8.0 / 1.0; // driver : driven \newline \newline private CANSparkMax motor; \newline private RelativeEncoder encoder; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{CANSparkMax(RobotMap.MOTOR\_IDENTIFIER}, \seqsplit{CANSparkLowLevel.MotorType.kBrushless);} \newline \seqsplit{motor.restoreFactoryDefaults();} // factory default \newline \newline encoder = motor.getEncoder(); \newline \seqsplit{encoder.setPositionConversionFactor(1} / \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO);} \newline \seqsplit{encoder.setVelocityConversionFactor(1} / \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO);} \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline double mechanismRotations = encoder.getPosition(); \newline double mechanismRpm = encoder.getVelocity(); \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Encoder Access (Talon FX, Integrated Encoder)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private static final double \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO} = 8.0 / 1.0; // driver : driven \newline \newline private TalonFX motor; \newline private StatusSignal\textless{}Double\textgreater{} positionSignal; \newline private StatusSignal\textless{}Double\textgreater{} velocitySignal; \newline \newline @Override \newline public void robotInit() \{ \newline motor = new \seqsplit{TalonFX(RobotMap.MOTOR\_IDENTIFIER);} \newline \newline TalonFXConfiguration configuration = new TalonFXConfiguration(); \newline \seqsplit{configuration.Feedback.FeedbackSensorSource} = \seqsplit{FeedbackSensorSourceValue}.RotorSensor; \newline \seqsplit{configuration.Feedback.SensorToMechanismRatio} = \seqsplit{MOTOR\_TO\_MECHANISM\_GEAR\_RATIO;} \newline \seqsplit{motor.getConfigurator().apply(configuration);} \newline \newline positionSignal = motor.getPosition(); \newline velocitySignal = motor.getVelocity(); \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline \seqsplit{BaseStatusSignal.refreshAll(positionSignal}, velocitySignal); // only once per 20ms loop, typically in periodic \newline \newline double mechanismRotations = \seqsplit{positionSIgnal.getValueAsDouble();} \newline double \seqsplit{mechanismRotationsPerSecond} = \seqsplit{velocitySignal.getValueAsDouble();} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \begin{tabularx}{17.67cm}{X} \SetRowColor{DarkBackground} \mymulticolumn{1}{x{17.67cm}}{\bf\textcolor{white}{Encoder Access (CANCoder, Absolute)}} \tn \SetRowColor{LightBackground} \mymulticolumn{1}{x{17.67cm}}{private CANCoder encoder; \newline private StatusSignal\textless{}Double\textgreater{} absPositionSignal; \newline \newline @Override \newline public void robotInit() \{ \newline encoder = new \seqsplit{CANCoder(RobotMap.ENCODER);} \newline \newline CANcoderConfiguration configuration = new CANcoderConfiguration(); \newline \seqsplit{configuration.MagnetSensor.AbsoluteSensorRange} = \seqsplit{AbsoluteSensorRangeValue.Unsigned\_0To1;} \newline \seqsplit{encoder.getConfigurator().apply(configuration);} \newline \newline absPositionSignal = \seqsplit{motor.getAbsolutePosition();} \newline \} \newline \newline @Override \newline public void teleopPeriodic() \{ \newline \seqsplit{BaseStatusSignal.refreshAll(absPositionSignal);} // only once per 20ms loop, typically in periodic \newline \newline // typically absolute encoders are placed on the shaft after a gearbox, so gearbox ratio handling isn't needed here. \newline double mechanismRotationAbs = \seqsplit{absPositionSignal.getValueAsDouble();} // {[}0, 1{]} -\textgreater{} {[}0, 360{]} \newline \}} \tn \hhline{>{\arrayrulecolor{DarkBackground}}-} \end{tabularx} \par\addvspace{1.3em} \end{document}