First draft of Wii Robot Racing, a simple example of using Wii Remote connected via bluetooth to control an m3pi robot, plus RFID \"powerups\" to modify behaviour
Dependencies: mbed m3pi ID12RFIDIRQ
main.cpp@0:e2ef12467862, 2011-04-11 (annotated)
- Committer:
- simon
- Date:
- Mon Apr 11 23:03:22 2011 +0000
- Revision:
- 0:e2ef12467862
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
simon | 0:e2ef12467862 | 1 | // mbed Robot Racing Wii example |
simon | 0:e2ef12467862 | 2 | // Connects to Wii Wheel/Remote to get control input to drive m3pi robots |
simon | 0:e2ef12467862 | 3 | // Also has RFID reader to trigger different powerups/slowdowns |
simon | 0:e2ef12467862 | 4 | // Robot has a simple inertial model to give it a more natural car-like driving acceleration and deceleration |
simon | 0:e2ef12467862 | 5 | |
simon | 0:e2ef12467862 | 6 | #include "mbed.h" |
simon | 0:e2ef12467862 | 7 | |
simon | 0:e2ef12467862 | 8 | #include "USBHost.h" // Peter Barratt's USB Bluetooth Dongle code |
simon | 0:e2ef12467862 | 9 | #include "m3pi.h" // m3pi robot controls |
simon | 0:e2ef12467862 | 10 | #include "Wiimote.h" // Wii Remote message decoding |
simon | 0:e2ef12467862 | 11 | #include "ID12RFID.h" // RFID reader |
simon | 0:e2ef12467862 | 12 | |
simon | 0:e2ef12467862 | 13 | Serial pc(USBTX, USBRX); |
simon | 0:e2ef12467862 | 14 | m3pi m3pi(p8,p9,p10); |
simon | 0:e2ef12467862 | 15 | |
simon | 0:e2ef12467862 | 16 | ID12RFID rfid(p14); |
simon | 0:e2ef12467862 | 17 | |
simon | 0:e2ef12467862 | 18 | #define ACCELERATE 0.02 |
simon | 0:e2ef12467862 | 19 | #define DECAY 0.01 |
simon | 0:e2ef12467862 | 20 | |
simon | 0:e2ef12467862 | 21 | static float clamp(float v, float mn, float mx) { |
simon | 0:e2ef12467862 | 22 | return (v < mn) ? mn : (v > mx) ? mx : v; |
simon | 0:e2ef12467862 | 23 | } |
simon | 0:e2ef12467862 | 24 | |
simon | 0:e2ef12467862 | 25 | Timer banana; |
simon | 0:e2ef12467862 | 26 | |
simon | 0:e2ef12467862 | 27 | // indicate a banana has been hit |
simon | 0:e2ef12467862 | 28 | void banana_hit() { |
simon | 0:e2ef12467862 | 29 | banana.reset(); |
simon | 0:e2ef12467862 | 30 | banana.start(); |
simon | 0:e2ef12467862 | 31 | } |
simon | 0:e2ef12467862 | 32 | |
simon | 0:e2ef12467862 | 33 | // see if there is any impact from bananas! |
simon | 0:e2ef12467862 | 34 | // returns 1.0 for full pain, decaying to 0.0 over time |
simon | 0:e2ef12467862 | 35 | float banana_impact() { |
simon | 0:e2ef12467862 | 36 | if(banana > 2.0) { |
simon | 0:e2ef12467862 | 37 | banana.stop(); |
simon | 0:e2ef12467862 | 38 | banana.reset(); |
simon | 0:e2ef12467862 | 39 | } |
simon | 0:e2ef12467862 | 40 | if(banana > 0) { |
simon | 0:e2ef12467862 | 41 | return clamp(2.0 - banana, 0.0, 1.0); |
simon | 0:e2ef12467862 | 42 | } else { |
simon | 0:e2ef12467862 | 43 | return 0; |
simon | 0:e2ef12467862 | 44 | } |
simon | 0:e2ef12467862 | 45 | } |
simon | 0:e2ef12467862 | 46 | |
simon | 0:e2ef12467862 | 47 | #define NORMAL_SPEED 0.3 |
simon | 0:e2ef12467862 | 48 | |
simon | 0:e2ef12467862 | 49 | volatile float max_speed = NORMAL_SPEED; |
simon | 0:e2ef12467862 | 50 | volatile float velocity = 0; |
simon | 0:e2ef12467862 | 51 | |
simon | 0:e2ef12467862 | 52 | Timer boost; |
simon | 0:e2ef12467862 | 53 | |
simon | 0:e2ef12467862 | 54 | void boost_impact() { |
simon | 0:e2ef12467862 | 55 | if(boost > 2.0) { |
simon | 0:e2ef12467862 | 56 | boost.stop(); |
simon | 0:e2ef12467862 | 57 | boost.reset(); |
simon | 0:e2ef12467862 | 58 | max_speed = NORMAL_SPEED; |
simon | 0:e2ef12467862 | 59 | } |
simon | 0:e2ef12467862 | 60 | } |
simon | 0:e2ef12467862 | 61 | |
simon | 0:e2ef12467862 | 62 | void boost_hit() { |
simon | 0:e2ef12467862 | 63 | max_speed = .7; |
simon | 0:e2ef12467862 | 64 | velocity = .7; |
simon | 0:e2ef12467862 | 65 | boost.reset(); |
simon | 0:e2ef12467862 | 66 | boost.start(); |
simon | 0:e2ef12467862 | 67 | } |
simon | 0:e2ef12467862 | 68 | |
simon | 0:e2ef12467862 | 69 | void slowmo_hit() { |
simon | 0:e2ef12467862 | 70 | max_speed = 0.15; |
simon | 0:e2ef12467862 | 71 | velocity = 0.0; |
simon | 0:e2ef12467862 | 72 | boost.reset(); |
simon | 0:e2ef12467862 | 73 | boost.start(); |
simon | 0:e2ef12467862 | 74 | } |
simon | 0:e2ef12467862 | 75 | |
simon | 0:e2ef12467862 | 76 | // this is called by the USB infrastructure when a wii message comes in |
simon | 0:e2ef12467862 | 77 | void wii_data(char * data) { |
simon | 0:e2ef12467862 | 78 | |
simon | 0:e2ef12467862 | 79 | Wiimote wii; |
simon | 0:e2ef12467862 | 80 | wii.decode(data); |
simon | 0:e2ef12467862 | 81 | |
simon | 0:e2ef12467862 | 82 | // temporary action triggers |
simon | 0:e2ef12467862 | 83 | if(wii.up) { banana_hit(); } |
simon | 0:e2ef12467862 | 84 | if(wii.down) { boost_hit(); } |
simon | 0:e2ef12467862 | 85 | if(wii.left) { slowmo_hit(); } |
simon | 0:e2ef12467862 | 86 | |
simon | 0:e2ef12467862 | 87 | if(wii.two) { // active acceleration |
simon | 0:e2ef12467862 | 88 | velocity += ACCELERATE; |
simon | 0:e2ef12467862 | 89 | if(velocity > max_speed) { velocity = max_speed; } |
simon | 0:e2ef12467862 | 90 | } else if(wii.one) { // active deceleration/reverse |
simon | 0:e2ef12467862 | 91 | velocity -= ACCELERATE; |
simon | 0:e2ef12467862 | 92 | if(velocity < -max_speed) { velocity = -max_speed; } |
simon | 0:e2ef12467862 | 93 | } else { // decay to zero |
simon | 0:e2ef12467862 | 94 | if(velocity < 0) { |
simon | 0:e2ef12467862 | 95 | velocity += DECAY; |
simon | 0:e2ef12467862 | 96 | if(velocity > 0) { velocity = 0; } |
simon | 0:e2ef12467862 | 97 | } else { |
simon | 0:e2ef12467862 | 98 | velocity -= DECAY; |
simon | 0:e2ef12467862 | 99 | if(velocity < 0) { velocity = 0; } |
simon | 0:e2ef12467862 | 100 | } |
simon | 0:e2ef12467862 | 101 | } |
simon | 0:e2ef12467862 | 102 | |
simon | 0:e2ef12467862 | 103 | float factor = wii.wheel / 190.0f; |
simon | 0:e2ef12467862 | 104 | |
simon | 0:e2ef12467862 | 105 | float left_factor = (factor >= 0.0) ? 1.0 : 1.0 - (-factor); |
simon | 0:e2ef12467862 | 106 | float right_factor = (factor <= 0.0) ? 1.0 : 1.0 - factor; |
simon | 0:e2ef12467862 | 107 | |
simon | 0:e2ef12467862 | 108 | boost_impact(); |
simon | 0:e2ef12467862 | 109 | float impact = banana_impact(); |
simon | 0:e2ef12467862 | 110 | |
simon | 0:e2ef12467862 | 111 | if(impact > 0.0) { |
simon | 0:e2ef12467862 | 112 | m3pi.left_motor(1 * impact); |
simon | 0:e2ef12467862 | 113 | m3pi.right_motor(-1 * impact); |
simon | 0:e2ef12467862 | 114 | velocity = 0; |
simon | 0:e2ef12467862 | 115 | } else { |
simon | 0:e2ef12467862 | 116 | m3pi.left_motor(velocity * right_factor); |
simon | 0:e2ef12467862 | 117 | m3pi.right_motor(velocity * left_factor); |
simon | 0:e2ef12467862 | 118 | } |
simon | 0:e2ef12467862 | 119 | } |
simon | 0:e2ef12467862 | 120 | |
simon | 0:e2ef12467862 | 121 | DigitalOut led_active(LED4); |
simon | 0:e2ef12467862 | 122 | |
simon | 0:e2ef12467862 | 123 | int main() { |
simon | 0:e2ef12467862 | 124 | pc.baud(38400); |
simon | 0:e2ef12467862 | 125 | |
simon | 0:e2ef12467862 | 126 | printf("Hello Wii Racing...\n"); |
simon | 0:e2ef12467862 | 127 | |
simon | 0:e2ef12467862 | 128 | USBInit(); |
simon | 0:e2ef12467862 | 129 | |
simon | 0:e2ef12467862 | 130 | |
simon | 0:e2ef12467862 | 131 | while (1) { |
simon | 0:e2ef12467862 | 132 | USBLoop(); |
simon | 0:e2ef12467862 | 133 | led_active = !led_active; |
simon | 0:e2ef12467862 | 134 | if(rfid.readable()) { |
simon | 0:e2ef12467862 | 135 | int id = rfid.read(); |
simon | 0:e2ef12467862 | 136 | // ignore id for now |
simon | 0:e2ef12467862 | 137 | banana_hit(); |
simon | 0:e2ef12467862 | 138 | } |
simon | 0:e2ef12467862 | 139 | } |
simon | 0:e2ef12467862 | 140 | } |