1
#include "DriveRobot.h"
2
#include <libirobot/Robot.h>
3
#include <libirobot/Drive.h>
4
#include <libirobot/SerialControl.h>
5
#include <libirobot/sensors/BumpAndDropSensor.h>
6
#include <libirobot/sensors/BooleanSensor.h>
7
#include <libirobot/Song.h>
8
#include <libirobot/sensors/IRSensor.h>
9
#include <libirobot/sensors/ChargeSourceSensor.h>
10
#include <libirobot/sensors/UnsignedValueSensor.h>
11
#include <libirobot/sensors/ValueSensor.h>
12
#include <libirobot/Debug.h>
13
14
#include <math.h>
15
16
using namespace iRobot;
17
using namespace std;
18
19
#define QUARTER_NOTE 16 
20
21
DriveRobot::DriveRobot ( const char ttyDevice[] )
22
        : Robot ( ttyDevice ),
23
		  m_speed(0),
24
		  m_lastDir(Drive::Right),
25
		  m_tryingToDock(false),
26
		  m_dockAttempted(false),
27
		  m_dockTimeout(0)
28
{
29
    setMode ( Full );
30
    setAutoUpdate( Sensor::All, true );
31
32
	Song cliffMusic(2);
33
	Song::Note cliffnotes[] = {
34
		{ 60, QUARTER_NOTE },
35
		{ 57, QUARTER_NOTE },
36
	};
37
	for(int i = 0;i<2;i++) {
38
		cliffMusic.setNotePitch(i, cliffnotes[i].pitch);
39
		cliffMusic.setNoteLength(i, cliffnotes[i].length);
40
	}
41
	setSong(1, cliffMusic);
42
}
43
44
void
45
DriveRobot::avoid()
46
{
47
    Drive* d = getDrive();
48
	d->move(0);
49
    d->move(-(int)Drive::Medium );
50
    m_dockTimeout+=d->waitForDistance(100);
51
	d->move ( Drive::Medium, m_lastDir );
52
    d->waitForRotation(15);
53
}
54
55
bool
56
DriveRobot::reachedCliff()
57
{
58
		BooleanSensor* cliffLeft = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffLeft ) );
59
		BooleanSensor* cliffFrontLeft = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffFrontLeft ) );
60
		BooleanSensor* cliffFrontRight = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffFrontRight ) );
61
		BooleanSensor* cliffRight = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffRight ) );
62
		return cliffLeft->value() || cliffFrontRight->value() || cliffFrontLeft->value() || cliffRight->value();
63
}
64
65
DriveRobot::Side
66
DriveRobot::cliffSide()
67
{
68
    BooleanSensor* cliffLeft = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffLeft ) );
69
    BooleanSensor* cliffFrontLeft = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffFrontLeft ) );
70
    BooleanSensor* cliffFrontRight = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffFrontRight ) );
71
    BooleanSensor* cliffRight = static_cast<BooleanSensor*> ( getSensor( Sensor::CliffRight ) );
72
    if (cliffFrontLeft->value() && cliffFrontRight->value())
73
        return Center;
74
    if (cliffLeft->value() || cliffFrontLeft->value())
75
        return Left;
76
    if (cliffRight->value() || cliffFrontRight->value())
77
        return Right;
78
}
79
80
bool
81
DriveRobot::fellOffCliff()
82
{
83
    BumpAndDropSensor* s = static_cast<BumpAndDropSensor*> ( getSensor ( Sensor::BumpsAndDrops ) );
84
	return s->flags() & BumpAndDropSensor::DropAny;
85
}
86
87
void
88
DriveRobot::dock()
89
{
90
    Drive* d = getDrive();
91
	IRSensor* ir = static_cast<IRSensor*> ( getSensor( Sensor::IR ) );
92
	unsigned char c = ir->value();
93
	ChargeSourceSensor* sources = static_cast<ChargeSourceSensor*> ( getSensor( Sensor::ChargeSources ) );
94
	ValueSensor* distance = static_cast<ValueSensor*> ( getSensor( Sensor::Distance ) );
95
	m_dockTimeout+=distance->value();
96
	if (m_dockTimeout > 2000) {
97
		m_dockTimeout = 0;
98
		m_tryingToDock = false;
99
		m_dockAttempted = false;
100
	} else if (sources->sources() & ChargeSourceSensor::Base) {
101
		d->move(0);
102
		m_tryingToDock = false;
103
		return;
104
	} else if (m_tryingToDock) {
105
		if (m_dockAttempted) {
106
			d->move(-Drive::Medium);
107
            m_dockTimeout+=d->waitForDistance(300);
108
			if (m_lastDir == Drive::Right)
109
				d->move(Drive::Fast, Drive::Left);
110
			else
111
				d->move(Drive::Fast, Drive::Right);
112
			d->waitForRotation(180);
113
            d->move(Drive::Medium);
114
            m_dockTimeout+=d->waitForDistance(100);
115
            m_dockAttempted = false;
116
		} else if ((c == (unsigned char)IRSensor::RedAndGreenBuoysAndForceField || c == (unsigned char)IRSensor::ForceField) && bumped()) {
117
			d->move(-Drive::Slow);
118
            m_dockTimeout+=d->waitForDistance(15);
119
			d->move(0);
120
			delay(1000000);
121
			m_dockAttempted = true;
122
		} else if (c == (unsigned char)IRSensor::RedAndGreenBuoys || c == (unsigned char)IRSensor::RedAndGreenBuoysAndForceField) {
123
			d->move(170);
124
		} else if (c == (unsigned char)IRSensor::RedBuoy || c == (unsigned char)IRSensor::RedBuoyAndForceField) {
125
			d->move(Drive::Medium, 100);
126
			m_lastDir = Drive::Left;
127
		} else if (c == (unsigned char)IRSensor::GreenBuoy || c == (unsigned char)IRSensor::GreenBuoyAndForceField) {
128
			d->move(Drive::Medium, -100);
129
			m_lastDir = Drive::Right;
130
		} else {
131
			if (m_lastDir == Drive::Right)
132
				d->move(Drive::Medium, 200);
133
			else
134
				d->move(Drive::Medium, -200);
135
		}
136
	} else {
137
		if (c == (unsigned char) IRSensor::ForceField || c == (unsigned char)IRSensor::RedBuoy || c == (unsigned char)IRSensor::GreenBuoy || c == (unsigned char)IRSensor::RedAndGreenBuoys) {
138
			m_tryingToDock = true;
139
		} else {
140
			d->move(Drive::Medium);
141
		}
142
	}
143
}
144
145
bool
146
DriveRobot::bumped()
147
{
148
    BumpAndDropSensor* s = static_cast<BumpAndDropSensor*> ( getSensor ( Sensor::BumpsAndDrops ) );
149
    BooleanSensor* wall = static_cast<BooleanSensor*> ( getSensor ( Sensor::VirtualWall ) );
150
	return s->flags() & BumpAndDropSensor::BumpAny || wall->value();
151
}
152
153
bool
154
DriveRobot::bumpedLeft()
155
{
156
    BumpAndDropSensor* s = static_cast<BumpAndDropSensor*> ( getSensor ( Sensor::BumpsAndDrops ) );
157
	return s->flags() & BumpAndDropSensor::BumpLeft;
158
}
159
160
bool
161
DriveRobot::bumpedRight()
162
{
163
    BumpAndDropSensor* s = static_cast<BumpAndDropSensor*> ( getSensor ( Sensor::BumpsAndDrops ) );
164
	return s->flags() & BumpAndDropSensor::BumpRight;
165
}
166
167
void
168
DriveRobot::loop()
169
{
170
	m_powerColor++;
171
	uint8_t leds;
172
	if (m_powerColor > 128)
173
		leds = Play;
174
	else
175
		leds = Advance;
176
	setLEDs(leds, m_powerColor, ((float)m_powerColor/255)*255);
177
	BooleanSensor* song = static_cast<BooleanSensor*> ( getSensor( Sensor::SongPlaying ) );
178
	if (song->value())
179
		return;
180
	ChargeSourceSensor* sources = static_cast<ChargeSourceSensor*> ( getSensor( Sensor::ChargeSources ) );
181
	if (sources->sources() & ChargeSourceSensor::Base) {
182
		UnsignedValueSensor* battery = static_cast<UnsignedValueSensor*> ( getSensor( Sensor::BatteryCharge ) );
183
		UnsignedValueSensor* capacity = static_cast<UnsignedValueSensor*> ( getSensor( Sensor::BatteryCapacity ) );
184
		IROBOT_DEBUG("Battery: " << battery->value() << "/" << capacity->value() << " " << (int)((battery->value()/(float)capacity->value())*100) << "%");
185
		return;
186
	}
187
	dock();
188
    Drive* d = getDrive();
189
	if (fellOffCliff()) {
190
		d->move(0);
191
		if (!song->value()) {
192
			playSong(1);
193
			delay(1000000);
194
		}
195
	} else if (reachedCliff()) {
196
        if (cliffSide() == Left)
197
            m_lastDir = Drive::Left;
198
        if (cliffSide() == Right)
199
            m_lastDir = Drive::Right;
200
		avoid();
201
	} else if ( bumped() ) {
202
		if ( bumpedLeft() && bumpedRight() ) {
203
			avoid();
204
		} else if ( bumpedLeft() ) {
205
			d->move ( Drive::Medium, Drive::Right);
206
			m_lastDir = Drive::Right;
207
            delay ( 3000 );
208
		} else {
209
			d->move ( Drive::Medium, Drive::Left );
210
			m_lastDir = Drive::Left;
211
            BooleanSensor* wall = static_cast<BooleanSensor*> ( getSensor( Sensor::Wall ) );
212
            do {
213
                updateSensor( Sensor::Wall );
214
            } while (wall->value());
215
		}
216
		m_speed = 30;
217
	} else if (!m_tryingToDock) {
218
		if (m_speed < Drive::Medium)
219
			m_speed+=20;
220
		d->move ( m_speed );
221
	}
222
}
223
224
void
225
DriveRobot::disconnected()
226
{
227
    IROBOT_DEBUG("Disconnected.");
228
    exit ( 0 );
229
}