Hak5
Save 10% at GoDaddy.com with coupon code HAK

HakHouse Rover

From Hak5

Jump to: navigation, search

3295209625_7fdd24226c.jpg

<embed type="application/x-shockwave-flash" src="http://revision3.com/player-v2741" allowfullscreen="true" width="555" height="312" />

Contents

[edit] Concept

What could be better than a remote controlled tank? A remote controlled tank powered by Linux.

Our aim is to build an inexpensive rover with all the bells and whistles you'd expect from an expensive off the shelf robot. Live streaming video? Check. Laser turret to play with the cat? Double check. RFID? Why not.

[edit] Build Parts


[edit] Code

This code isn't pretty but works as a proof of concept. Please feel free to contribute :)

With the Phidget drivers and documentation installed we modify the example file ifkit.c

[edit] C

// InterfacekitTest.cpp : Defines the entry point for the console application.
/*
	- Modified by ReDucTor
		* Removed While
		* Removed goto exit in while
		* Removed extra code in test_interfacekit
		* Insert code to accept arguments and use a switch
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <phidget21.h>

#define ROVER_FORWARD	0
#define ROVER_BACKWARD	1
#define ROVER_LEFT		2
#define ROVER_RIGHT		3


void display_generic_properties(CPhidgetHandle phid)
{
	int sernum, version;
	const char *deviceptr;
	CPhidget_getDeviceType(phid, &deviceptr);
	CPhidget_getSerialNumber(phid, &sernum);
	CPhidget_getDeviceVersion(phid, &version);

	printf("%s\n", deviceptr);
	printf("Version: %8d SerialNumber: %10d\n", version, sernum);
	return;
}


int IFK_DetachHandler(CPhidgetHandle IFK, void *userptr)
{
	printf("Detach handler ran!\n");
	return 0;
}

int IFK_ErrorHandler(CPhidgetHandle IFK, void *userptr, int ErrorCode, const char *unknown)
{
	printf("Error handler ran!\n");
	return 0;
}

int IFK_OutputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
{
	printf("Output %d is %d\n", Index, Value);
	return 0;
}

int IFK_InputChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
{
	printf("Input %d is %d\n", Index, Value);
	return 0;
}

int IFK_SensorChangeHandler(CPhidgetInterfaceKitHandle IFK, void *userptr, int Index, int Value)
{
	printf("Sensor %d is %d\n", Index, Value);
	return 0;
}


int IFK_AttachHandler(CPhidgetHandle IFK, void *userptr)
{
	CPhidgetInterfaceKit_setSensorChangeTrigger((CPhidgetInterfaceKitHandle)IFK, 0, 0);
	printf("Attach handler ran!\n");
	return 0;
}

int test_interfacekit(int direction, int duration)
{
	int numInputs, numOutputs, numSensors;
	int err;
	CPhidgetInterfaceKitHandle IFK = 0;

	CPhidgetInterfaceKit_create(&IFK);

	CPhidgetInterfaceKit_set_OnInputChange_Handler(IFK, IFK_InputChangeHandler, NULL);
	CPhidgetInterfaceKit_set_OnOutputChange_Handler(IFK, IFK_OutputChangeHandler, NULL);
	CPhidgetInterfaceKit_set_OnSensorChange_Handler(IFK, IFK_SensorChangeHandler, NULL);
	CPhidget_set_OnAttach_Handler((CPhidgetHandle)IFK, IFK_AttachHandler, NULL);
	CPhidget_set_OnDetach_Handler((CPhidgetHandle)IFK, IFK_DetachHandler, NULL);
	CPhidget_set_OnError_Handler((CPhidgetHandle)IFK, IFK_ErrorHandler, NULL);
	
	CPhidget_open((CPhidgetHandle)IFK, -1);

	//wait 5 seconds for attachment
	if((err = CPhidget_waitForAttachment((CPhidgetHandle)IFK, 5000)) != EPHIDGET_OK )
	{
		const char *errStr;
		CPhidget_getErrorDescription(err, &errStr);
		printf("Error waiting for attachment: (%d): %s\n",err,errStr);
		goto exit;
	}
	
	display_generic_properties((CPhidgetHandle)IFK);
	CPhidgetInterfaceKit_getOutputCount((CPhidgetInterfaceKitHandle)IFK, &numOutputs);
	CPhidgetInterfaceKit_getInputCount((CPhidgetInterfaceKitHandle)IFK, &numInputs);
	CPhidgetInterfaceKit_getSensorCount((CPhidgetInterfaceKitHandle)IFK, &numSensors);
	
	CPhidgetInterfaceKit_setOutputState((CPhidgetInterfaceKitHandle)IFK, 0, 1);

	printf("Sensors:%d Inputs:%d Outputs:%d\n", numSensors, numInputs, numOutputs);

	//	CPhidgetInterfaceKit_setOutputState(IFK, 0, 0);

	//CPhidgetInterfaceKit_setOutputState(IFK, 7, 1); // is this stuff needed
	//CPhidgetInterfaceKit_setOutputState(IFK, 7, 0); // i don't know. i only have 4 outputs
		
//this is where the stuff goes
// 0 left track forward
// 1 right track forward
// 2 left track backward
// 3 right track backward

	// Reset everything to zero -- workaround weird bug 0 always fires
	CPhidgetInterfaceKit_setOutputState(IFK, 0, 0);
	CPhidgetInterfaceKit_setOutputState(IFK, 1, 0);
	CPhidgetInterfaceKit_setOutputState(IFK, 2, 0);
	CPhidgetInterfaceKit_setOutputState(IFK, 3, 0);

	// Direction
	switch (direction)
	{
		case ROVER_FORWARD:
			CPhidgetInterfaceKit_setOutputState(IFK, 0, 1);
			CPhidgetInterfaceKit_setOutputState(IFK, 1, 1);
			break;
		case ROVER_BACKWARD:
			CPhidgetInterfaceKit_setOutputState(IFK, 2, 1);
			CPhidgetInterfaceKit_setOutputState(IFK, 3, 1);
			break;
		case ROVER_LEFT:
			CPhidgetInterfaceKit_setOutputState(IFK, 0, 1);
			CPhidgetInterfaceKit_setOutputState(IFK, 3, 1);
			break;
		case ROVER_LEFT:
			CPhidgetInterfaceKit_setOutputState(IFK, 1, 1);
			CPhidgetInterfaceKit_setOutputState(IFK, 2, 1);
			break;

	}

	//take a nap
	//sleep(1);
	usleep(duration);		

	// Reset everything again
	CPhidgetInterfaceKit_setOutputState(IFK, 0, 0);
	CPhidgetInterfaceKit_setOutputState(IFK, 1, 0);
	CPhidgetInterfaceKit_setOutputState(IFK, 2, 0);
	CPhidgetInterfaceKit_setOutputState(IFK, 3, 0);

exit:
	CPhidget_close((CPhidgetHandle)IFK);
	CPhidget_delete((CPhidgetHandle)IFK);

	return 0;
}

int main(int argc, char* argv[])
{
	int direction, duration;

	if(argc != 2) {
		printf("Usage:%s direction duration\n",argv[0]);
		return 1;
	}

	if(strcmp(argv[1],"forward") == 0) {
		direction = ROVER_FORWARD;
	} else if(strcmp(argv[1],"backward") == 0) {
		direction = ROVER_BACKWARD;
	} else if(strcmp(argv[1],"left") == 0) {
		direction = ROVER_LEFT;
	} else if(strcmp(argv[1],"right") == 0) {
		direction = ROVER_RIGHT;
	} else {
		printf("Invalid Direction\n");
		return 1;
	}

	if(strcmp(argv[2],"low") == 0) {
		direction = ROVER_DURATION_LOW;
	} else if(strcmp(argv[2],"mid") == 0) {
		direction = ROVER_DURATION_MID;
	} else if(strcmp(argv[2],"high") == 0) {
		direction = ROVER_DURATION_HIGH;
	} else {
		printf("Invalid Duration\n");
		return 1;
	}



	test_interfacekit(direction,duration);
	return 0;
}

[edit] PHP

I had originally written this bit of messy PHP:

<?php
/*
	- Modified by ReDucTor
		* Fixed switch having case values as constants
		* Removed Useless code
		* Moved to 0.0.2
		* Made a variable for file
		* Made it use arguments for direction/duration
		* Added Default to say piss off
*/
$verz="0.0.2"; 
$path = '/insert/path/to/file';
if (isset($_POST["rcmd"])) {
	$rcmd = $_POST["rcmd"];
switch ($rcmd) {
    case 'F':
        exec($path.' forward low'); break;
    case 'FF':
        exec($path.' forward mid'); break;
    case ''FFF:
        exec($path.' forward high'); break;
    case B:
        exec($path.' backward low'); break;
    case BB:
        exec($path.' backward mid'); break;
    case BBB:
        exec($path.' backward high'); break;
    case L:
        exec($path.' left low'); break;
    case LL:
        exec($path.' left low'); break;
    case LLL:
        exec($path.' left mid'); break;
    case R:
        exec($path.' right high'); break;
    case RR:
        exec($path.' right mid'); break;
    case RRR:
        exec($path.' right high'); break;
	default:
		die('Piss off');
	}
}
?>
<html>
<head><title>HakHouse Rover Control</title></head>
<body>
<center><h1>HakHouse Rover Control</h1><b>Version <?php echo $verz; ?></b></center>

<form method="post" action="<?php echo $PHP_SELF;?>">
<table border="0">
	<tr>
		<td></td>
		<td>
			<input type="submit" value="F" name="rcmd"> <input type="submit" value="FF" name="rcmd"> <input type="submit" value="FFF" name="rcmd">
		</td>
		<td></td>
	</tr>
	<tr>
		<td>
			<input type="submit" value="LLL" name="rcmd"><br/>
			<input type="submit" value="LL" name="rcmd"><br />
			<input type="submit" value="L" name="rcmd">
		</td>
		<td></td>
		<td>
			<input type="submit" value="R" name="rcmd"><br />
			<input type="submit" value="RR" name="rcmd"><br />
			<input type="submit" value="RRR" name="rcmd">
		</td>
	</tr>
	<tr>
		<td></td>
		<td>
			<input type="submit" value="B" name="rcmd"> <input type="submit" value="BB" name="rcmd"> <input type="submit" value="BBB" name="rcmd">
		</td>
		<td></td>
	</tr>
</table>
</form>

</body>
</html>

but then JZMan submitted this pretty code to the project:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>Hak5 Tank</title>

<LINK href="css/main.css" rel="stylesheet" type="text/css">

<script src="lib/jquery-1.3.min.js" type="text/javascript"></script>

</head>

<body>

	<script>

		 $(document).ready(function() {

		   $('#FL').click(function() {$.post("controller.php", {rcmd: "FL"});});

		   $('#FFF').click(function() {$.post("controller.php", {rcmd: "FFF"});});

		   $('#FR').click(function() {$.post("controller.php", {rcmd: "FR"});});

		   $('#RRR').click(function() {$.post("controller.php", {rcmd: "RRR"});});

		   $('#RR').click(function() {$.post("controller.php", {rcmd: "RR"});});

		   $('#R').click(function() {$.post("controller.php", {rcmd: "R"});});

		   $('#F').click(function() {$.post("controller.php", {rcmd: "F"});});

		   $('#B').click(function() {$.post("controller.php", {rcmd: "B"});});

		   $('#L').click(function() {$.post("controller.php", {rcmd: "L"});});

		   $('#LL').click(function() {$.post("controller.php", {rcmd: "LL"});});

		   $('#LLL').click(function() {$.post("controller.php", {rcmd: "LLL"});});

		   $('#BL').click(function() {$.post("controller.php", {rcmd: "BL"});});

		   $('#BBB').click(function() {$.post("controller.php", {rcmd: "BBB"});});

		   $('#BR').click(function() {$.post("controller.php", {rcmd: "BR"});});

		   $('#BB').click(function() {$.post("controller.php", {rcmd: "BB"});});

		   $('#FF').click(function() {$.post("controller.php", {rcmd: "FF"});});

		 });

	</script>

    <div id="MainCont">

    	<div id="FL"></div>

        <div id="FFF"></div>

    	<div id="FR"></div>

        <div id="RRR"></div>

    	<div id="RR"></div>

        <div id="R"></div>

        <div id="F"></div>

    	<div id="B"></div>

    	<div id="L"></div>

        <div id="LL"></div>

    	<div id="LLL"></div>

        <div id="BL"></div>

    	<div id="BBB"></div>

        <div id="BR"></div>

    	<div id="BB"></div>

        <div id="FF"></div>

        <div id="center"></div>

        <div id="mid"></div>         

    </div>

</body>

</html>

This html requires additional javascript, css and images. Download version 0.2 full package.

[edit] Ideas for future additions

  • Wireless Web Camera
    • This camera is on order
  • Laser Emitter Turret
    • This laser module emitter on order
  • RFID
    • This RFID kit is being considered
  • Ultrasonic distance sensors for obstacle sensing/avoidance
    • This or something cheaper