Exemple #1
0
Beh* behLight(Beh* lightPtr, int32 light_value[],int ErrorlightPtr[],boolean *TaskDone, boolean *IntegralWindup) {
	// this function compute control law  (tv, rv) to move robot toward light and sets TaskDone to 1 if the robot is at the light
	boolean done = FALSE;

	//assumption is fl is 0, fr is 1
	// commented out  for adding controller
	//if (abs(diff) < 10)
	//sensor_offset = -diff;

	//else
	//sensor_offset = 0;

	// end comment
	int32 tv;
	int32 rv;
	//static int32 integralError = 0;

	int32 diff;
	if ((abs(light_value[0]) < 1200) &&  (abs(light_value[1]) < 1200 ) && (abs(light_value[2]) < 1200 ) &&  (abs(light_value[3]) < 1200 )) {
		//ledsSetPattern(LED_BLUE, LED_PATTERN_ON, LED_BRIGHTNESS_LOW, LED_RATE_MED);
		//uint32 deltaTicks = encoder_delta_ticks(currentTime, prevTime);

		//if (max ( light_value[2] , light_value[3] ) > max(light_value[1],light_value[0])){
		//if ((light_value[2]> light_value[1]) || (light_value[3],light_value[0])){
		if ( min(light_value[2],light_value[3]) > (100 * max (light_value[1],light_value[0]) /100)){
		//if (light_value[2]>min(light_value[2],light_value[3]) ){
			// diff =  (max ( light_value[2] , light_value[3] ) -  max(light_value[1],light_value[0]));
			diff = MILLIRAD_PI /4;}
		else{
			diff = light_value[1] - light_value[0];}

		//behPIController(lightPtr, diff, ErrorlightPtr,IntegralWindup);
		behPController(lightPtr, diff);

		//behPIDController(lightPtr, diff,ErrorlightPtr, IntegralWindup);
		// #### commented out  for adding controller
		//lightPtr->tv = SPEED;
		//lightPtr->rv = (sensor_offset + diff) * K;
		// #### end comment

		*TaskDone = 0;
	}
	else {
		ledsSetPattern(LED_GREEN, LED_PATTERN_ON, LED_BRIGHTNESS_LOW, LED_RATE_MED);
		*TaskDone =1;
		lightPtr->tv = 0;
		lightPtr->rv = 0;
	}

	return lightPtr;
}
Exemple #2
0
void task2(void* parameters)
{
	int count = 0;

	while(TRUE)
	{
		if(count < 10)
		{
			serial_send_string_mutex((char*) parameters);
			++count;
		}
		ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED, LED_RATE_MED);
	}
}
Exemple #3
0
void behaviorTask(void* parameters) {

	/******** Variables *********/

	uint32 lastWakeTime = osTaskGetTickCount();
	uint32 neighborRound = 0;
	uint8 manipulationRobotsCounter = 0;

	/******** Variables Declared by JJF ********/

	//BroadcastMessage broadcastMessage;
	BroadcastMessage treeArray[MRM_ROBOT_COUNT_MAX]; // changed type
	nbrDataRobotList robotList[MRM_ROBOT_COUNT_MAX];

	/******** Initializations ********/
	radioCommandSetSubnet(2);

	neighborsInit(NEIGHBOR_ROUND_PERIOD);
	//TODO yo uonly need to call this function once
	irCommsSetXmitPower(MRM_IR_XMIT_COMMS_XMIT_POWER);

	systemPrintStartup();


	// make a robot list to sort all the robots
	robotListCreate(robotList, MRM_ROBOT_COUNT_MAX);  	// generate a robot list


	/* create all the trees, and set them to not be sources */
	for (i = 0; i < MRM_ROBOT_COUNT_MAX; ++i) {
		broadcastMsgCreate(&treeArray[i], MRM_TREE_MAX_HOP);  	// generate a broadcast tree
		//broadcastMsgSetSource(&tree_array[i], FALSE);		// I'm not the course yet myself as the source of the broadcastMessage
	}


//	int i;		// used as loop counter
//	for (i = 1; i < MAX_ROBOT_NUM; i++) {
//		broadcastMsgCreate(&tree_array[i], maxHop)
//	}

	/* add one manipultaion robot for ourself */
	manipulationRobotsCounter = 1;

	/******** Behavior **************/


	for (;;) {
		if (rprintfIsHost()) {
			ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
			continue;
		} //end if host
		else { // infinite loop starts from here

			BroadcastMessage tempTree;
			boolean treeExist = FALSE;
			NbrList nbrList;

			neighborsGetMutex();
			printNow = neighborsNewRoundCheck(&neighborRound);
			//cprintf("print %d \n",printNow);

			nbrListCreate(&nbrList);
			uint8 i;
			for (i = 0; i < manipulationRobotsCounter; i++){
				broadcastMsgUpdate(&treeArray[i], &nbrList);
			}



			//nbrListPrintHops(&nbrList, &broadcastMessage, "OMG");

//			uint8 tempSourceID = broadcastMessage.msgSourceID.value;
//			uint8 tempMsgHops = broadcastMessage.msgHops.value;
//			uint8 tempSenderID = broadcastMessage.senderID;
//
//			treeUpdate(&tree_array[0], tempSourceID,
//					tempSenderID, tempMsgHops);	// update my tree, it will be at the top of the array initially


//			// create a data wrapper that contains my broadcastMsg
//			nbrDataBroadcastMsgCreate(&broadcastMsgData, "broadcastMsg");

			for (i = 0; i < nbrListGetSize(&nbrList); i++) {
				nbrPtr = nbrListGetNbr(&nbrList, i);

				if (nbrPtr != NULL) {
					int j;
					uint8 tempSourceID;
					uint8 tempMsgHops;
					uint8 tempSenderID;

					for (j = 0; j < manipulationRobotsCounter; j++) {
						if (treeArray[j].msgSourceID.value == roneID) {
							tempSourceID = broadcastMsgGetSourceIDNbr(&treeArray[j], nbrPtr);
							tempMsgHops = broadcastMsgGetHopsNbr(&treeArray[j], nbrPtr);
							tempSenderID = broadcastMsgGetSenderIDNbr(&treeArray[j], nbrPtr);
							cprintf("In my message, my sourceID is %d, MsgHops is %d, SenderID is %d, tempSourceID is %d, tempMsgHop"
									"s is %d, tempSenderID is %d.\n",
									treeArray[j].msgSourceID.value, treeArray[j].msgHops.value, treeArray[j].senderID, tempSourceID, tempMsgHops, tempSenderID);
							break;
						}
					}


					if ( tempSourceID != 0) {

//						/* Update my broadcastMsg with tempSouceId, tempMsgHops, and tempSenderID */
//						broadcastMessage.senderID = tempSenderID;
//						broadcastMessage.msgSourceID.value = tempSourceID;
//						broadcastMessage.msgHops.value = tempMsgHops;
//						if (tempSourceID == roneID)
//							broadcastMessage.isSource == TRUE;
//						else
//							broadcastMessage.isSource == FALSE;
//
//						broadcastMsgUpdate(&broadcastMessage, &nbrList);



						for (j = 0; j < manipulationRobotsCounter; j++) {
							if (treeArray[j].msgSourceID.value == tempSourceID) {
								broadcastMsgUpdate(&treeArray[j], &nbrList);
								//treeUpdate(&tree_array[j], broadcastMessage.msgSourceID.value, broadcastMessage.senderID, broadcastMessage.msgHops.value);
								treeExist = TRUE;
								break;
							}
						}
						if (!treeExist) {
							cprintf("I am making a tree %d.\n", manipulationRobotsCounter);
							cprintf("after making a treebb, my sourceID is %d, senderID is %d, hopNum is %d.\n", treeArray[manipulationRobotsCounter].msgSourceID.value, treeArray[manipulationRobotsCounter].senderID, treeArray[manipulationRobotsCounter].msgHops.value);
							cprintf("msgUpdate nbrlist's length %d\n", nbrListGetSize(&nbrList));
							cprintf("robot no.%d Num hops: %d\n", treeArray[manipulationRobotsCounter-1].msgSourceID.value, treeArray[manipulationRobotsCounter-1].msgHops.value);
							broadcastMsgUpdate(&treeArray[manipulationRobotsCounter], &nbrList);
							cprintf("after making a tree, my sourceID is %d, senderID is %d, hopNum is %d.\n", treeArray[manipulationRobotsCounter].msgSourceID.value, treeArray[manipulationRobotsCounter].senderID, treeArray[manipulationRobotsCounter].msgHops.value);
							//treeUpdate(&tree_array[robot_counter], broadcastMessage.msgSourceID.value, broadcastMessage.senderID, broadcastMessage.msgHops.value);
							// sort the tree array;
							int loop_counter = manipulationRobotsCounter;
							while(loop_counter > 0) {
								if (treeArray[loop_counter].msgSourceID.value < treeArray[loop_counter-1].msgSourceID.value) {
									tempTree = treeArray[loop_counter];
									treeArray[loop_counter] = treeArray[loop_counter-1];
									treeArray[loop_counter-1] = tempTree;
								}
								loop_counter--;
							}
							manipulationRobotsCounter++;  // we increment robot_counter because we've updated a new tree in array
						} else {
							treeExist = FALSE;
						}
					}

				}
			}
			printTreeArray(&treeArray, manipulationRobotsCounter);


			///////////////////////////////////////////////////////////
			neighborsPutMutex(); // commented
			osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);

		} // END of else , if the robot is not Host

	} //forever for loop
} //behaviorTask()
void behaviorTask(void* parameters) {
	//rprintfSetSleepTime(500);

	uint32 lastWakeTime = osTaskGetTickCount();
	uint8 navigationMode = MODE_IDLE;
	Beh behOutput;
	boolean printNow;
	uint32 neighborRound = 0;
	NbrList nbrList;
	int i;
	Nbr* nbrPtr;

	BroadcastMessage broadcastMessage;
	broadcastMsgCreate(&broadcastMessage, 20);

	systemPrintStartup();
	systemPrintMemUsage();
	neighborsInit(NEIGHBOR_ROUND_PERIOD);
	radioCommandSetSubnet(1);

	NbrData guessWeight;
	NbrData guessX_1,guessX_2,guessX_3,guessX_4;
	NbrData guessY_1,guessY_2,guessY_3,guessY_4;

	nbrDataCreate(&(guessWeight), "guessWeight", 8, 0);
	nbrDataCreate32(&guessX_1,&guessX_2,&guessX_3,&guessX_4, "guessX_1", "guessX_2","guessX_3","guessX_4",0);			//in milliradians
	nbrDataCreate32(&guessY_1,&guessY_2,&guessY_3,&guessY_4, "guessY_1", "guessY_2","guessY_3","guessY_4",0);	 //in millimeters

	uint32 x,y, xprime, yprime, nbrOrient,nbrBear, nbrWeight, weightTot, xtot, ytot, xave, yave;
	uint8 roundWeight;

	//uint16 IRXmitPower = IR_COMMS_POWER_MAX/4;
	//GlobalRobotList globalRobotListPtr;
	//globalRobotListCreate(&globalRobotListPtr);

	for (;;) {
		if (rprintfIsHost()) {
			ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
			continue;
		}else{
			/*** INIT STUFF ***/
			behOutput = behInactive;
			neighborsGetMutex();
			printNow = neighborsNewRoundCheck(&neighborRound);
			//irCommsSetXmitPower(IRXmitPower);
			nbrListCreate(&nbrList);
			broadcastMsgUpdate(&broadcastMessage, &nbrList);

			//globalRobotListUpdate(&globalRobotListPtr, &nbrList);

			if(printNow){
			//	globalRobotListPrintAllTree(&globalRobotListPtr, &nbrList);
			}

			/*** READ BUTTONS ***/
			if (buttonsGet(BUTTON_RED)) {
				navigationMode = GUESSCOM;
			}else if (buttonsGet(BUTTON_GREEN)) {
			} else if (buttonsGet(BUTTON_BLUE)) {
			}

			/** STATES MACHINE **/
			switch (navigationMode) {
			case GUESSCOM: {
				ledsSetPattern(LED_RED, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
				break;
			}
			case MODE_IDLE:
			default: {
				ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
				break;
			}
			}
			if(navigationMode == GUESSCOM){
				roundWeight = 0;
				xtot = 0;
				ytot = 0;
				weightTot = 0;
				for (i = 0; i < nbrListGetSize(&nbrList); i++) {
					nbrPtr = nbrListGetNbr(&nbrList, i);
					nbrOrient = nbrGetOrientation(nbrPtr) + PI;
					nbrBear = nbrGetBearing(nbrPtr) + PI;
					x = nbrDataGetNbr32(&guessX_1,&guessX_2,&guessX_3,&guessX_4,nbrPtr);
					y = nbrDataGetNbr32(&guessY_1,&guessY_2,&guessY_3,&guessY_4,nbrPtr);
					if(printNow){
						cprintf("NBR: B%d O%d X%d Y%d ",nbrOrient,nbrOrient,x,y);
					}
					xprime = x*cosMilliRad(nbrOrient)/1000 - y*sinMilliRad(nbrOrient)/1000;
					yprime = x*sinMilliRad(nbrOrient)/1000 + y*cosMilliRad(nbrOrient)/1000;

					x = xprime;
					y = yprime + nbrEdgeDis;
					if(printNow){
						cprintf("MATH: X'%d Y'%d X''%d Y''%d ",xprime,xprime,x,y);
					}

					xprime = x*cosMilliRad(nbrBear)/1000 - y*sinMilliRad(nbrBear)/1000;
					yprime = x*sinMilliRad(nbrBear)/1000 + y*cosMilliRad(nbrBear)/1000;
					if(printNow){
						cprintf("X'''%d Y'''%d\n",xprime,xprime);
					}
					nbrWeight = nbrDataGetNbr(&guessWeight,nbrPtr);
					weightTot += nbrWeight;
					xtot += nbrWeight * xprime;
					ytot += nbrWeight * yprime;
					roundWeight++;
				}
				xave = xtot / weightTot;
				yave = ytot / weightTot;
				nbrDataSet32(&guessX_1,&guessX_2,&guessX_3,&guessX_4,xave);
				nbrDataSet32(&guessY_1,&guessY_2,&guessY_3,&guessY_4,yave);
				nbrDataSet(&guessWeight,roundWeight);
				if(printNow){
					cprintf("Guess: X %d Y%d Weight %d\n",xave,yave,weightTot);
				}
			}

			/*** FINAL STUFF ***/
			motorSetBeh(&behOutput);
			neighborsPutMutex();

			// delay until the next behavior period
			osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);
			lastWakeTime = osTaskGetTickCount();
		}//end not host
	} // end for loop
} //end behavior function
void
behaviorTask(void* parameters)
{
	int x, y;
	int i, dead;
	int state = STATE_IDLE;
	NbrList nbrList;
	uint32 c = 0;
	uint32 neighborsCheck;
	uint8 buttonRed, buttonGreen, buttonBlue;
	int16 bearing, orientation, newRV;
	int32 tv, rv;
	int32 tvR, rvR = 0;
	boolean foundObj = 0;
	Beh behU = behInactive;
	uint32 lastWakeTime = osTaskGetTickCount();
	char* RXmsg;

	radioCommandSetSubnet(2);

	/* Set LEDs to idle state pattern */
	ledsSetPattern(LED_GREEN,
			LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);

	/* Neighbor data sets for TV and RV */
	NbrData moving;

	/* Initialize nbrs and data */
    neighborsInit(200);
    nbrDataCreate(&moving, "moving", 8, 0);

	for (;;) {
		/* Receive user input and set state */
		buttonRed = buttonsGet(BUTTON_RED);
		buttonGreen = buttonsGet(BUTTON_GREEN);
		buttonBlue = buttonsGet(BUTTON_BLUE);

		if (buttonRed) {
			state = STATE_RECIEVE;
			ledsSetPattern(LED_RED,
					LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
		} else if (buttonBlue) {
			dead = 0;
			state = STATE_SEND;
			ledsSetPattern(LED_BLUE,
					LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
		} else if (buttonGreen) {
			state = STATE_IDLE;
			ledsSetPattern(LED_GREEN,
					LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
		}

		neighborsGetMutex();
		switch (state) {
		/* Receiving data from traveling robot */
		case STATE_RECIEVE: {
		    nbrDataSet(&moving, STATE_RECIEVE);
			/* Only print on a new nbr round */
			if (neighborsNewRoundCheck(&neighborsCheck)) {
				nbrListCreate(&nbrList);
				if(radioCommandReceive(&radioCmdRemoteControl, &radioMessageRX, 0))
					RXmsg = radioCommandGetDataPtr(&radioMessageRX);

				for (i = 0; i < nbrList.size; i++) {
					if (nbrDataGetNbr(&moving, nbrList.nbrs[i]) == STATE_SEND) {
						/* cprintf("%d,%d,%s",
							nbrList.nbrs[i]->orientation,
							nbrList.nbrs[i]->bearing,
							RXmsg); */
						rprintf("%d,%d,%s",
								nbrList.nbrs[i]->orientation,
								nbrList.nbrs[i]->bearing,
								RXmsg);
						c += 1;
					}
				}
			}
			break;
		}
		/* Drive in a U shaped path around neighbor */
		case STATE_SEND: {
		    nbrDataSet(&moving, STATE_SEND);
			nbrListCreate(&nbrList);

			/*if (nbrList.size > 0) {
				bearing = nbrList.nbrs[0]->bearing;

				// If we are still driving towards the nbr
				if (abs(bearing) < PI2) {
					behSetTvRv(&behU, TV_SPEED, 0);
				 //Orbiting the nbr
				} else {
					bearing -= PI2;

					if (bearing < 0) {
						newRV = (bearing - PI2) / 1.5;
						behSetTvRv(&behU, TV_SPEED, newRV);
					} else {
						newRV = (bearing + PI2) / 1.5;
						behSetTvRv(&behU, TV_SPEED, newRV);
					}

					if (abs(newRV) < 200)
						behSetTvRv(&behU, TV_SPEED, 0);
				}

				// If we have completed a half circle, just go forward
				orientation = nbrList.nbrs[0]->orientation;
				if (orientation > 2900)
					behSetTvRv(&behU, TV_SPEED, 0);
			// Go to idle if we lose the nbr
			} else {
				dead++;

				if (dead > 5) {
					state = STATE_IDLE;
					ledsSetPattern(LED_GREEN,
							LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
					break;
				}
			}*/
			if(irObstaclesGetBearing() || foundObj){
				foundObj = 1;
				behWallMove(&behU,TV_SPEED, WALL_FOLLOW_SIDE);
			} else{
				behSetTvRv(&behU,TV_SPEED,0);
			}

			/* Transmit tv and rv */
			motorGetTVRV(&tv, &rv);

			if (neighborsNewRoundCheck(&neighborsCheck)) {
				//cprintf("%d,%d\n", tv, rv);
				rprintf("%d,%d\n", x++, y++);
				x = x % 198;
				y = y % 173;
			}

			//sprintf(radioMessageTX.command.data, "%ld,%ld\n", tv, rv);
			//radioCommandXmit(&radioCmdRemoteControl, ROBOT_ID_ALL, &radioMessageTX);

			break;
		}
		/* Idle until active */
		case STATE_IDLE:
		default: {
			foundObj == 0;
		    nbrDataSet(&moving, STATE_IDLE);
			behU = behInactive;
			break;
		}
		}
		neighborsPutMutex();
		motorSetBeh(&behU);
		osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);
	}
}
Exemple #6
0
// behaviors run every 50ms.  They should be designed to be short, and terminate quickly.
// they are used for robot control.  Watch this space for a simple behavior abstraction
// to appear.
//
void behaviorTask(void* parameters)
{

	/******** Variables *********/
	uint32 lastWakeTime = osTaskGetTickCount();
	uint32 neighborRoundPrev = 0;
	uint32 neighborRound = 0;
	uint32 alpha = 0;
	uint8 i = 0;
	uint16 IRXmitPower = IR_COMMS_POWER_MAX;

	boolean newSensorData;
	int32 tv, rv;

	uint16 leader = 0;
	uint16 mode = INACTIVE;
	uint16 nbrMode = INACTIVE;
	uint16 nbrLeader = 0;
	uint16 wait = 0;
	uint32 rotateNum = 0;
	uint32 translateNum = 0;
	NbrData msgLeader;
	NbrData msgBearing;
	NbrData msgMode;
	NbrList nbrList;
	Nbr* nbrPtr;
	Nbr* leaderPtr;

	nbrDataCreate(&msgLeader, "leader", 1, 0);
	nbrDataCreate(&msgBearing, "bearing", 7, 0);
	nbrDataCreate(&msgMode, "mode", 2, 0);

	Beh behOutput;

	/******** Initializations ********/
	radioCommandSetSubnet(1);
	neighborsInit(NEIGHBOR_ROUND_PERIOD);
	broadcastMsgCreate(&broadcastMessage, 20);

	systemPrintStartup();

	/******** Behavior **************/
	for (;;)
	{

		behOutput = behInactive;
		neighborsGetMutex();
		printNow = neighborsNewRoundCheck(&neighborRound);
		cprintf("print %d \n",printNow);
		irCommsSetXmitPower(IRXmitPower);
		nbrListCreate(&nbrList);
		broadcastMsgUpdate(&broadcastMessage, &nbrList);

		//Check Buttons, won't start until leader selected
		if (buttonsGet(BUTTON_RED)==1)
		{
			leader = 1;
			mode = TRANSLATE;
		}
		// Checks Green button to stop behavior
		if (buttonsGet(BUTTON_GREEN)==1)
		{
			leader = 1;
			mode = ROTATE;
		}
		if (buttonsGet(BUTTON_BLUE)==1)
		{
			leader = 1;
			mode = LEADERSTOP;
		}

		translateNum = 0;
		rotateNum = 0;
		uint8 foundLeader = 0;
		uint32 interruptNum = 0;
		if (leader ==1){
			//do nothing
		} else {
			//check for mode change
			for (i = 0; i < nbrList.size; ++i){
				nbrPtr = nbrList.nbrs[i];
				nbrMode = nbrDataGetNbr(&msgMode, nbrPtr);
				nbrLeader = nbrDataGetNbr(&msgLeader, nbrPtr);
				if (nbrLeader == 1){
					foundLeader = 1;
					mode = nbrMode;
					leaderPtr = nbrPtr;
				} else {
					if (nbrMode != 0){
						if(nbrMode == 1){
							translateNum = translateNum +1;
						} else if (nbrMode == 2){
							rotateNum = rotateNum + 1;
						} else if (nbrMode == 3){
							interruptNum = interruptNum + 1;
						}
					}
				}
			}
			if (foundLeader != 1){
				if(translateNum > rotateNum && translateNum > interruptNum){
					mode = TRANSLATE;
				} else if (rotateNum > translateNum && rotateNum > interruptNum){
					mode = ROTATE;
				} else if (rotateNum == 0 && translateNum == 0 && interruptNum == 0){
					//dont change from previous mode
				} else if (interruptNum > translateNum && interruptNum > rotateNum){
					mode = LEADERSTOP;
				}	else {
					mode= TRANSLATE;
				}
			}
		}
		nbrDataSet(&msgLeader, leader);
		nbrDataSet(&msgMode, mode);
		if(printNow){
			cprintf("found? %d leader %d, mode %d \n",foundLeader,leader, mode);
		}

		switch(mode){
		case INACTIVE: {
			behOutput = behInactive;
			ledsSetPattern(LED_RED, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED, LED_RATE_MED);
			break;
		}
		case LEADERSTOP: {
			behOutput = behInactive;
			ledsSetPattern(LED_RED, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
			break;
		}
		case TRANSLATE: {
			ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
			if(leader){
				//move forward
				behSetTv(&behOutput,50);
			} else {
				alpha = behFlockAngle(&nbrList);
				if (abs(alpha) < 95){
					wait = wait + 1;
					behFlock(&behOutput, &nbrList, 50);
					//if (wait > 10) {
					//	behFlock(&behOutput, &nbrList, 50);
					//} else {
					//	behFlock(&behOutput, &nbrList, 0);
					//}
				} else {
					wait = 0;
					behFlock(&behOutput, &nbrList, 50);
				}
			}
			break;
		}
		case ROTATE: {
			ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_MED);
			if(leader){
				behOutput = behInactive;
			} else {
				behFlockNormalToLeader(&behOutput,&nbrList,50);
				//behOrbit(&behOutput,&nbrList,50);
			}
			break;
		}
		}//end mode switch
		motorSetBeh(&behOutput);
		neighborsPutMutex();
		osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);
	}//forever for loop
}//behaviorTask()
Exemple #7
0
// behaviors run every 50ms.  They should be designed to be short, and terminate quickly.
// they are used for robot control.  Watch this space for a simple behavior abstraction
// to appear.
//
void behaviorTask(void* parameters) {

	/******** Variables *********/
	uint32 lastWakeTime = osTaskGetTickCount();
	uint32 neighborRoundPrev = 0;
	uint32 neighborRound = 0;
	uint8 i = 0;
	uint16 IRXmitPower = IR_COMMS_POWER_MAX;

	boolean newSensorData;
	int32 tv, rv;

	uint16 leader = 0;
	uint16 mode = MODE_INACTIVE;
	uint16 nbrMode = MODE_INACTIVE;
	uint16 nbrLeader = 0;
	uint16 wait = 0;

	NbrData msgLeaderPosXR;
	NbrData msgLeaderPosYR;

	NbrData msgLeaderPosXS;
	NbrData msgLeaderPosYS;

	Nbr* nbrPtr;
	Nbr* leaderPtr;
	int32 translatetime = 0;
	int32 rotateTime = 0;
	NbrList nbrList;

	int32 nbrBearing = 0;
	int32 nbrDist = 0;
	int32 alpha;
	int32 flockAngleIntegral = 0;
	int32 flockAngleIntegral2 = 0;

	uint32 accelCounter = 0;
	int32 leaderPosY = 0;
	int32 leaderPosX = 0;
	Beh behOutput;

	/******** Initializations ********/
	radioCommandSetSubnet(1);
	neighborsInit(NEIGHBOR_ROUND_PERIOD);

	nbrDataCreate(&msgLeaderPosXR, "positionx", 8, 0);
	nbrDataCreate(&msgLeaderPosYR, "positiony", 8, 0);

	nbrDataCreate(&msgLeaderPosXS, "positionx", 8, 0);
	nbrDataCreate(&msgLeaderPosYS, "positiony", 8, 0);

	broadcastMsgCreate(&broadcastMessage, 20);
	broadcastMsgDataCreate(&broadcastData_Mode, &broadcastMessage, "mode",
			MODE_INACTIVE);
	broadcastMsgDataCreate(&broadcastData_DesiredHeading, &broadcastMessage,
			"heading", 0);
	uint32 senderID_seen = 0;

	systemPrintStartup();
	uint8 val = 0;
	int32 t = 0;
	int16 leaderBearing = 0;
	uint32 leaderDist = 0;
	int32 l1 = 0;
	int32 l2 = 0;
	/******** Behavior **************/
	for (;;) {
		behOutput = behInactive;
		neighborsGetMutex();
		printNow = neighborsNewRoundCheck(&neighborRound);
		//cprintf("print %d \n",printNow);
		//TODO yo uonly need to call this function once
		irCommsSetXmitPower(IRXmitPower);
		nbrListCreate(&nbrList);
		broadcastMsgUpdate(&broadcastMessage, &nbrList);
		if (broadcastMessage.active == TRUE) {
			if (broadcastMsgIsSource(&broadcastMessage)) {
				nbrDataSet(&msgLeaderPosXS, 0);
				nbrDataSet(&msgLeaderPosYS, 0);
				//nbrDataSet(&msgLeaderPosXR, 0);
				//nbrDataSet(&msgLeaderPosYR, 0);
				if (printNow) {
					cprintf("x: %d y: %d dist: %d bear: %d\n", 0, 0, 0, 0);
				}

			} else

			{
				int32 senderID = broadcastMsgGetSenderID(&broadcastMessage);

				//behFlockNormalToLeader(&behOutput, &nbrList, nbrPtr,tv);
				for (t = 0; t < nbrList.size; ++t) {
					nbrPtr = nbrList.nbrs[t];
					if (nbrPtr->ID == senderID) {
						senderID_seen = 1;
						nbrBearing = nbrGetBearing(nbrPtr);
						nbrDist = nbrGetRange(nbrPtr);

						if (printNow) {
							cprintf("dist: %d bear: %d\n", nbrDist, nbrBearing);
							//cprintf("posx: %d posy: %d \n",&msgLeaderPosX.value,&msgLeaderPosY.value);

						}
						l1 = ((int8) nbrDataGet(nbrPtr))	* LEADER_POS_SCALER;
						l2 = ((int8) nbrDataGet(&msgLeaderPosYR))
								* LEADER_POS_SCALER;

						leaderPosX = l1
								+ (int32)(
										nbrDist * cosMilliRad(nbrBearing)
												/ MILLIRAD_TRIG_SCALER);
						leaderPosY = l2
								+ (int32)(
										nbrDist * sinMilliRad(nbrBearing)
												/ MILLIRAD_TRIG_SCALER);
						leaderPosX = boundAbs(leaderPosX, LEADER_POS_BOUND);
						leaderPosY = boundAbs(leaderPosY, LEADER_POS_BOUND);

						nbrDataSet(&msgLeaderPosXS,
								(int8)(leaderPosX / LEADER_POS_SCALER));
						nbrDataSet(&msgLeaderPosYS,
								(int8)(leaderPosY / LEADER_POS_SCALER));
						int32 dist = leaderPosX * leaderPosX
								+ leaderPosY * leaderPosY;
						leaderDist = sqrtInt((uint32) dist);
						leaderBearing = atan2MilliRad(leaderPosY, leaderPosX);

						/*
						 * Problems:
						 * 	1- leader bearing not normalized
						 * 	2- distance never changes
						 */
						leaderBearing = normalizeAngleMilliRad2(leaderBearing);

					}
				}

				/*if (printNow) {
				 cprintf("x: %d y: %d dist: %d bear: %d\n", leaderPosX,
				 leaderPosY, leaderDist, leaderBearing);
				 //cprintf("posx: %d posy: %d \n",&msgLeaderPosX.value,&msgLeaderPosY.value);
				 cprintf("posx: %d posy: %d \n", l1, l2);

				 }*/

			}
		}
		//Check Buttons, won't start until leader selected
		if(buttonsGet(BUTTON_RED)&&buttonsGet(BUTTON_GREEN)){
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_COM);
			translatetime = 0;
			rotateTime = 0;
			val = MODE_COM;
		}else if (buttonsGet(BUTTON_RED)) {
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_TRANSLATE);
			val = MODE_TRANSLATE;
			translatetime = 0;
			rotateTime = 0;
		} else if (buttonsGet(BUTTON_GREEN)) {
			// Checks Green button to stop behavior
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_ROTATE);
			translatetime = 0;
			rotateTime = 0;
			val = MODE_ROTATE;

		} else if (buttonsGet(BUTTON_BLUE)) {
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_LEADERSTOP);
			translatetime = 0;
			rotateTime = 0;
			val = MODE_LEADERSTOP;

		}

		if (printNow)
			cprintf("hops, mode = %d,%d\n",
					broadcastMsgGetHops(&broadcastMessage),
					broadcastMsgDataGet(&broadcastData_Mode));

		//		uint32 translateNum = 0;
		//		uint32 rotateNum = 0;
		//		uint8 foundLeader = 0;
		//		uint32 interruptNum = 0;
		//		leaderPtr = NULL;
		//		if (broadcastMsgIsSource(&broadcastMessage)){
		//			//do nothing
		//		} else {
		//			//check for mode change
		//			for (i = 0; i < nbrList.size; ++i){
		//				nbrPtr = nbrList.nbrs[i];
		//				nbrMode = nbrDataGetNbr(&msgMode, nbrPtr);
		//				nbrLeader = nbrDataGetNbr(&msgLeader, nbrPtr);
		//				if (nbrLeader == 1){
		//					foundLeader = 1;
		//					mode = nbrMode;
		//					leaderPtr = nbrPtr;
		//					if(mode == MODE_ROTATE){
		//						translatetime = 0;
		//					}
		//					if(mode == MODE_TRANSLATE){
		//						rotateTime = 0;
		//					}
		//				} else {
		//					if (nbrMode != 0){
		//						if(nbrMode == 1){
		//							translateNum = translateNum +1;
		//						} else if (nbrMode == 2){
		//							rotateNum = rotateNum + 1;
		//						} else if (nbrMode == 3){
		//							interruptNum = interruptNum + 1;
		//						}
		//					}
		//				}
		//			}
		//			if (foundLeader != 1){
		//				if(translateNum > rotateNum && translateNum > interruptNum){
		//					mode = MODE_TRANSLATE;
		//					rotateTime = 0;
		//				} else if (rotateNum > translateNum && rotateNum > interruptNum){
		//					mode = MODE_ROTATE;
		//					translatetime = 0;
		//				} else if (rotateNum == 0 && translateNum == 0 && interruptNum == 0){
		//					//dont change from previous mode
		//				} else if (interruptNum > translateNum && interruptNum > rotateNum){
		//					mode = MODE_LEADERSTOP;
		//					translatetime = 0;
		//					rotateTime = 0;
		//				}	else {
		//					mode= MODE_TRANSLATE;
		//					rotateTime = 0;
		//				}
		//			}
		//		}
		if (printNow) {
			cprintf("sender: %d\n", broadcastMsgGetSenderID(&broadcastMessage));
		} else {
			val = broadcastMsgDataGet(&broadcastData_Mode);
			//cprintf("val: %d\n", val);
			broadcastMsgDataSet(&broadcastData_Mode, val);
		}
		switch (val) {
		case MODE_INACTIVE: {
			behOutput = behInactive;
			//cprintf("inactive \n");
			ledsSetPattern(LED_RED, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED,
					LED_RATE_MED);
			break;
		}
		case MODE_LEADERSTOP: {
			behOutput = behInactive;
			ledsSetPattern(LED_RED, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED,
					LED_RATE_MED);
			break;
		}
		case MODE_TRANSLATE: {
			translatetime = translatetime + 1;

			ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED,
					LED_RATE_MED);
			if (broadcastMsgIsSource(&broadcastMessage)) {
				//Pulsing Green LEDS indicate waiting to translate
				//Circling Green LEDS indicate translation has begun
				if (translatetime <= DELAY_TRANSLATE) { // set the time delay before start translating
					behSetTvRv(&behOutput, 0, 0);
					ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE,
							LED_BRIGHTNESS_LOW, LED_RATE_MED);
				} else {

					// TODO : add a timer for the duration of translation : if (translatetime <= TRANSLATE_ PERIOD)
					behSetTvRv(&behOutput, TV, 0);
					ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE,
							LED_BRIGHTNESS_LOW, LED_RATE_MED);
					// TODO : else {					behSetTvRv(&behOutput, TV, 0);
					//  					// mode = MODE_INACTIVE    }




				}
			} else {
				int32 tvgain, error;
				// either push or flock, depending on the experiment
				//				alpha = behFlockAngle(&nbrList);
				//				rvBearingController(&behMove, alpha, 90);
				//				error = behFlockAngleMax(&nbrList)/ 100;
				//				if(abs(error) > 3) {
				//					//behMove.tv = 0;
				//					if(error > 0) {
				//						motorSetPWM(MOTOR_LEFT, -PHOTOTAXIS_PWM);
				//						motorSetPWM(MOTOR_RIGHT, PHOTOTAXIS_PWM);
				//					} else {
				//						motorSetPWM(MOTOR_LEFT, PHOTOTAXIS_PWM);
				//						motorSetPWM(MOTOR_RIGHT, -PHOTOTAXIS_PWM);
				//					}
				//					cprintf("rotate    error % 4d  tv% 4d size% 4d\n",	error, behMove.tv, nbrList.size );
				//				} else {
				////					behMove.tv = FLOCK_TV;
				//					motorSetPWM(MOTOR_LEFT, PHOTOTAXIS_PWM);
				//					motorSetPWM(MOTOR_RIGHT, PHOTOTAXIS_PWM);
				//					cprintf("translate error % 4d  tv% 4d size% 4d\n",	error, behMove.tv, nbrList.size );
				//				}

				alpha = behFlockAngle(&nbrList); // consensus, be aligned with the leader
				// start PI controller
				error = alpha / 100;
				flockAngleIntegral = flockAngleIntegral * FLOCK_INTEGRAL_DECAY	/ 1000;
				flockAngleIntegral += (error * error) * (error > 0 ? 1 : -1);
				flockAngleIntegral = bound(flockAngleIntegral,
						-FLOCK_INTEGRAL_MAX, FLOCK_INTEGRAL_MAX);
				tvgain = 100 - (abs(flockAngleIntegral) * 100) / FLOCK_INTEGRAL_MAX;
				//tvgain = 100 - ((flockAngleIntegral*flockAngleIntegral) * 100)/(FLOCK_INTEGRAL_MAX*FLOCK_INTEGRAL_MAX);
				//behMove.rv = flockAngleIntegral;

				int32 rv_I = flockAngleIntegral * K_I / 100; //WEIGHTED TEST WORKS WITH 2
				int32 rv_P = error * K_P / 100; //WEIGHTED TEST WORKS WITH 2

				if (printNow) {
					cprintf(
							"error % 4d  flockAngleIntegral% 5d  rv_I% 4d  rv_P% 4d \n",
							alpha, flockAngleIntegral, rv_I, rv_P);
				}

				behOutput.rv = (rv_I + rv_P);

				//rv = ((100 - (networkSize*100)/4) * rv) / 100;

				behOutput.active = TRUE;

				//cprintf("error % 4d  flockAngleIntegral% 5d  tvgain% 4d  tv% 4d nbr% 4d\n",	alpha, flockAngleIntegral, tvgain, behMove.tv ,nbrGetID(nbrList ->nbrs));

				if (translatetime <= DELAY_TRANSLATE) { // set the time delay before start translating
					behOutput.tv = 0;
					ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE,
							LED_BRIGHTNESS_LOW, LED_RATE_MED);
				} else {

					// TODO : add a timer for the duration of translation : if (translatetime <= TRANSLATE_ PERIOD)

					//behOutput.tv = TV;
					behOutput.tv = TV_GAIN * FLOCK_TV * tvgain / 100;
					ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE,
							LED_BRIGHTNESS_LOW, LED_RATE_MED);


					// TODO : else {					behSetTvRv(&behOutput, 0, 0);
					// mode = MODE_INACTIVE    }



				}

			}
			//motorSetBeh(&behOutput);

			break;
		}
		case MODE_ROTATE: {
			translatetime = 0;
			rotateTime = rotateTime + 1;
			if (rotateTime <= DELAY_ROTATE) {
				behOutput.tv = 0;
				//behSetTvRv(&behOutput, 0, 0);
				ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_LOW,
						LED_RATE_MED);
			} else {

				if (broadcastMsgIsSource(&broadcastMessage)) {
					//if (rotateTime<=100){
					//	ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_SNAIL);
					//behOutput = behInactive;
					//} else {
					ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE,
							LED_BRIGHTNESS_MED, LED_RATE_MED);
					behOutput = behInactive;

					//}

				} else {

					//uint16 speed = 0;
					//	if (rotateTime <=100){
					//	tv = 0;
					//		speed = LED_RATE_SNAIL;
					//	} else {
					//	tv = TV;
					uint16 speed = LED_RATE_MED;
					//	}
					//	if(broadcastMsgIsSource(&broadcastMessage))
					//	{
					//	ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED, speed);
					//	behOutput = behInactive;
					//	nbrDataSet(&msgLeaderPosX , 0);
					//	nbrDataSet(&msgLeaderPosY , 0);

					//	} else {
					ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE,
							LED_BRIGHTNESS_MED, speed);
					int32 tv_gain, alpha;
					tv = 0;
					rv = 0;
					tv_gain = 0;
					behOutput.active = TRUE;
					//tv= TV_GAIN* nbrPtr->range/10;

					//alpha = behAngleNormalToLeader(leaderBearing);
					int32 error = alpha / 100;
					flockAngleIntegral2 = flockAngleIntegral2
							* FLOCK_INTEGRAL_DECAY / 1000;
					flockAngleIntegral2 += 1 * (error * error)
							* (error > 0 ? 1 : -1);
					flockAngleIntegral2 = bound(flockAngleIntegral2,
							-FLOCK_INTEGRAL_MAX, FLOCK_INTEGRAL_MAX);
					tv_gain = 100
							- (abs(flockAngleIntegral2) * 100)
									/ FLOCK_INTEGRAL_MAX;

					//leaderBearing = atan2MilliRad(leaderPosY , leaderPosX);
					//leaderDist = sqrtInt((uint32)dist) ;

					if (leaderBearing > 0) // turn to be normal to the leader
						alpha = normalizeAngleMilliRad2(
								leaderBearing - (int32) MILLIRAD_DEG_90);
					else

						alpha = normalizeAngleMilliRad2(
								leaderBearing + (int32) MILLIRAD_DEG_90);

					//uint32 leaderDist =dist/80 ;
					//alpha = MILLIRAD_DEG_30;
					//int32 FLOCK_RV_GAIN = 50;
					//rv = alpha * FLOCK_RV_GAIN / 100;

					int32 rv_I = 0 * flockAngleIntegral2 * K_I / 100; //WEIGHTED TEST WORKS WITH 2
					int32 rv_P = error * K_P; //WEIGHTED TEST WORKS WITH 2

					//	if (printNow) {
					//		cprintf(
					//				"error % 4d  flockAngleIntegral% 5d  rv_I% 4d  rv_P% 4d \n",
					//				alpha, flockAngleIntegral, rv_I, rv_P);
					//	}

					behOutput.rv = (rv_I + rv_P);

					//tv_gain = 1;
					tv = tv_gain * leaderDist / 4300; // set tv based on the distance to the leader

					//behOutput.rv = rv;
					behOutput.tv = tv;

					//cprintf("error % 4d  flockAngleIntegral% 5d  tvgain% 4d  tv% 4d nbr% 4d\n",	alpha, flockAngleIntegral, tvgain, behMove.tv ,nbrGetID(nbrList ->nbrs));

					//if (translatetime<=100){
					//	behOutput.tv = 0;
					//	ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
					//}
					//	else {
					//behOutput.tv = TV;0

					//	}
					//	motorSetBeh(&behOutput);

					ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE,
							LED_BRIGHTNESS_LOW, LED_RATE_MED);

					/*	if (senderID_seen == 1)

					 {
					 behOutput.rv = rv;
					 behOutput.tv = tv;

					 } else {
					 behOutput.rv = 0;
					 behOutput.tv = 0;
					 }


					 */

				}
				/*
				 for (i = 0; i < nbrList.size; ++i){
				 nbrPtr = nbrList.nbrs[i];
				 nbrLeader = nbrDataGetNbr(&msgLeader, nbrPtr);
				 //if (nbrLeader == 1)
				 if(broadcastMsgIsSource(&broadcastMessage))
				 {
				 tv= TV_GAIN* nbrPtr->range/10;
				 behFlockNormalToLeader(&behOutput, &nbrList, nbrPtr,tv);
				 }
				 }

				 if(leaderPtr != NULL){
				 ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED, speed);

				 motorSetBeh(&behOutput);

				 //behOrbitRange(&behOutput,leaderPtr,tv,2);
				 } else {
				 ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, speed);
				 }
				 */

				//}
			}

			break;
		}//end rotate
		case MODE_COM: {
			ledsSetPattern(LED_BLUE,LED_PATTERN_CLAW,LED_BRIGHTNESS_MED,LED_RATE_MED);
			break;
		}
		} //end mode switch
		  //motorSetBeh(&behOutput);
		motorSetBeh(&behOutput);

		neighborsPutMutex();
		osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);
	} //forever for loop
} //behaviorTask()
Exemple #8
0
void behaviorTask(void* parameters) {
	//rprintfSetSleepTime(500);

	uint32 lastWakeTime = osTaskGetTickCount();
	uint8 navigationMode = MODE_IDLE;
	Beh behOutput;
	uint8 i;
	boolean printNow, WAITING;
	uint32 neighborRound = 0;
	int RV;


	BroadcastMessage broadcastMessage;
	broadcastMsgCreate(&broadcastMessage, 20);

	systemPrintStartup();
	systemPrintMemUsage();
	neighborsInit(NEIGHBOR_ROUND_PERIOD);
	radioCommandSetSubnet(2);


	//uint16 IRXmitPower = IR_COMMS_POWER_MAX/4;

	boolean bounceGreen = 0;
	boolean bounceBlue = 0;
	boolean bounceRed  = 0;
	uint8 redCount = 0;
	uint8 blueCount = 0;

	//GRIPPER INIT
	gripperBoardInit();
	uint8 gripPos = REST;
	gripperGripRelax();
	for (;;) {
		if (rprintfIsHost()) {
			ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
			continue;
		}//end if host
		else{
			/*** INIT STUFF ***/
			behOutput = behInactive;
			neighborsGetMutex();
			printNow = neighborsNewRoundCheck(&neighborRound);


			/*** READ BUTTONS ***/
			if (buttonsGet(BUTTON_RED)) {
				navigationMode = ROT_LEFT;
				if(bounceRed){
					redCount++;
					if(redCount > 5){
						redCount = 0;
					}
				}
				bounceRed = 0;
			}
			if (buttonsGet(BUTTON_GREEN)) {
				gripPos = 0;
				navigationMode = MODE_IDLE;
			}
			if (buttonsGet(BUTTON_BLUE)) {
				navigationMode = ROT_RIGHT;
				if(bounceBlue){
					blueCount++;
					cprintf("1\n");
					if(blueCount > 5){
						blueCount = 0;
					}
				}
				bounceBlue = 0;
			}

			if (!buttonsGet(BUTTON_RED)) {
				bounceRed = 1;
			}
			if (!buttonsGet(BUTTON_GREEN)) {
				bounceGreen = 1;
			}
			if (!buttonsGet(BUTTON_BLUE)) {
				bounceBlue = 1;
			}

			/** STATES MACHINE **/
			switch (navigationMode) {
			case MODE_IDLE: {
				//Start Menu
				ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED, LED_RATE_SLOW);
				behOutput = behInactive;
				if(gripPos != ATTEMPTING){
					gripperGripUntilGripped();
					gripPos = ATTEMPTING;
				}
				cprintf("Idle");
				break;
			}
			case ROT_LEFT: {
				//Choose lowest robot amongst themselves to be controlled by remote
				navigationLEDsSet(redCount,0,blueCount,  0);
				RV = redCount*300;
				behSetTvRv(&behOutput, 0, RV);
				cprintf("Left RV %d ",RV);

				break;
			}
			case ROT_RIGHT: {
				//Robot to be controled by remote
				navigationLEDsSet(redCount,0,blueCount,  0);
				RV = blueCount*300;
				behSetTvRv(&behOutput, 0, -RV);
				cprintf("Right RV %d ",RV);
				break;
			}
			}

			cprintf("BUMP %d A X %d A Y %d A Z %d G X %d G Y %d G Z %d\n", bumpSensorsGetBearing(),
					accelerometerGetValue(ACCELEROMETER_X), accelerometerGetValue(ACCELEROMETER_Y), accelerometerGetValue(ACCELEROMETER_Z),
					gyroGetValue(GYRO_X_AXIS), gyroGetValue(GYRO_Y_AXIS), gyroGetValue(GYRO_Z_AXIS));
			/*** FINAL STUFF ***/
			motorSetBeh(&behOutput);
			neighborsPutMutex();

			// delay until the next behavior period
			osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);
			lastWakeTime = osTaskGetTickCount();
		}//end not host
	} // end for loop
} //end behavior function
Exemple #9
0
void behaviorTask(void* parameters) {
	//initialization
	uint32 lastWakeTime = osTaskGetTickCount();
	uint32 neighborRoundPrev = 0;
	uint32 neighborRound;
	uint8 neighbors;
	uint32 currentTime = osTaskGetTickCount();
	uint32 prevTime = 0;

	boolean reachedLightSource = FALSE;

	int32 integralError = 0;

	boolean targetSeen = 0;
	boolean lightActivated = 0;

	boolean TaskDone = 0;
	uint32 bumpSensorTimeOn = 0;
	uint32 bumpSensorTimeOff = 0;
	static boolean IntegralWindup = 0;

	uint8 currentState = MODE_IDLE;

	// search variables
	uint32 segmentNum = 0;
	uint32 TimeStart = currentTime;
	uint32 TimeForThisSegment = 0;
	static int ErrorLightPtr[2];
	ErrorLightPtr[0] = 0;
	ErrorLightPtr[1] = 0;
	//int ErrorlightPtr =&LightError;
	int32 light_value[4];


	neighborsInit(NEIGHBOR_ROUND_PERIOD);

	int32 light_value_init[4];

	light_value_init[0] = lightSensorGetValue(0); // front right light sensor
	light_value_init[1] = lightSensorGetValue(1); // front left light sensor
	light_value_init[2] = lightSensorGetValue(2); // rear left light sensor
	light_value_init[3] = lightSensorGetValue(3); // rear right sensor



	for (;;) {
		if (!rprintfIsHost()) {
			NbrList nbrList;
			Beh behMove = behInactive;

			neighborsGetMutex();
			nbrListCreate(&nbrList);

			currentTime = osTaskGetTickCount();
			buttonModeRGB(&currentState, MODE_FOLLOW_WALL_LEFT, MODE_IDLE, MODE_FOLLOW_WALL_RIGHT);


			uint8 bumpBits = bumpSensorsGetBits();

			if (bumpBits != 0 ) {
				bumpSensorTimeOn++;
				bumpSensorTimeOff = 0;
				isBumped = 1;
			}else{
				bumpSensorTimeOn = 0;
				bumpSensorTimeOff++;
			}

			light_value[0] = lightSensorGetValue(0)  - FR_OFFSET ; // front right light sensor
			light_value[1] = lightSensorGetValue(1); // front left light sensor
			light_value[2] = lightSensorGetValue(2); // rear left light sensor
			light_value[3] = lightSensorGetValue(3)  - RR_OFFSET; // rear right sensor
			//compute control law to move to light

			switch (currentState){
			case MODE_IDLE: {
				ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_SLOW);
				break;
			}
			case MODE_FOLLOW_WALL_LEFT: {
				behWallMove(&behMove, MOTION_TV, WALL_FOLLOW_LEFT);
				ledsSetPattern(LED_RED, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				break;
			}
			case MODE_FOLLOW_WALL_RIGHT: {
				behWallMove(&behMove, MOTION_TV, WALL_FOLLOW_RIGHT);
				ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				break;
			}
			case MODE_SEARCH_FOR_OBJECT:{
				ledsSetPattern(LED_RED, LED_PATTERN_ON, LED_BRIGHTNESS_MED, LED_RATE_MED);

				if(bumpSensorTimeOn > 5){
					currentState = MODE_TRANSPORT_TO_LIGHT;
				}
				//TODO: spiral mode.  For now, move straight
				//behSetTv(&behMove, SPEED);
				//behSetRv(&behMove, 0);

				// have we completed this segment?
				if( currentTime >= TimeStart+TimeForThisSegment ){
					segmentNum++;
					TimeStart = currentTime;
					// we want segments of length diameter*(1,1,2,2,3,3,4,4,5,5,...) to make a spiral path
					//    = (number)*robot_diameter_in_mm*1000 ms/s / SPEED_in_mm/s.
					TimeForThisSegment = ((segmentNum+1)/2)*110*1000/SPEED;
				}
				//Compute control law

				behSetTv(&behMove, SPEED);
				//  we added 100 to the multiplication to make a tighter spiral.
				behSetRv(&behMove,  MILLIRAD_DEG_90*1100/TimeForThisSegment);
				break;
			}
			case MODE_TRANSPORT_TO_LIGHT:{
				ledsSetPattern(LED_BLUE, LED_PATTERN_ON, LED_BRIGHTNESS_MED, LED_RATE_MED);

				/*if(bumpSensorTimeOff > 5){
					currentState = SEARCH_FOR_OBJECT;
					segmentNum = 0;
					TimeStart = currentTime;
					TimeForThisSegment = 0;
					break;

				}*/

				/*if ( TaskDone == 1 ){
					currentState = AT_LIGHT;
					break;
				}
*/
				// move toward the light
				behLight(&behMove , light_value, ErrorLightPtr,&TaskDone, &IntegralWindup );
				//behSetTv(behPtr, behPtr->tv);
				//behSetRv(behPtr, behPtr->rv);
				break;
			}
			case MODE_AT_LIGHT:{
				ledsSetPattern(LED_GREEN, LED_PATTERN_ON, LED_BRIGHTNESS_MED, LED_RATE_MED);
				behSetTvRv(&behMove, 0, 0);
				if ( TaskDone != 1 ){
					currentState = MODE_TRANSPORT_TO_LIGHT;
				}
				break;
			}
			}
			//cprintf("%d:%d,%d,%d,%d,%d,%d,%d\n", roneID, lightActivated, targetSeen, isBumped, bumpBits, light_value[0], light_value[1], TaskDone);


			motorSetBeh(&behMove);
			neighborsPutMutex();

			osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);

			//TODO: limit tv and rv.  (100 is a good limit?)
		}
	}
	return;
}
Exemple #10
0
void behaviorTask(void* parameters) {
	int state = STATE_IDLE;
	int movementState;
	int16 bumpBearing,rotateRV, currTv;
	uint32 lastWakeTime = osTaskGetTickCount();
	uint32 rotateTime, momentumTime;
	NbrList nbrList;
	Beh behOutput;
	uint8 buttonRed, buttonGreen, buttonBlue;
	boolean momementumActive, printNow;
	uint32 neighborRound = 0;
	int i;
	uint32 nbrBearing;

	Nbr* nbrPtr;
	NbrData type;
	NbrData velocity;

	// Init nbr system
	BroadcastMessage broadcastMessage;
	broadcastMsgCreate(&broadcastMessage, 20);
	radioCommandSetSubnet(1);
    neighborsInit(300);

    // Create nbr data
	nbrDataCreate(&type, "type", 2, 0);
	nbrDataCreate(&velocity, "velocity", 8, 0);

    // Print startup message and thread memory usage
	systemPrintStartup();
	systemPrintMemUsage();


	for (;;) {
		behOutput = behInactive;
		printNow = neighborsNewRoundCheck(&neighborRound);
		nbrListCreate(&nbrList);
		broadcastMsgUpdate(&broadcastMessage, &nbrList);
		// Determine state from buttons
		if (state == STATE_IDLE) {
			if (buttonsGet(BUTTON_RED)) {
				state = STATE_CUEBALL;
			} else if (buttonsGet (BUTTON_GREEN)) {
				state = STATE_POCKET;
			} else if (buttonsGet (BUTTON_BLUE)) {
				state = STATE_BALL;
			}
		}

		// Set LEDs for each state
		switch (state) {
		case STATE_CUEBALL: {
			ledsSetPattern(LED_ALL, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_SLOW);
			nbrDataSet(&type, STATE_CUEBALL);
			break;
		}
		case STATE_POCKET: {
			ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_SLOW);
			nbrDataSet(&type, STATE_POCKET);
			nbrDataSet(&velocity, 0);
			movementState = MOVE_IDLE;
			break;
		}
		case STATE_BALL: {
			nbrDataSet(&type, STATE_CUEBALL);
			if (roneID % 2)
				ledsSetPattern(LED_RED, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_SLOW);
			else
				ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED, LED_RATE_SLOW);
			break;
		}
		case STATE_IDLE:
		default: {
			ledsSetPattern(LED_ALL, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED, LED_RATE_SLOW);
			movementState = MOVE_IDLE;
			break;
		}
		}

		//Movement State Machine
		switch (movementState) {
			case MOVE_IDLE: {
				momementumActive = 0;
				behSetTvRv(&behOutput, 0, 0);
				nbrDataSet(&velocity, 0);
				if (bumpSensorsGetBearing() != -1) {
					movementState = MOVE_ROTATE;
					rotateTime = osTaskGetTickCount();
					bumpBearing = bumpSensorsGetBearing();

					if (state == STATE_CUEBALL){
						currTv = 150;
					} else if(state == STATE_BALL){
						//currTv = 75;
						for (i = 0; i < nbrList.size; i++){
							nbrPtr = nbrList.nbrs[i];
							nbrBearing = nbrGetBearing(nbrPtr);
							cprintf("NBR ID: %d, BB %d, NB %d\n",nbrGetID(nbrPtr),bumpBearing,nbrBearing);
							if(abs(nbrBearing -bumpBearing) < 500){
								currTv = nbrDataGetNbr(&velocity, nbrPtr);
								cprintf("currTv %d")
							}
						}
					}else{
						currTv = 0;
					}

					if(bumpBearing > 0){
						bumpBearing = PI - bumpBearing;
						rotateRV = -1000;
					} else{
						bumpBearing = PI - abs(bumpBearing);
						rotateRV = 1000;
					}
					//bearing = bearing * 1.25;
					behSetTvRv(&behOutput, 0, rotateRV);
				}
				break;
			}
Exemple #11
0
// behaviors run every 50ms.  They should be designed to be short, and terminate quickly.
// they are used for robot control.  Watch this space for a simple behavior abstraction
// to appear.
//
void behaviorTask(void* parameters) {

	/******** Variables *********/
	uint32 lastWakeTime = osTaskGetTickCount();
	uint32 neighborRoundPrev = 0;
	uint32 neighborRound = 0;
	uint8 i = 0;
	uint16 IRXmitPower = IR_COMMS_POWER_MAX;

	boolean newSensorData;
	int32 tv, rv;

	uint16 leader = 0;
	uint16 mode = MODE_INACTIVE;
	uint16 nbrMode = MODE_INACTIVE;
	uint16 nbrLeader = 0;
	uint16 wait = 0;

	NbrData msgLeaderPosX;
	NbrData msgLeaderPosY;
	NbrData msgNbrType;
	NbrDataFloat msgWeight;

	Nbr* nbrPtr;
	Nbr* leaderPtr = NULL;
	Nbr* safestGuidePtr = NULL;
	int32 translatetime = 0;
	int32 rotateTime = 0;
	NbrList nbrList;

	int32 nbrBearing = 0;
	int32 nbrDist = 0;
	int32 alpha;
	int32 flockAngleIntegral = 0;
	int32 flockAngleIntegral2 = 0;

	uint32 accelCounter = 0;
	int32 leaderPosY = 0;
	int32 leaderPosX = 0;
	Beh behOutput;

	/******** Initializations ********/
	radioCommandSetSubnet(1);
	neighborsInit(NEIGHBOR_ROUND_PERIOD);

	nbrDataCreate(&msgLeaderPosX, "positionx", 8, 0);
	nbrDataCreate(&msgLeaderPosY, "positiony", 8, 0);
	nbrDataCreate(&msgNbrType, "type", 2, TRANSPORT);
	nbrDataCreateFloat(&msgWeight, "weight");

	broadcastMsgCreate(&broadcastMessage, 20);
	broadcastMsgDataCreate(&broadcastData_Mode, &broadcastMessage, "mode",MODE_INACTIVE);
	broadcastMsgDataCreate(&broadcastData_DesiredHeading, &broadcastMessage,"heading", 0);
	uint32 senderID_seen = 0;

	irCommsSetXmitPower(IRXmitPower);
	systemPrintStartup();
	uint8 state = 0;
	int32 t = 0;
	int16 leaderBearing = 0;
	uint32 leaderDist = 0;
	/******** Behavior **************/
	for (;;) {
		behOutput = behInactive;
		neighborsGetMutex();
		printNow = neighborsNewRoundCheck(&neighborRound);
		nbrListCreate(&nbrList);
		broadcastMsgUpdate(&broadcastMessage, &nbrList);

		int32 senderID = broadcastMsgGetSenderID(&broadcastMessage);
		/**** Calculate Position to All Neighbors ****/
		for (t = 0; t < nbrList.size; ++t) {
			nbrPtr = nbrList.nbrs[t];
			if (nbrPtr->ID == senderID) {
				senderID_seen = 1;
				nbrBearing = nbrGetBearing(nbrPtr);
				nbrDist = nbrGetRange(nbrPtr);
				int32 l1 = ((int8)nbrDataGet(&msgLeaderPosX)) * LEADER_POS_SCALER;
				int32 l2 = ((int8)nbrDataGet(&msgLeaderPosY)) * LEADER_POS_SCALER;

				leaderPosX = l1 + (int32)(nbrDist * cosMilliRad(nbrBearing) / MILLIRAD_TRIG_SCALER);
				leaderPosY = l2 + (int32)(nbrDist * sinMilliRad(nbrBearing) / MILLIRAD_TRIG_SCALER);
				leaderPosX = boundAbs(leaderPosX, LEADER_POS_BOUND);
				leaderPosY = boundAbs(leaderPosY, LEADER_POS_BOUND);

				nbrDataSet(&msgLeaderPosX, (int8)(leaderPosX / LEADER_POS_SCALER));
				nbrDataSet(&msgLeaderPosY, (int8)(leaderPosY / LEADER_POS_SCALER));

				int32 dist = leaderPosX * leaderPosX + leaderPosY * leaderPosY;

				leaderBearing = atan2MilliRad(leaderPosY, leaderPosX);
				leaderDist = sqrtInt((uint32) dist);
			}
		}

		/**** Check Button Input ****/
		//Check Buttons, won't start until leader selected
		if (buttonsGet(BUTTON_RED)) {
			//Sets leader
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_INACTIVE);
			state = MODE_LEADER;
			translatetime = 0;
			rotateTime = 0;
		} else if (buttonsGet(BUTTON_GREEN)) {
			//Starts navigation mode
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_ROTATE);
			translatetime = 0;
			rotateTime = 0;
			state = MODE_ROTATE;

		} else if (buttonsGet(BUTTON_BLUE)) {
			//Stops all modes
			broadcastMsgSetSource(&broadcastMessage, TRUE);
			broadcastMsgDataSet(&broadcastData_Mode, MODE_LEADERSTOP);
			translatetime = 0;
			rotateTime = 0;
			state = MODE_LEADERSTOP;
		}

		/*** Debugging Prints ***/
		if (printNow){
			cprintf("hops, mode = %d,%d\n",broadcastMsgGetHops(&broadcastMessage),broadcastMsgDataGet(&broadcastData_Mode));
		}

		if (printNow) {
			cprintf("sender: %d\n", broadcastMsgGetSenderID(&broadcastMessage));
		} else {
			state = broadcastMsgDataGet(&broadcastData_Mode);
			cprintf("val: %d\n", state);
			broadcastMsgDataSet(&broadcastData_Mode, state);
		}

		/*** Determine Action ***/
		switch (state) {
		case MODE_LEADER: {
			//Leader flashes all LEDS
			ledsSetPattern(LED_ALL,LED_PATTERN_BLINK,LED_BRIGHTNESS_MED,LED_RATE_MED);

			/*** Select Safest Guide ***/
			Nbr* newSafestPtr = NULL;
			NbrDataFloat msgWeight;
			uint8 nbrType = UNSAFE;
			for(t = 0; t < nbrList.size; ++t){
				nbrPtr = nbrList.nbrs[t];
				nbrType = nbrDataGetNbr(&msgNbrType,nbrPtr);
				if(nbrType == TRANSPORT){
					//Ignore transport neighbors for choosing parent robot
					continue;
				} else {
					//Find minimum cost parent
					if(newSafestPtr != NULL){
						//If we have a guide selected, compare and determine if new should be selected
						if(nbrDataGetNbrFloat(&msgWeight,nbrPtr) < nbrDataGetNbrFloat(&msgWeight,newSafestPtr)){
							newSafestPtr = nbrPtr;
						}
					}
				}
			}
			if(newSafestPtr != NULL){
				//if we have a new safest guide with low weight, compare to current and switch or not
				if(newSafestPtr->ID != safestGuidePtr->ID){
					//switch guides
					safestGuidePtr = newSafestPtr;
				}
			}

			/*** Tell Others What to Do ***/

			break;
		}
		case MODE_INACTIVE: {
			behOutput = behInactive;
			//cprintf("inactive \n");
			ledsSetPattern(LED_RED, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED,LED_RATE_MED);
			break;
		}
		case MODE_LEADERSTOP: {
			behOutput = behInactive;
			ledsSetPattern(LED_RED, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED,LED_RATE_MED);
			break;
		}
		case MODE_TRANSLATE: {
			translatetime = translatetime + 1;

			if (broadcastMsgIsSource(&broadcastMessage)) {
				//Pulsing Green LEDS indicate waiting to translate
				//Circling Green LEDS indicate translation has begun
				if (translatetime <= 100) {
					behSetTvRv(&behOutput, 0, 0);
					ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE,LED_BRIGHTNESS_LOW, LED_RATE_MED);
				} else {
					behSetTvRv(&behOutput, TV, 0);
					ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE,LED_BRIGHTNESS_LOW, LED_RATE_MED);
				}
			} else {
				int32 tvgain, error;

				alpha = behFlockAngle(&nbrList);

				error = alpha / 100;
				flockAngleIntegral = flockAngleIntegral * FLOCK_INTEGRAL_DECAY / 1000;
				flockAngleIntegral += (error * error) * (error > 0 ? 1 : -1);
				flockAngleIntegral = bound(flockAngleIntegral,-FLOCK_INTEGRAL_MAX, FLOCK_INTEGRAL_MAX);
				tvgain = 100 - (abs(flockAngleIntegral) * 100) / FLOCK_INTEGRAL_MAX;

				int32 rv_I = flockAngleIntegral * K_I / 100; //WEIGHTED TEST WORKS WITH 2
				int32 rv_P = error * K_P / 100; //WEIGHTED TEST WORKS WITH 2

				if (printNow) {
					cprintf(
							"error % 4d  flockAngleIntegral% 5d  rv_I% 4d  rv_P% 4d \n",
							alpha, flockAngleIntegral, rv_I, rv_P);
				}
				behOutput.rv = (rv_I + rv_P);
				behOutput.active = TRUE;

				if (translatetime <= 100) {
					//If waiting to start translating, pulse green LEDS
					behOutput.tv = 0;
					ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE,LED_BRIGHTNESS_LOW, LED_RATE_MED);
				} else {
					//If translating, circling green LEDS
					behOutput.tv = 2 * FLOCK_TV * tvgain / 100;
					ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE,LED_BRIGHTNESS_LOW, LED_RATE_MED);
				}
			}

			break;
		}
		case MODE_ROTATE: {
			rotateTime = rotateTime + 1;
			if (broadcastMsgIsSource(&broadcastMessage)) {
				ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE, LED_BRIGHTNESS_MED,LED_RATE_MED);
				behOutput = behInactive;
				nbrDataSet(&msgLeaderPosX, 0);
				nbrDataSet(&msgLeaderPosY, 0);

			} else {
				uint16 speed = LED_RATE_MED;
				ledsSetPattern(LED_BLUE, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_MED,LED_RATE_MED);
				int32 tv_gain, alpha;
				tv = 0;
				rv = 0;
				tv_gain = 0;
				behOutput.active = TRUE;
				if (leaderBearing > 0)
					alpha = normalizeAngleMilliRad2(leaderBearing - (int32) MILLIRAD_DEG_90);
				else
					alpha = normalizeAngleMilliRad2(leaderBearing + (int32) MILLIRAD_DEG_90);
				int32 FLOCK_RV_GAIN = 50;
				rv = alpha * FLOCK_RV_GAIN / 100;
				tv_gain = 1;
				tv = tv_gain * leaderDist / 20;
				if (senderID_seen == 1){
					behOutput.rv = rv;
					behOutput.tv = tv;
				} else {
					behOutput.rv = 0;
					behOutput.tv = 0;
				}
			}
			break;
		}
		} //end mode switch

		//Set behavior and finish this task period
		motorSetBeh(&behOutput);
		neighborsPutMutex();
		osTaskDelayUntil(&lastWakeTime, BEHAVIOR_TASK_PERIOD);
	} //forever for loop
} //behaviorTask()
Exemple #12
0
// behaviors run every 50ms.  They should be designed to be short, and terminate quickly.
// they are used for robot control.  Watch this space for a simple behavior abstraction
// to appear.
void behaviorTask(void* parameters) {
	uint32 lastWakeTime = osTaskGetTickCount();
	Beh behOutput;
	uint32 neighborRound = 0;
	boolean printNow;
	uint8 mode = MODE_SENSE;
	char string[18];
	static uint32 printTime = 0;
	uint32 buttonTime = 0;
	int32 i;
	uint8 tileIDOld;

    neighborsInit(300);

    // wait for a sec to get initial magnetometer values
    osTaskDelay(500);
    magSetOffset();

    // init the sound task
    playworksSoundInit();
	tileIDOld = bumpSensorsGetBits();

	while (TRUE) {
		behOutput = behInactive;
		neighborsGetMutex();

		if ((osTaskGetTickCount() - printTime) > PRINT_TIME) {
			printTime += PRINT_TIME;
			printNow = TRUE;
		} else {
			printNow = FALSE;
		}

		switch (mode) {
		case MODE_PROGRAM: {
			//ledsSetPattern(LED_RED, LED_PATTERN_PULSE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
			if (buttonsGetEdge(BUTTON_RED)) {
				// add a left turn
				waypointListAdd(COMMAND_LEFT);
				ledsSetPattern(LED_RED, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_MED);
				buttonTime = osTaskGetTickCount();
			}
			if (buttonsGetEdge(BUTTON_GREEN)) {
				// add a forward motion
				waypointListAdd(COMMAND_FORWARD);
				ledsSetPattern(LED_GREEN, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_MED);
				buttonTime = osTaskGetTickCount();
			}
			if (buttonsGetEdge(BUTTON_BLUE)) {
				// add a right turn
				waypointListAdd(COMMAND_RIGHT);
				ledsSetPattern(LED_BLUE, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_MED);
				buttonTime = osTaskGetTickCount();
			}
			if ((osTaskGetTickCount() - buttonTime) > BUTTON_PRESS_TIME) {
				ledsSetPattern(LED_ALL, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_LOW, LED_RATE_MED);
			}

			if (((osTaskGetTickCount() - buttonTime) > COMMAND_EXECUTE_TIME) &&
					(waypointListWriteIdx > 0)) {
				waypointListReadIdx = 0;
				mode = MODE_MOVE;
				currentCommand = waypointReadCommand();
			}
			break;
		}
		case MODE_MOVE: {
			// read the waypoint list and move to the next waypoint
			switch (currentCommand) {
			case COMMAND_FORWARD: {
				uint32 distance = encoderGetOdometer() - motionOdometerStart;
				uint32 distanceToGoal = TILE_WIDTH - distance;
				int32 tv = computeVelRamp(MOTION_TV, MOTION_TV_MIN, MOTION_TV_RAMP_DISTANCE, distance, distanceToGoal);
				if (distance > TILE_WIDTH) {
					cprintf(",done\n");
					currentCommand = waypointReadCommand();
				} else {
					if (printNow) cprintf(",%d", distance);
					behSetTvRv(&behOutput, tv, 0);
				}
				ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				break;
			}
			case COMMAND_LEFT: {
				Pose pose;
				encoderGetPose(&pose);
				int32 angle = abs(smallestAngleDifference(motionPoseStart.theta, pose.theta));
				int32 angleToGoal = MILLIRAD_HALF_PI - angle;
				int32 rv = computeVelRamp(MOTION_RV, MOTION_RV_MIN, MOTION_RV_RAMP_DISTANCE, angle, angleToGoal);
				if (angle > MILLIRAD_HALF_PI) {
					cprintf(",done\n");
					currentCommand = waypointReadCommand();
				} else {
					if (printNow) cprintf(",%d", angle);
					behSetTvRv(&behOutput, 0, rv);
				}
				ledsSetPattern(LED_RED, LED_PATTERN_PULSE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				break;
			}
			case COMMAND_RIGHT: {
				Pose pose;
				encoderGetPose(&pose);
				int32 angle = abs(smallestAngleDifference(motionPoseStart.theta, pose.theta));
				int32 angleToGoal = MILLIRAD_HALF_PI - angle;
				int32 rv = computeVelRamp(MOTION_RV, MOTION_RV_MIN, MOTION_RV_RAMP_DISTANCE, angle, angleToGoal);
				if (angle > MILLIRAD_HALF_PI) {
					cprintf(",done\n");
					currentCommand = waypointReadCommand();
				} else {
					if (printNow) cprintf(",%d", angle);
					behSetTvRv(&behOutput, 0, -rv);
				}
				ledsSetPattern(LED_BLUE, LED_PATTERN_PULSE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				break;
			}
			case COMMAND_DONE: {
				cprintf(",done\n");
				waypointListWriteIdx = 0;
				waypointListReadIdx = 0;
				mode = MODE_PROGRAM;
			}
			default:
				break;
			}
			break;
		}
		default:
		case MODE_SENSE:
		case MODE_LINE_FOLLOW: {
			static int32 magMagFilteredLeft = 0;
			static int32 magMagFilteredRight = 0;
			static uint8 turningDirection = ROTATE_RIGHT;
			static int32 rvLineFollow = 0;
			static int32 tvLineFollow = 0;
			static uint32 rvDirectionChangeTime = 0;

			char rvDirChange[] = "   ";

		    if (buttonsGet(BUTTON_RED)) {
		    	magSetOffset();
			}
		    if (buttonsGet(BUTTON_GREEN)) {
		    	mode = MODE_LINE_FOLLOW;
			}

		    int32 magValues[MAG_AXES];
		    int32 x, y, z;
		    for (i = 0; i < MAG_AXES; i++) {
		    	magValues[i] = magGetValueLeftRaw(i) - magOffsetValuesLeft[i];
			}
		    x = magValues[MAG_X_AXIS];
		    y = magValues[MAG_X_AXIS];
		    z = magValues[MAG_X_AXIS];

		    int32 magMagLeft = sqrtInt(x*x + y*y + z*z);
		    magMagLeft = magMagLeft * 100 / 570;
		    int32 magMagFilteredPrevLeft = magMagFilteredLeft;
		    magMagFilteredLeft = filterIIR(magMagFilteredLeft, magMagLeft, MAG_IIR_TIME_CONSTANT);

		    for (i = 0; i < MAG_AXES; i++) {
		    	magValues[i] = magGetValueRightRaw(i) - magOffsetValuesRight[i];
			}
		    x = magValues[MAG_X_AXIS];
		    y = magValues[MAG_X_AXIS];
		    z = magValues[MAG_X_AXIS];

		    int32 magMagRight = sqrtInt(x*x + y*y + z*z);
		    magMagRight = magMagRight * 100 / 7565;
		    int32 magMagFilteredPrevRight = magMagFilteredRight;
		    magMagFilteredRight = filterIIR(magMagFilteredRight, magMagRight, MAG_IIR_TIME_CONSTANT);


		    //if (printNow) cprintf("mag,% 6d,% 6d,% 6d,% 6d,% 6d\n", x, y, z, magMag, magMagFiltered);
			//if (printNow) cprintf("left % 6d,% 6d right % 6d,% 6d\n", magMagLeft, magMagFilteredLeft, magMagRight, magMagFilteredRight);
		    uint8 tileID = bumpSensorsGetBits();
			if (tileIDOld != tileID) {
				playTileSound(tileID);
				tileIDOld = tileID;
			}
			if (printNow) cprintf("tile % 4d, left % 6d right % 6d\n", tileID, magMagFilteredLeft, magMagFilteredRight);

			if (mode == MODE_LINE_FOLLOW) {
				int32 diff = magMagFilteredLeft - magMagFilteredRight;
//				int32 rvDiff = rvLineFollowNew - rvLineFollow;
//				int32 tvLineFollowNew = 0;
//				if (rvDiff > RV_MAX_DIFF) {
//					rvLineFollow += RV_MAX_DIFF;
//					tvLineFollowNew = MOTION_TV/6;
//					ledsSetPattern(LED_RED, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
//				}else if (rvDiff < -RV_MAX_DIFF) {
//					rvLineFollow -= RV_MAX_DIFF;
//					tvLineFollowNew = MOTION_TV/6;
//					ledsSetPattern(LED_BLUE, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
//				}else {
//					rvLineFollow = rvLineFollowNew;
//					tvLineFollowNew = MOTION_TV/2;
//					ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
//				}

				int32 rvLineFollowNew = diff * RV_GAIN / 100;
				int32 tvLineFollowNew = 0;
				if (rvLineFollowNew > RV_MAX) {
					//rvLineFollow += RV_MAX_DIFF;
					//rvLineFollow = RV_MAX;
					tvLineFollowNew = MOTION_TV/3;
					ledsSetPattern(LED_RED, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				}else if (rvLineFollowNew < -RV_MAX) {
					//rvLineFollow -= RV_MAX_DIFF;
					//rvLineFollow = -RV_MAX;
					tvLineFollowNew = MOTION_TV/3;
					ledsSetPattern(LED_BLUE, LED_PATTERN_ON, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				} else {
					//rvLineFollow = rvLineFollowNew;
					tvLineFollowNew = MOTION_TV;
					ledsSetPattern(LED_GREEN, LED_PATTERN_PULSE, LED_BRIGHTNESS_HIGH, LED_RATE_FAST);
				}
				rvLineFollow = filterIIR(rvLineFollow, rvLineFollowNew, 50);


				tvLineFollowNew = MOTION_TV - MOTION_TV * abs(rvLineFollowNew) / RV_MAX;
				if ((tvLineFollowNew - tvLineFollow) > TV_MAX_DIFF) {
					tvLineFollow += TV_MAX_DIFF;
				}else if ((tvLineFollowNew - tvLineFollow) < -TV_MAX_DIFF) {
					tvLineFollow -= TV_MAX_DIFF;
				} else {
					tvLineFollow = tvLineFollowNew;
				}
				behSetTvRv(&behOutput, tvLineFollowNew, rvLineFollow);
				if (printNow) cprintf("left % 6d | right % 6d | rv % 6d | tv % 6d\n", magMagFilteredLeft, magMagFilteredRight, rvLineFollow, tvLineFollow);
			} else {
				ledsSetPattern(LED_GREEN, LED_PATTERN_CIRCLE, LED_BRIGHTNESS_HIGH, LED_RATE_MED);
			}
			break;
		}
		}

		//behSetTvRv(&behOutput, -200, 0);

		motorSetBeh(&behOutput);
		neighborsPutMutex();

		osTaskDelayUntil(&lastWakeTime, 20);
	}
}