blob: 274cb1870f4afdec2a986c13b23ed4496b48720b [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
Brian Silverman1a675112016-02-20 20:42:49 -05002/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */
Brian Silverman26e4e522015-12-17 01:56:40 -05003/* Open Source Software - may be modified and shared by FRC teams. The code */
Brian Silverman1a675112016-02-20 20:42:49 -05004/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
Brian Silverman26e4e522015-12-17 01:56:40 -05006/*----------------------------------------------------------------------------*/
7
8#include "DriverStation.h"
Brian Silverman26e4e522015-12-17 01:56:40 -05009#include "Timer.h"
Brian Silverman1a675112016-02-20 20:42:49 -050010#include "simulation/MainNode.h"
11//#include "MotorSafetyHelper.h"
Brian Silverman26e4e522015-12-17 01:56:40 -050012#include "Utility.h"
13#include "WPIErrors.h"
14#include <string.h>
15#include "Log.hpp"
Brian Silverman1a675112016-02-20 20:42:49 -050016#include "boost/mem_fn.hpp"
Brian Silverman26e4e522015-12-17 01:56:40 -050017
18// set the logging level
19TLogLevel dsLogLevel = logDEBUG;
Brian Silverman26e4e522015-12-17 01:56:40 -050020
21#define DS_LOG(level) \
Brian Silverman1a675112016-02-20 20:42:49 -050022 if (level > dsLogLevel) ; \
23 else Log().Get(level)
Brian Silverman26e4e522015-12-17 01:56:40 -050024
Brian Silverman1a675112016-02-20 20:42:49 -050025const uint32_t DriverStation::kBatteryChannel;
Brian Silverman26e4e522015-12-17 01:56:40 -050026const uint32_t DriverStation::kJoystickPorts;
Brian Silverman1a675112016-02-20 20:42:49 -050027const uint32_t DriverStation::kJoystickAxes;
28const float DriverStation::kUpdatePeriod = 0.02;
29uint8_t DriverStation::m_updateNumber = 0;
Brian Silverman26e4e522015-12-17 01:56:40 -050030
31/**
Brian Silverman1a675112016-02-20 20:42:49 -050032 * DriverStation contructor.
Brian Silverman26e4e522015-12-17 01:56:40 -050033 *
34 * This is only called once the first time GetInstance() is called
35 */
36DriverStation::DriverStation() {
Brian Silverman1a675112016-02-20 20:42:49 -050037 state = msgs::DriverStationPtr(new msgs::DriverStation());
38 stateSub = MainNode::Subscribe("~/ds/state",
39 &DriverStation::stateCallback, this);
40 // TODO: for loop + boost bind
41 joysticks[0] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
42 joysticksSub[0] = MainNode::Subscribe("~/ds/joysticks/0",
43 &DriverStation::joystickCallback0, this);
44 joysticks[1] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
45 joysticksSub[1] = MainNode::Subscribe("~/ds/joysticks/1",
46 &DriverStation::joystickCallback1, this);
47 joysticks[2] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
48 joysticksSub[2] = MainNode::Subscribe("~/ds/joysticks/2",
49 &DriverStation::joystickCallback2, this);
50 joysticks[3] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
51 joysticksSub[3] = MainNode::Subscribe("~/ds/joysticks/5",
52 &DriverStation::joystickCallback3, this);
53 joysticks[4] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
54 joysticksSub[4] = MainNode::Subscribe("~/ds/joysticks/4",
55 &DriverStation::joystickCallback4, this);
56 joysticks[5] = msgs::FRCJoystickPtr(new msgs::FRCJoystick());
57 joysticksSub[5] = MainNode::Subscribe("~/ds/joysticks/5",
58 &DriverStation::joystickCallback5, this);
Brian Silverman26e4e522015-12-17 01:56:40 -050059
Brian Silverman1a675112016-02-20 20:42:49 -050060 AddToSingletonList();
Brian Silverman26e4e522015-12-17 01:56:40 -050061}
62
63/**
Brian Silverman1a675112016-02-20 20:42:49 -050064 * Return a pointer to the singleton DriverStation.
Brian Silverman26e4e522015-12-17 01:56:40 -050065 */
Brian Silverman1a675112016-02-20 20:42:49 -050066DriverStation& DriverStation::GetInstance()
67{
68 static DriverStation instance;
69 return instance;
Brian Silverman26e4e522015-12-17 01:56:40 -050070}
71
72/**
Brian Silverman1a675112016-02-20 20:42:49 -050073 * Read the battery voltage. Hardcoded to 12 volts for Simulation.
Brian Silverman26e4e522015-12-17 01:56:40 -050074 *
Brian Silverman1a675112016-02-20 20:42:49 -050075 * @return The battery voltage.
Brian Silverman26e4e522015-12-17 01:56:40 -050076 */
Brian Silverman1a675112016-02-20 20:42:49 -050077float DriverStation::GetBatteryVoltage() const
78{
79 return 12.0; // 12 volts all the time!
Brian Silverman26e4e522015-12-17 01:56:40 -050080}
81
82/**
83 * Get the value of the axis on a joystick.
84 * This depends on the mapping of the joystick connected to the specified port.
85 *
86 * @param stick The joystick to read.
87 * @param axis The analog axis value to read from the joystick.
88 * @return The value of the axis on the joystick.
89 */
Brian Silverman1a675112016-02-20 20:42:49 -050090float DriverStation::GetStickAxis(uint32_t stick, uint32_t axis)
91{
92 if (axis < 0 || axis > (kJoystickAxes - 1))
93 {
94 wpi_setWPIError(BadJoystickAxis);
95 return 0.0;
96 }
97 if (stick < 0 || stick > 5)
98 {
99 wpi_setWPIError(BadJoystickIndex);
100 return 0.0;
101 }
Brian Silverman26e4e522015-12-17 01:56:40 -0500102
Brian Silverman1a675112016-02-20 20:42:49 -0500103 std::unique_lock<std::recursive_mutex> lock(m_joystickMutex);
104 if (joysticks[stick] == nullptr || axis >= joysticks[stick]->axes().size())
105 {
106 return 0.0;
107 }
108 return joysticks[stick]->axes(axis);
Brian Silverman26e4e522015-12-17 01:56:40 -0500109}
110
111/**
Brian Silverman1a675112016-02-20 20:42:49 -0500112 * The state of a specific button (1 - 12) on the joystick.
113 * This method only works in simulation, but is more efficient than GetStickButtons.
Brian Silverman26e4e522015-12-17 01:56:40 -0500114 *
Brian Silverman1a675112016-02-20 20:42:49 -0500115 * @param stick The joystick to read.
116 * @param button The button number to check.
117 * @return If the button is pressed.
Brian Silverman26e4e522015-12-17 01:56:40 -0500118 */
Brian Silverman1a675112016-02-20 20:42:49 -0500119bool DriverStation::GetStickButton(uint32_t stick, uint32_t button)
120{
121 if (stick < 0 || stick >= 6)
122 {
123 wpi_setWPIErrorWithContext(ParameterOutOfRange, "stick must be between 0 and 5");
124 return false;
125 }
Brian Silverman26e4e522015-12-17 01:56:40 -0500126
Brian Silverman1a675112016-02-20 20:42:49 -0500127 std::unique_lock<std::recursive_mutex> lock(m_joystickMutex);
128 if (joysticks[stick] == nullptr || button >= joysticks[stick]->buttons().size())
129 {
130 return false;
131 }
132 return joysticks[stick]->buttons(button-1);
Brian Silverman26e4e522015-12-17 01:56:40 -0500133}
134
135/**
136 * The state of the buttons on the joystick.
Brian Silverman1a675112016-02-20 20:42:49 -0500137 * 12 buttons (4 msb are unused) from the joystick.
Brian Silverman26e4e522015-12-17 01:56:40 -0500138 *
139 * @param stick The joystick to read.
140 * @return The state of the buttons on the joystick.
141 */
Brian Silverman1a675112016-02-20 20:42:49 -0500142short DriverStation::GetStickButtons(uint32_t stick)
143{
144 if (stick < 0 || stick >= 6)
145 {
146 wpi_setWPIErrorWithContext(ParameterOutOfRange, "stick must be between 0 and 5");
147 return false;
148 }
149 short btns = 0, btnid;
Brian Silverman26e4e522015-12-17 01:56:40 -0500150
Brian Silverman1a675112016-02-20 20:42:49 -0500151 std::unique_lock<std::recursive_mutex> lock(m_joystickMutex);
152 msgs::FRCJoystickPtr joy = joysticks[stick];
153 for (btnid = 0; btnid < joy->buttons().size() && btnid < 12; btnid++)
154 {
155 if (joysticks[stick]->buttons(btnid))
156 {
157 btns |= (1 << btnid);
158 }
159 }
160 return btns;
Brian Silverman26e4e522015-12-17 01:56:40 -0500161}
162
Brian Silverman1a675112016-02-20 20:42:49 -0500163// 5V divided by 10 bits
164#define kDSAnalogInScaling ((float)(5.0 / 1023.0))
165
Brian Silverman26e4e522015-12-17 01:56:40 -0500166/**
Brian Silverman1a675112016-02-20 20:42:49 -0500167 * Get an analog voltage from the Driver Station.
168 * The analog values are returned as voltage values for the Driver Station analog inputs.
169 * These inputs are typically used for advanced operator interfaces consisting of potentiometers
170 * or resistor networks representing values on a rotary switch.
Brian Silverman26e4e522015-12-17 01:56:40 -0500171 *
Brian Silverman1a675112016-02-20 20:42:49 -0500172 * @param channel The analog input channel on the driver station to read from. Valid range is 1 - 4.
173 * @return The analog voltage on the input.
Brian Silverman26e4e522015-12-17 01:56:40 -0500174 */
Brian Silverman1a675112016-02-20 20:42:49 -0500175float DriverStation::GetAnalogIn(uint32_t channel)
176{
177 wpi_setWPIErrorWithContext(UnsupportedInSimulation, "GetAnalogIn");
178 return 0.0;
Brian Silverman26e4e522015-12-17 01:56:40 -0500179}
180
181/**
Brian Silverman1a675112016-02-20 20:42:49 -0500182 * Get values from the digital inputs on the Driver Station.
183 * Return digital values from the Drivers Station. These values are typically used for buttons
184 * and switches on advanced operator interfaces.
185 * @param channel The digital input to get. Valid range is 1 - 8.
Brian Silverman26e4e522015-12-17 01:56:40 -0500186 */
Brian Silverman1a675112016-02-20 20:42:49 -0500187bool DriverStation::GetDigitalIn(uint32_t channel)
188{
189 wpi_setWPIErrorWithContext(UnsupportedInSimulation, "GetDigitalIn");
190 return false;
Brian Silverman26e4e522015-12-17 01:56:40 -0500191}
192
193/**
Brian Silverman1a675112016-02-20 20:42:49 -0500194 * Set a value for the digital outputs on the Driver Station.
195 *
196 * Control digital outputs on the Drivers Station. These values are typically used for
197 * giving feedback on a custom operator station such as LEDs.
198 *
199 * @param channel The digital output to set. Valid range is 1 - 8.
200 * @param value The state to set the digital output.
Brian Silverman26e4e522015-12-17 01:56:40 -0500201 */
Brian Silverman1a675112016-02-20 20:42:49 -0500202void DriverStation::SetDigitalOut(uint32_t channel, bool value)
203{
204 wpi_setWPIErrorWithContext(UnsupportedInSimulation, "SetDigitalOut");
Brian Silverman26e4e522015-12-17 01:56:40 -0500205}
206
207/**
Brian Silverman1a675112016-02-20 20:42:49 -0500208 * Get a value that was set for the digital outputs on the Driver Station.
209 * @param channel The digital ouput to monitor. Valid range is 1 through 8.
210 * @return A digital value being output on the Drivers Station.
Brian Silverman26e4e522015-12-17 01:56:40 -0500211 */
Brian Silverman1a675112016-02-20 20:42:49 -0500212bool DriverStation::GetDigitalOut(uint32_t channel)
213{
214 wpi_setWPIErrorWithContext(UnsupportedInSimulation, "GetDigitalOut");
215 return false;
Brian Silverman26e4e522015-12-17 01:56:40 -0500216}
217
Brian Silverman1a675112016-02-20 20:42:49 -0500218bool DriverStation::IsEnabled() const
219{
220 std::unique_lock<std::recursive_mutex> lock(m_stateMutex);
221 return state != nullptr ? state->enabled() : false;
Brian Silverman26e4e522015-12-17 01:56:40 -0500222}
223
Brian Silverman1a675112016-02-20 20:42:49 -0500224bool DriverStation::IsDisabled() const
225{
226 return !IsEnabled();
Brian Silverman26e4e522015-12-17 01:56:40 -0500227}
228
Brian Silverman1a675112016-02-20 20:42:49 -0500229bool DriverStation::IsAutonomous() const
230{
231 std::unique_lock<std::recursive_mutex> lock(m_stateMutex);
232 return state != nullptr ?
233 state->state() == msgs::DriverStation_State_AUTO : false;
Brian Silverman26e4e522015-12-17 01:56:40 -0500234}
235
Brian Silverman1a675112016-02-20 20:42:49 -0500236bool DriverStation::IsOperatorControl() const
237{
238 return !(IsAutonomous() || IsTest());
Brian Silverman26e4e522015-12-17 01:56:40 -0500239}
240
Brian Silverman1a675112016-02-20 20:42:49 -0500241bool DriverStation::IsTest() const
242{
243 std::unique_lock<std::recursive_mutex> lock(m_stateMutex);
244 return state != nullptr ?
245 state->state() == msgs::DriverStation_State_TEST : false;
Brian Silverman26e4e522015-12-17 01:56:40 -0500246}
247
248/**
249 * Is the driver station attached to a Field Management System?
Brian Silverman1a675112016-02-20 20:42:49 -0500250 * Note: This does not work with the Blue DS.
251 * @return True if the robot is competing on a field being controlled by a Field Management System
Brian Silverman26e4e522015-12-17 01:56:40 -0500252 */
Brian Silverman1a675112016-02-20 20:42:49 -0500253bool DriverStation::IsFMSAttached() const
254{
255 return false; // No FMS in simulation
Brian Silverman26e4e522015-12-17 01:56:40 -0500256}
257
258/**
259 * Return the alliance that the driver station says it is on.
260 * This could return kRed or kBlue
Brian Silverman1a675112016-02-20 20:42:49 -0500261 * @return The Alliance enum
Brian Silverman26e4e522015-12-17 01:56:40 -0500262 */
Brian Silverman1a675112016-02-20 20:42:49 -0500263DriverStation::Alliance DriverStation::GetAlliance() const
264{
265 // if (m_controlData->dsID_Alliance == 'R') return kRed;
266 // if (m_controlData->dsID_Alliance == 'B') return kBlue;
267 // wpi_assert(false);
268 return kInvalid; // TODO: Support alliance colors
Brian Silverman26e4e522015-12-17 01:56:40 -0500269}
270
271/**
272 * Return the driver station location on the field
273 * This could return 1, 2, or 3
Brian Silverman1a675112016-02-20 20:42:49 -0500274 * @return The location of the driver station
Brian Silverman26e4e522015-12-17 01:56:40 -0500275 */
Brian Silverman1a675112016-02-20 20:42:49 -0500276uint32_t DriverStation::GetLocation() const
277{
278 return -1; // TODO: Support locations
Brian Silverman26e4e522015-12-17 01:56:40 -0500279}
280
281/**
282 * Wait until a new packet comes from the driver station
283 * This blocks on a semaphore, so the waiting is efficient.
Brian Silverman1a675112016-02-20 20:42:49 -0500284 * This is a good way to delay processing until there is new driver station data to act on
Brian Silverman26e4e522015-12-17 01:56:40 -0500285 */
Brian Silverman1a675112016-02-20 20:42:49 -0500286void DriverStation::WaitForData()
287{
288 std::unique_lock<std::mutex> lock(m_waitForDataMutex);
289 m_waitForDataCond.wait(lock);
Brian Silverman26e4e522015-12-17 01:56:40 -0500290}
291
292/**
293 * Return the approximate match time
Brian Silverman1a675112016-02-20 20:42:49 -0500294 * The FMS does not currently send the official match time to the robots
295 * This returns the time since the enable signal sent from the Driver Station
296 * At the beginning of autonomous, the time is reset to 0.0 seconds
297 * At the beginning of teleop, the time is reset to +15.0 seconds
298 * If the robot is disabled, this returns 0.0 seconds
299 * Warning: This is not an official time (so it cannot be used to argue with referees)
300 * @return Match time in seconds since the beginning of autonomous
Brian Silverman26e4e522015-12-17 01:56:40 -0500301 */
Brian Silverman1a675112016-02-20 20:42:49 -0500302double DriverStation::GetMatchTime() const
303{
304 if (m_approxMatchTimeOffset < 0.0)
305 return 0.0;
306 return Timer::GetFPGATimestamp() - m_approxMatchTimeOffset;
Brian Silverman26e4e522015-12-17 01:56:40 -0500307}
308
309/**
310 * Report an error to the DriverStation messages window.
311 * The error is also printed to the program console.
312 */
Brian Silverman1a675112016-02-20 20:42:49 -0500313void DriverStation::ReportError(std::string error)
314{
315 std::cout << error << std::endl;
316}
Brian Silverman26e4e522015-12-17 01:56:40 -0500317
Brian Silverman1a675112016-02-20 20:42:49 -0500318/**
319 * Report a warning to the DriverStation messages window.
320 * The warning is also printed to the program console.
321 */
322void DriverStation::ReportWarning(std::string error)
323{
324 std::cout << error << std::endl;
325}
326
327/**
328 * Report an error to the DriverStation messages window.
329 * The error is also printed to the program console.
330 */
331void DriverStation::ReportError(bool is_error, int32_t code,
332 const std::string& error,
333 const std::string& location,
334 const std::string& stack)
335{
336 if (!location.empty())
337 std::cout << (is_error ? "Error" : "Warning") << " at " << location << ": ";
338 std::cout << error << std::endl;
339 if (!stack.empty())
340 std::cout << stack << std::endl;
341}
342
343/**
344 * Return the team number that the Driver Station is configured for
345 * @return The team number
346 */
347uint16_t DriverStation::GetTeamNumber() const
348{
349 return 348;
350}
351
352void DriverStation::stateCallback(const msgs::ConstDriverStationPtr &msg)
353{
354 {
355 std::unique_lock<std::recursive_mutex> lock(m_stateMutex);
356 *state = *msg;
357 }
358 m_waitForDataCond.notify_all();
359}
360
361void DriverStation::joystickCallback(const msgs::ConstFRCJoystickPtr &msg,
362 int i)
363{
364 std::unique_lock<std::recursive_mutex> lock(m_joystickMutex);
365 *(joysticks[i]) = *msg;
366}
367
368void DriverStation::joystickCallback0(const msgs::ConstFRCJoystickPtr &msg)
369{
370 joystickCallback(msg, 0);
371}
372
373void DriverStation::joystickCallback1(const msgs::ConstFRCJoystickPtr &msg)
374{
375 joystickCallback(msg, 1);
376}
377
378void DriverStation::joystickCallback2(const msgs::ConstFRCJoystickPtr &msg)
379{
380 joystickCallback(msg, 2);
381}
382
383void DriverStation::joystickCallback3(const msgs::ConstFRCJoystickPtr &msg)
384{
385 joystickCallback(msg, 3);
386}
387
388void DriverStation::joystickCallback4(const msgs::ConstFRCJoystickPtr &msg)
389{
390 joystickCallback(msg, 4);
391}
392
393void DriverStation::joystickCallback5(const msgs::ConstFRCJoystickPtr &msg)
394{
395 joystickCallback(msg, 5);
Brian Silverman26e4e522015-12-17 01:56:40 -0500396}