-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRobotMain.cpp
More file actions
1788 lines (1527 loc) · 57.8 KB
/
RobotMain.cpp
File metadata and controls
1788 lines (1527 loc) · 57.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/******************************************************************************
*
* Sprockets 2011 Code
* Authors: Duane Jeffery
* Matt Aceto
* Brendan van Ryn
* Terry Shi
* Stuart Sullivan
* Will Surmak
* Last Updated: 2/3/2011
*
******************************************************************************/
/* These two values select the stopping distances during autonomous. The first is for straighline, and the second is
* for the Y-branch. Simply replace the number beside the capitalized name and re-download the code. To do so, press
* Ctrl+Shift+A to compile, then select FIRST->Download from the top menu. Finally, make sure to reboot the robot. */
#define STRAIGHTLINEDISTANCE 240
#define BRANCHEDLINEDISTANCE 821
/* Left = back, right = front */
// Header files
#include "WPILib.h"
#include "vision\AxisCamera.h"
#include "math.h"
#include "stdlib.h"
// Drive system definitions. Use these to specify which drive system is in use.
#define MECANUM 32
#define SWERVE 51
// Handles the tedious driverstation output overhead
// Simply pass a number and it will be sent to the driver station
#define CLEARMESSAGE DriverStationLCD::GetInstance()->Clear()
#define DISPLAYMESSAGE(b, a) DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line ## b, 1, "%d", a); DriverStationLCD::GetInstance()->UpdateLCD()
#define DISPLAYSTRING(b, a) DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line ## b, 1, a); DriverStationLCD::GetInstance()->UpdateLCD()
// Autonomous mode definitions. Use these to specify which autonomous mode to use.
#define STRAIGHT 0
#define BRANCH 1
// Determine which drive system we are using
// If the drive system is defined as MECANUM, the mecanum
// drive code is used. If it is defined as SWERVE, the swerve
// drive code is used. Otherwise, the compiler generates an error
#define DRIVESYSTEM SWERVE
#if (DRIVESYSTEM != MECANUM && DRIVESYSTEM != SWERVE) || !defined DRIVESYSTEM
#error "Drive system not specified"
#endif
// Ultrasonic stopping distance for autonomous
// Branch angle for y-autonomous
#define BRANCHSTOPDISTANCE 400
#define BRANCHANGLE -0.12
// Steering mode macros for the swerve drive function
#define STRAFE 0
#define TANK 1
#define MONSTER 2
#define CAR 3
#define AUTOMONSTER_LEFT 4
#define AUTOMONSTER_RIGHT 5
// Number of pulses per rotation on the steering encoders
// To acheive a pulse value, multiply an angle by this value
// AUTOALIGNSTOP is a time limit before the autoalign function should automatically exit
#define PULSES_PER_STEER (1020)
#define AUTOALIGNSTOP 1000
// Speed of claw rollers
#define CLAWROLLERSPEED 0.6
// Motor macros to be changed depending on whether we use Jaguars or Victors
#define LPDRIVEMOTOR Jaguar*
#define DRIVEMOTOR(a) Jaguar(a)
// Joystick deadbands
#define JOYSTICK_DEADBAND_X 0.0525f
#define JOYSTICK_DEADBAND_Y 0.100f
// Steering synchronization macros
#define STEERINGSYNCDEADBAND 5 // Manimum difference between encoders for synchronization to take effect
#define STEERINGSYNCDISTANCE 100 // Maximum distance between drive units before one steering motor is stopped completely
#define STEERINGSYNCDIVIDER 200 // Resolution of the steering synchronization code (smaller values means more frequent synchronization)
// When the lock button is pressed, multiply the drive speed by this to reduce chances of tipping
#define LOCKBUTTONLIMIT 0.625
// Button Macros
// An x indicates that an imaginary button was specified, such as for an untested feature
#define CLAWREVERSEBUTTON !clawStick->GetRawButton(1)
#define PIVOTPOSITIONHOME clawStick->GetRawButton(2)
#define PIVOTPOSITIONMIDDLE clawStick->GetRawButton(4)
#define PIVOTPOSITIONLOW clawStick->GetRawButton(80) // x
#define PIVOTPOSITIONFULL clawStick->GetRawButton(5)
#define EXTENDBUTTON clawStick->GetRawButton(6)
#define RETRACTBUTTON clawStick->GetRawButton(7)
#define LOCKBUTTONPRESSED leftStick->GetRawButton(2)
#define PIVOTDOWNBUTTON clawStick->GetRawButton(10)
#define PIVOTUPBUTTON clawStick->GetRawButton(11)
#define PIVOTPOSITIONHIGH clawStick->GetRawButton(30) // x
#define STEERALIGNBUTTON leftStick->GetRawButton(10)
#define MONSTERENABLEBUTTON leftStick->GetRawButton(1)
#define DEPLOYMINIBOT leftStick->GetRawButton(6)
#define RETRACTMINIBOT leftStick->GetRawButton(7)
#define SWERVEENABLEBUTTON rightStick->GetRawButton(1)
#define CARENABLEBUTTON rightStick->GetRawButton(20) // x
#define EXITSTEERALIGN leftStick->GetRawButton(11)
#define PICKUPBUTTON clawStick->GetRawButton(9)
#define DRIVEREVERSEOFF (leftStick->GetRawButton(4) || leftStick->GetRawButton(5) || leftStick->GetRawButton(3))
#define DRIVEREVERSEON (rightStick->GetRawButton(4) || rightStick->GetRawButton(5) || rightStick->GetRawButton(3))
#define PREPICKUPBUTTON clawStick->GetRawButton(8)
// Slot for second digital sidecar
#define DIGITALSIDECARTWO 6
// Autonomous travel time (how long should it strafe after the branch?)
#define AUTONOMOUSTRAVELTIME 3300
// Autonomous straight section time
#define AUTONOMOUSSTRAIGHT 1600
// Autonomous manipulation time
#define MANIPULATIONTIME 6000
// Delay between arriving at rack and deploying tube in autonomous
#define RETRACTTIME 3000
// Amount of time for the tube to be manipulated when the claw switch is triggered
#define AUTOMANIPULATETIME 1750
// Travel speed an angle along branch
#define BRANCHSPEED 0.5
// Port number macros in case things get moved around
#define RIGHTJOYSTICKPORT 1
#define LEFTJOYSTICKPORT 4
#define CLAWJOYSTICKPORT 3
#define LIGHTSENSORPORT1 1
#define LIGHTSENSORPORT2 2
#define LIGHTSENSORPORT3 3
#define LIGHTSENSORPORT4 13
#define ARMENCCHANNELA 7
#define ARMENCCHANNELB 6
#define LEFTSTEERINGENCODERA 12
#define LEFTSTEERINGENCODERB 11
#define RIGHTSTEERINGENCODERA 14
#define RIGHTSTEERINGENCODERB 13
#define EXTENDLIMITSWITCHPORT 4
#define RETRACTLIMITSWITCHPORT 8
#define PIVOTLIMITSWITCHUPPORT 10
#define PIVOTLIMITSWITCHDOWNPORT 9
#define MINIBOTLIMITSWITCHPORT 1
#define STEERINGLIMITFRONTRIGHT 2
#define STEERINGLIMITFRONTLEFT 3
#define STEERINGLIMITBACKRIGHT 4
#define STEERINGLIMITBACKLEFT 5
#define LFMOTORPORT 1
#define LRMOTORPORT 2
#define RFMOTORPORT 3
#define RRMOTORPORT 4
#define LEFTSTEERINGPORT 5
#define RIGHTSTEERINGPORT 6
#define EXTENDMOTORPORT 9
#define PIVOTMOTORPORT 10
#define CLAWTOPMOTORPORT 7
#define CLAWBOTTOMMOTORPORT 8
#define MINIBOTDEPLOYPORT 1
#define MINIBOTRETRACTPORT 2
#define BRAKEPORT 3
#define MINIBOTDEPLOYPORT2 4
#define COMPRESSORSWITCHPORT 12
#define COMPRESSORSPIKEPORT 8
#define CLAWSWITCHPORT 9
#define ULTRAPORT 3
#define ARMLIGHTSENSOR 10
#define SWERVEBLOCKENCODER1 8
#define SWERVEBLOCKENCODER2 6
#define AUTOSWITCHPORT 12
#define PREPICKUPEXTEND 35
// Arm positions
#define ARM_FULLUP 140
#define ARM_RACKTOP 120
#define ARM_RACKMIDDLE 30
#define ARM_RACKBOTTOM 12
#define ARM_HOME 0
// Arm extension limits
#define ARMEXTENDHOME 33
#define ARMEXTENDRACK 57
// Movement speed limits
#define ARMLIMITHEIGHT 25
#define ARMLIMITFACTOR 0.8
// Arm approach distances and speeds
#define ARMAPPROACHUP 25
#define ARMAPPROACHDOWN 25
#define ARMUPSPEED 1.0
#define ARMDOWNSPEED -1.0
#define ARMEXTENDSPEED 1
#define ARMDEADBAND 6
// Steering approach distance
#define STEERING_APPROACH_DISTANCE 100.0f
#define STEERING_DEADBAND 0.02f
// Function prototypes
float Abs(float); // Absolute value function
class MecanumDrive
{
public:
LPDRIVEMOTOR lfDrive; // Create a pointer to a Jag/Victor for the LF Motor
LPDRIVEMOTOR lrDrive; // Create a pointer to a Jag/Victor for the LR Motor
LPDRIVEMOTOR rfDrive; // Create a pointer to a Jag/Victor for the RF Motor
LPDRIVEMOTOR rrDrive; // Create a pointer to a Jag/Victor for the RR Motor
Victor* leftSteer; // Create a pointer to a Jag/Victor for the left steering motor
Victor* rightSteer; // Create a pointer to a Jag/Victor for the right steering motor
Victor* extendMotor; // Create a pointer to a victor for the arm extend motor
Victor* pivotMotor; // Create a pointer to a victor for the arm pivot motor
Victor* topclawmotor; // Create a pointer to a victor for the top claw motor
Victor* bottomclawmotor; // Create a pointer to a victor for the bottom claw motor
Encoder *leftSteeringEncoder; // Create a pointer to an encoder for the left steering motor
Encoder *rightSteeringEncoder; // Create a pointer to an encoder for the right steering motor
RobotDrive *robotDrive; // Create a pointer to a default drive system
DigitalInput *frontleftSteerLimit; // These limit switches prevent wheel rotation beyond limits
DigitalInput *frontrightSteerLimit; //
DigitalInput *backleftSteerLimit; //
DigitalInput *backrightSteerLimit; //
DigitalInput *ClawSwitch; // Limit switch on claw to detect tube presence
float output_speed; // Used by swerve drive
bool flag2, flag3; // Various flags used by swerve drive
int DriveReverse; // Either 1 or -1 for forward or reversed drive, respectively
float y_sign; // Sign of joystick y-movement for the drive reverse feature
int oldLeftEncoderValue, oldRightEncoderValue; // Hold the values of the encoders since the last time the swerve-synchronizing code was called
int trip; // Increment each time third sensor is tripped, to check for consistency and prevent noise from being a problem
public:
MecanumDrive(UINT32 lfMotor, UINT32 lrMotor, UINT32 rfMotor, UINT32 rrMotor)
{
lfDrive = new DRIVEMOTOR(lfMotor); // Create drive motor pointers
lrDrive = new DRIVEMOTOR(lrMotor);
rfDrive = new DRIVEMOTOR(rfMotor);
rrDrive = new DRIVEMOTOR(rrMotor);
extendMotor = new Victor(EXTENDMOTORPORT); // Create pointer to arm extend motor
pivotMotor = new Victor(PIVOTMOTORPORT); // Create pointer to arm pivot motor
topclawmotor = new Victor(CLAWTOPMOTORPORT); //Create a pointer to the top claw motor
bottomclawmotor = new Victor(CLAWBOTTOMMOTORPORT); // Create a pointer to the bottom claw motor
robotDrive = new RobotDrive(lfMotor, lrMotor, rfMotor, rrMotor); // The mecanum function assumes that a robot drive with this setup has been created
frontrightSteerLimit = new DigitalInput(DIGITALSIDECARTWO, STEERINGLIMITFRONTRIGHT); // Create steering limit switches
frontleftSteerLimit = new DigitalInput(DIGITALSIDECARTWO, STEERINGLIMITFRONTLEFT);
backrightSteerLimit = new DigitalInput(DIGITALSIDECARTWO, STEERINGLIMITBACKRIGHT);
backleftSteerLimit = new DigitalInput(DIGITALSIDECARTWO, STEERINGLIMITBACKLEFT);
ClawSwitch = new DigitalInput(DIGITALSIDECARTWO, CLAWSWITCHPORT); // Create a limit switch to detect tube presence in claw
leftSteeringEncoder = new Encoder(LEFTSTEERINGENCODERA, LEFTSTEERINGENCODERB); // Encoders to track rotation positions of motors
rightSteeringEncoder = new Encoder(RIGHTSTEERINGENCODERA, RIGHTSTEERINGENCODERB);
leftSteer = new Victor(LEFTSTEERINGPORT); // Motor controller for steering movement
rightSteer = new Victor(RIGHTSTEERINGPORT);
DriveReverse = 1; // Store the state of the drive reverse feature (1 = forward)
reset_variables(); // Reset and start all encoders and clear various state variables
}//End of MecanumDrive constructor
// Track the line and check the ultrasonic sensor distance for autonomous
int MoveSwerve(int leftSensor, int rightSensor, int endOfLineSensor, int armPivot, AnalogChannel *ultraDistance, int AutoMode)
{
int AUTOSTOPDISTANCE; // Stores the distance to stop (as read by the ultrasonic sensor)
if(AutoMode) AUTOSTOPDISTANCE = STRAIGHTLINEDISTANCE; // Straightline stopping distance
else AUTOSTOPDISTANCE = BRANCHEDLINEDISTANCE; // Y-branch stopping distance
// If we are within the decided distance from the wall
if(ultraDistance->GetVoltage() * 1000 < AUTOSTOPDISTANCE)
{
// Increment a trip counter
trip++;
// If we have been within the given distance for long enough, we can hopefully
// Rule out error on the part of the sensor, and stop, returning our state
if(trip > 320)
{
lfDrive->Set(0);
lrDrive->Set(0);
rfDrive->Set(0);
rrDrive->Set(0);
// Robot should stop moving
return 1;
}
}
// Anything too short to reach 320 was probably just interference from debris, so lower the trip value again
else if(trip > 0) trip--;
// If the right sensor hits the line
if (rightSensor)
{
// Stop the left motors
lfDrive->Set(0);
lrDrive->Set(0);
rfDrive->Set(0.9);
rrDrive->Set(0.9);
}
// If the right sensor has not hit the line, but the left one has,
// set the motors to turn right
else if (leftSensor)
{
lfDrive->Set(0.9);
lrDrive->Set(0.9);
rfDrive->Set(0);
rrDrive->Set(0);
}
// If neither sensor has hit the line, move forward normally
else
{
lfDrive->Set(0.4);
lrDrive->Set(0.4);
rfDrive->Set(0.4);
rrDrive->Set(0.4);
}
// Robot should continue moving
return 0;
}
// Swerve drive function
void DriveSwerve(Joystick *leftStick, Joystick *rightStick, Joystick *clawStick, DigitalInput *ArmPivotLimitDown, DigitalInput *ArmPivotLimitUp, DigitalInput *ArmRetractLimit, DigitalInput *ArmExtendLimit, Encoder *ArmEncoder, int ArmTarget, int ArmPosition, char AutonomousOverride, int ArmPickup, int ArmDeploy, int ArmExtendTarget)
{
static int monsterenabled = 0, carenabled = 0, align = 0, rotateSwitch = 0; // Steering modes and alignment state variables
static int syncDivider = 0; // We only call run the synchronization code periodically
static int aligntime = 0; // We need to give the wheels a little extra time after they reach their goal
float right_x, right_y, left_x, left_y, clawy; // Displacements of joystick axes
int SteerMode; // Between TANK, MONSTER, STRAFE, AUTOMONSTER(RIGHT/LEFT), and CAR
if(DRIVEREVERSEON) DriveReverse = -1;
if(DRIVEREVERSEOFF) DriveReverse = 1;
if (AutonomousOverride == 1)
{
right_x = left_x = -0.32;
right_y = left_y = 0.45;
}
else if (AutonomousOverride == 3)
{
right_x = left_x = 0.32;
right_y = left_y = 0.45;
}
else if (AutonomousOverride == 2)
{
// Return wheels to home and stop
right_x = 0.01;
right_y = 0.01;
left_x = 0.01;
left_y = 0.01;
}
// If the wheels are turned full left, indicating the end of the first stage of auto-align,
// reset the encoders so that this new position is considered center. Continue to stage three
else if (align == 2)
{
align = 3;
DriverStationLCD::GetInstance()->Clear();
DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line1, 1, "mode 2");
DriverStationLCD::GetInstance()->UpdateLCD();
rightSteeringEncoder->Reset();
leftSteeringEncoder->Reset();
}
// If we are in the final stage of wheel alignment, we set the goal to "full-right", which should translate to centre
// because the wheels are turned full-left.
// Once the wheels are centred, we reset the encoders again and exit wheel-alignment mode
else if (align >= 3)
{
DriverStationLCD::GetInstance()->Clear();
DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line1, 1, "mode 3");
DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line2, 1, "%d",
leftSteeringEncoder->Get());
DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line3, 1, "%d",
rightSteeringEncoder->Get());
DriverStationLCD::GetInstance()->UpdateLCD();
right_x = 1.0;
left_x = 1.0;
right_y = 0.01;
left_y = 0.01;
// If the steering motors have finished centering, reset them to center
// and exit auto-align mode
if(leftSteeringEncoder->Get() > AUTOALIGNSTOP && rightSteeringEncoder->Get() < -AUTOALIGNSTOP)
{
aligntime--;
if(aligntime < 1)
{
leftSteeringEncoder->Reset();
rightSteeringEncoder->Reset();
align = 0;
}
}
else aligntime++;
}
else
{
// Read position of left and right drive joysticks
right_x = rightStick->GetRawAxis(1);
right_y = rightStick->GetRawAxis(2);
left_x = leftStick->GetRawAxis(1);
left_y = leftStick->GetRawAxis(2);
}
// Get position of claw y-axis
clawy = clawStick->GetRawAxis(2);
// If the claw stick is less than the deadband, ignore it
if (Abs(clawy) <= JOYSTICK_DEADBAND_Y)
clawy = 0.0f;
// Check the monster/car/swerve buttons
if (SWERVEENABLEBUTTON)
monsterenabled = 0, carenabled = 0;
else if (MONSTERENABLEBUTTON)
monsterenabled = 1, carenabled = 0;
else if (CARENABLEBUTTON)
monsterenabled = 0, carenabled = 1;
// If the auto-align button is pressed, set the align flag and enter strafe mode
if (STEERALIGNBUTTON)
{
align = 1;
SteerMode = STRAFE;
monsterenabled = 0;
carenabled = 0;
}
// In case something goes wrong, this button exits auto-align mode prematurely
if (EXITSTEERALIGN && align > 0)
{
leftSteeringEncoder->Reset();
rightSteeringEncoder->Reset();
align = 0;
}
// If the arm should extend, set the motor forward
// If the arm should retract, set the motor backward
// Otherwise, stop any previous motion
if ((EXTENDBUTTON || ArmPickup == 1) && ArmExtendLimit->Get())
extendMotor->Set(1);
else if ((RETRACTBUTTON || ArmDeploy || ArmPickup == 2) && ArmRetractLimit->Get())
extendMotor->Set(-1);
else if(ArmExtendTarget == -1) // *&^%$#@!~`
extendMotor->Set(0);
// If the arm should pivot up, and the arm has not hit the limit switch, set the motor forward
// If the arm should pivot down, and the arm has not hit the limit switch, set the motor backward
// Otherwise, stop any previous motion
if (PIVOTUPBUTTON && ArmPivotLimitUp->Get())
pivotMotor->Set(ARMUPSPEED);
else if (PIVOTDOWNBUTTON && ArmPivotLimitDown->Get())
pivotMotor->Set(ARMDOWNSPEED);
else if (ArmTarget == -1)
pivotMotor->Set(0);
// If the arm hits the lower limit switch, reset the encoder
if (!ArmPivotLimitDown->Get())
ArmEncoder->Reset();
if(!ClawSwitch->Get() && clawy > 0 && !CLAWREVERSEBUTTON) clawy = 0;
/*// If the tube triggers the claw switch, enter rotate mode
// Otherwise, exit and reset the time counter
if(!ClawSwitch->Get()) rotateSwitch = 1;
else rotateSwitch = 0, rotateTime = 0;*/
// If it's in auto-pickup mode, the rollers should suck in
// Unless the switch has been hit
if(ArmPickup == 1 && !rotateSwitch)
{
topclawmotor->Set(-1);
bottomclawmotor->Set(1);
}
/*// If the switch has been hit, manipulate the tube for a period of time
// to point it upward
else if(ArmPickup && rotateTime < AUTOMANIPULATETIME)
{
rotateTime++;
topclawmotor->Set(-1);
bottomclawmotor->Set(-1);
}*/
// If it's in auto-deploy mode, the rollers should eject
else if(ArmDeploy)
{
topclawmotor->Set(1);
bottomclawmotor->Set(-1);
}
// If the trigger on the claw stick is pressed, set both motors in the same
// direction, according to the joystick axis
else if(!CLAWREVERSEBUTTON)
{
topclawmotor->Set(-clawy);
bottomclawmotor->Set(clawy);
}
else
{
// Otherwise, spin the motors inverse to each other.
// The motor that spins outward travels more slowly to
// prevent the tube from sliding out.
if(clawy > 0)
{
topclawmotor->Set(-clawy);
bottomclawmotor->Set(-clawy / 2);
}
else
{
topclawmotor->Set(-clawy / 2);
bottomclawmotor->Set(-clawy);
}
}
// If both joysticks have been tilted sideways by more than the dead band amount and monster mode is enabled, set to monster mode
// Otherwise, if both joysticks have been tilted sideways by more than the dead band amount, set to strafe mode
// Otherwise, set to tank mode
if ((Abs(right_x) > JOYSTICK_DEADBAND_X && Abs(left_x) > JOYSTICK_DEADBAND_X) || LOCKBUTTONPRESSED)
{
if (monsterenabled)
SteerMode = MONSTER;
else if (carenabled)
SteerMode = CAR;
else
SteerMode = STRAFE;
}
// If the left joystick points forward and the right points backward, enter full-angle monster clockwise
else if(left_y > JOYSTICK_DEADBAND_Y && right_y < -JOYSTICK_DEADBAND_Y)
{
SteerMode = AUTOMONSTER_RIGHT;
}
// If the right joystick points backward and the left joystick points backward, enter full-angle monster counter-clockwise
else if(left_y < -JOYSTICK_DEADBAND_Y && right_y > JOYSTICK_DEADBAND_Y)
{
SteerMode = AUTOMONSTER_LEFT;
}
else SteerMode = TANK;
//*******************************************************************************************
//STEERING ALIGNMENT
//*******************************************************************************************
// If steering alignment buttons are held on joystick and the auto-align mode is not running
if (rightStick->GetRawButton(8) && rightStick->GetRawButton(9) && !align)
{
if (rightStick->GetRawButton(6))
{ //move left steering to right
if (backrightSteerLimit->Get())
leftSteer->Set(-0.4);
else
leftSteer->Set(0);
leftSteeringEncoder->Stop();
leftSteeringEncoder->Reset();
flag2 = true; //***j
}
else if (rightStick->GetRawButton(7))
{ //move lrft steering to left
if (backleftSteerLimit->Get())
leftSteer->Set(0.4);
else
leftSteer->Set(0);
leftSteeringEncoder->Stop();
leftSteeringEncoder->Reset();
flag2 = true; //***j
}
else if (flag2)
{
leftSteer->Set(0);
leftSteeringEncoder->Start();
flag2 = false; //***j
}
if (rightStick->GetRawButton(10))
{ //move right steering to right
if (frontrightSteerLimit->Get())
rightSteer->Set(-0.4);
else
rightSteer->Set(0);
rightSteeringEncoder->Stop();
flag3 = true;
rightSteeringEncoder->Reset();
} else if (rightStick->GetRawButton(11))
{ //move right steering to left
if (frontleftSteerLimit->Get())
rightSteer->Set(0.4);
else
rightSteer->Set(0);
rightSteeringEncoder->Stop();
flag3 = true;
rightSteeringEncoder->Reset();
} else if (flag3)
{
rightSteer->Set(0);
rightSteeringEncoder->Start();
flag3 = false;
}
} //end of if steering alignment buttons are held on joystick
// If auto-align has been initiated, move until both limit switches are hit
else if (align == 1)
{
DriverStationLCD::GetInstance()->Clear();
DriverStationLCD::GetInstance()->Printf(DriverStationLCD::kUser_Line1, 1, "mode 1");
DriverStationLCD::GetInstance()->UpdateLCD();
if (frontleftSteerLimit->Get())
rightSteer->Set(0.5);
else
rightSteer->Set(0);
if (backrightSteerLimit->Get())
leftSteer->Set(-0.5);
else
leftSteer->Set(0);
if (!rightSteer->Get() && !leftSteer->Get())
align = 2;
}
//if steering position must come from drive joystick position (x,y)
else
{
//read position of each steering encoder
float leftSteeringEncoderVal = leftSteeringEncoder->Get();
float rightSteeringEncoderVal = rightSteeringEncoder->Get();
float leftSyncPercent = 1.0f; // These are used to scale the steering motor speeds
float rightSyncPercent = 1.0f; // to synchronize them
//CLEARMESSAGE;
//DISPLAYMESSAGE(2, (int)(leftSteeringEncoderVal));
//DISPLAYMESSAGE(3, (int)(rightSteeringEncoderVal));
//normalize the values (convert from counted integer >> real number from +1 to -1)
leftSteeringEncoderVal = leftSteeringEncoderVal / PULSES_PER_STEER;
rightSteeringEncoderVal = rightSteeringEncoderVal / PULSES_PER_STEER;
float leftgoal = 0;
float rightgoal = 0;
syncDivider++; // Count another call
// If enough of a delay has been incurred already, perform the synchronization code
if(syncDivider > STEERINGSYNCDIVIDER)
{
// Reset the divider
syncDivider = 0;
// Determine which steering unit is turning faster
int deltaLeft;
int deltaRight;
deltaLeft = oldLeftEncoderValue - (int)leftSteeringEncoderVal;
deltaRight = oldRightEncoderValue - (int)rightSteeringEncoderVal;
oldLeftEncoderValue = (int)leftSteeringEncoderVal;
oldRightEncoderValue = (int)rightSteeringEncoderVal;
if(abs(deltaLeft) > abs(deltaRight) + STEERINGSYNCDEADBAND && abs(deltaRight) > STEERINGSYNCDEADBAND)
{
// Left is moving too fast, so adjust
leftSyncPercent = (float)abs(oldLeftEncoderValue - oldRightEncoderValue) / STEERINGSYNCDISTANCE;
if(leftSyncPercent > 1.0f) leftSyncPercent = 1.0f;
else if(leftSyncPercent < 0.0f) leftSyncPercent = 0.0f;
leftSyncPercent = 1.0f - leftSyncPercent;
}
else if(abs(deltaRight) > abs(deltaLeft) + STEERINGSYNCDEADBAND && abs(deltaLeft) > STEERINGSYNCDEADBAND)
{
// Right is moving too fast, so adjust
rightSyncPercent = (float)abs(oldLeftEncoderValue - oldRightEncoderValue) / STEERINGSYNCDISTANCE;
if(rightSyncPercent > 1.0f) rightSyncPercent = 1.0f;
else if(rightSyncPercent < 0.0f) rightSyncPercent = 0.0f;
rightSyncPercent = 1.0f - rightSyncPercent;
}
}
if (SteerMode == TANK)
{
//point left wheels straignt towards the wide front
leftgoal = 0;
rightgoal = 0;
// Reverse the drive if necessary (DriveReverse is either 1 or -1). This is only for tank
left_y *= DriveReverse;
right_y *= DriveReverse;
// Swap the left and right drive settings if the drive has been reversed
if(DriveReverse == -1)
{
float temp;
temp = left_x;
left_x = right_x;
right_x = temp;
}
// If the arm is above a certain height, reduce movement sensitivity
if(ArmEncoder->Get() > ARMLIMITHEIGHT)
{
lfDrive->Set(left_y * ARMLIMITFACTOR);
lrDrive->Set(left_y * ARMLIMITFACTOR);
rfDrive->Set(right_y * ARMLIMITFACTOR);
rrDrive->Set(right_y * ARMLIMITFACTOR);
}
// Otherwise, don't limit speed
else
{
lfDrive->Set(left_y);
lrDrive->Set(left_y);
rfDrive->Set(right_y);
rrDrive->Set(right_y);
}
}
else if (SteerMode == STRAFE || SteerMode == MONSTER || SteerMode
== CAR || SteerMode == AUTOMONSTER_LEFT || SteerMode == AUTOMONSTER_RIGHT)
{
float deflection = 0;
float steer_angle = 0;
short quadrant = 0;
float y_avg = 0;
y_avg = (right_y + left_y) / 2;
if(y_avg == 0.0f) y_avg = JOYSTICK_DEADBAND_Y / 100;
y_sign = y_avg / Abs(y_avg); y_sign *= -1;
float x_avg;
x_avg = (left_x + right_x) / 2;
if(Abs(y_avg) > 0.8 && SteerMode == MONSTER)
{
SteerMode = CAR;
}
//determine output speed based on net joyustick deflection
deflection = sqrt((y_avg * y_avg) + (x_avg * x_avg)); //Pythagorean Theorem
//keep number within range. Ignore corners of joystick motion
if (deflection > 1)
{
deflection = 1;
}
else if (deflection < -1)
{
deflection = -1;
}
// If we are in auto-monster, the deflection should be set to the difference between the two joystick positions
if(SteerMode == AUTOMONSTER_LEFT || SteerMode == AUTOMONSTER_RIGHT) deflection = Abs(left_y - right_y) / 2;
if (align >= 1)
{ //no drive during alignment mode
deflection = 0;
}
// If the arm is above a certain height, reduce drive sensitivity
if(ArmEncoder->Get() > ARMLIMITHEIGHT) deflection *= ARMLIMITFACTOR;
//determine steering position based on joystick angle (measured in radians)
steer_angle = atan(Abs(x_avg) / Abs(y_avg)); //trigonometry Tan-1 = Opp / Adj
//conversion from radians to degrees
steer_angle = steer_angle * (180 / 3.14159);
//convert to normalized value (between forward >> 0.85 and sideways >> 0)
steer_angle = (steer_angle * 0.85) / 90;
// Reverse drive direction if necessary
deflection *= DriveReverse;
// If the lock button is pressed, we use a special quadrant
if(LOCKBUTTONPRESSED)
{
quadrant = 7;
SteerMode = STRAFE;
deflection *= LOCKBUTTONLIMIT;
}
//if joysticks are pointed in the right straight deadband
else if(x_avg > 0 && Abs(y_avg) <= JOYSTICK_DEADBAND_Y)
{
quadrant = 6;
}
//if joysticks are pointed in the left straight deadband
else if (x_avg < 0 && Abs(y_avg) <= JOYSTICK_DEADBAND_Y)
{
quadrant = 5;
}
//if joysticks are pointed in 4th quadrant
else if (x_avg > 0 && y_avg >= 0)
{
//to make driving easier, when the arm is up, the arm side becomes the "front"
//when the arm is down, the kicker side becomes the "front"
quadrant = 4;
}
//if joysticks are pointed in 3rd quardant
else if (x_avg < 0 && y_avg > 0)
{
quadrant = 3;
}
//if joysticks are pointed in 2nd quardant
else if (x_avg < 0 && y_avg <= 0)
{
quadrant = 2;
}
//if joysticks are pointed in 1st quadrant
else
{
quadrant = 1;
}
//set direction to drive and angle to steering based on quardant of motion
if (quadrant == 4)
{
rfDrive->Set(deflection);
rrDrive->Set(deflection);
lfDrive->Set(deflection);
lrDrive->Set(deflection);
leftgoal = steer_angle * -1;
rightgoal = steer_angle;
}
else if (quadrant == 3)
{
rfDrive->Set(deflection);
rrDrive->Set(deflection);
lfDrive->Set(deflection);
lrDrive->Set(deflection);
leftgoal = steer_angle;
rightgoal = steer_angle * -1;
}
else if (quadrant == 2)
{
rfDrive->Set(deflection * -1);
rrDrive->Set(deflection * -1);
lfDrive->Set(deflection * -1);
lrDrive->Set(deflection * -1);
leftgoal = steer_angle * -1;
rightgoal = steer_angle;
}
else if (quadrant == 1)
{
rfDrive->Set(deflection * -1);
rrDrive->Set(deflection * -1);
lfDrive->Set(deflection * -1);
lrDrive->Set(deflection * -1);
leftgoal = steer_angle;
rightgoal = steer_angle * -1;
}
else if (quadrant == 5)
{
if (align >= 1 || Abs(leftSteer->Get()) > 0.05)
{
rfDrive->Set(0);
rrDrive->Set(0);
lfDrive->Set(0);
lrDrive->Set(0);
DISPLAYSTRING(4, "Wheels turning");
}
else
{
rfDrive->Set(deflection * -1);
rrDrive->Set(deflection * -1);
lfDrive->Set(deflection * -1);
lrDrive->Set(deflection * -1);
DISPLAYSTRING(4, "Wheels stopped");
}
leftgoal = -0.85;
rightgoal = 0.85;
}
else if (quadrant == 6)
{
if(align >= 1 || Abs(leftSteer->Get()) > 0.05)
{
rfDrive->Set(0);
rrDrive->Set(0);
lfDrive->Set(0);
lrDrive->Set(0);
DISPLAYSTRING(4, "Wheels turning");
}
else
{
rfDrive->Set(deflection * -1);
rrDrive->Set(deflection * -1);
lfDrive->Set(deflection * -1);
lrDrive->Set(deflection * -1);
DISPLAYSTRING(4, "Wheels stopped");
}
leftgoal = 0.85;
rightgoal = -0.85;
}
// If we are in lock-mode
else if(quadrant == 7)
{
// If auto-align is enabled or the steering is still turning
// stop the drive motors
if(align >= 1 || Abs(leftSteer->Get()) > 0.05)
{
rfDrive->Set(0);
rrDrive->Set(0);
lfDrive->Set(0);
lrDrive->Set(0);
DISPLAYSTRING(4, "Wheels turning");
}
// Otherwise, use the direct joystick x-values to set the motor speed
else
{
rfDrive->Set(-x_avg);
rrDrive->Set(-x_avg);
lfDrive->Set(-x_avg);
lrDrive->Set(-x_avg);
DISPLAYSTRING(4, "Wheels stopped");
}
// Set goal position for steering to full right
leftgoal = 0.85;
rightgoal = -0.85;
}
} //end of if steering in strafe mode
//if MONSTER is steermode, invert the leftsteer goal
if(SteerMode == MONSTER)
{
leftgoal *= -1;
leftgoal *= DriveReverse;
rightgoal *= DriveReverse;
leftgoal *= y_sign;
rightgoal *= y_sign;
leftgoal *= 0.75;
rightgoal *= 0.75;
}
// In the case of either auto-monster, the deflection has already been calculated,
// so simply set the wheels to point either left and right or right and left in
// monster style
else if(SteerMode == AUTOMONSTER_LEFT)
{
leftgoal = -0.58;
rightgoal = -0.58;
leftgoal *= DriveReverse;