To build:

	% ./configure
	% make

Then try `./xbraitenberg --help'.

Other things to try:

	% ./xbraitenberg l v2a v2a v2a v2a
	% ./xbraitenberg l v2a v2b v3a v3b

The arguments here add objects to the world -- vehicles and lights. `v2a',
`v2b', `v3a', and `v3b' are four different kinds of Braitenberg vehicles,
based on Braitenberg's Vehicles 2A, 2B, 3A, and 3B. `l' is a stationary
light located at (0,0). There is also `timel', a "timed light" (see
TimedLight below) located at (0,0); and the pair of lights `l2a' and `l2b',
two stationary lights located at (-250,0) and (250,0).

You can use command line arguments to control the logic between sensors and
actuators. `--left-logic LOGIC' sets the left actuator's logic, and
`--right-logic LOGIC' sets the right actuator's logic. The LOGIC arguments
are C-like expressions. They are evaluated continuously to see how fast the
actuators should fire: 0 means stay still, positive numbers mean fire
forward, and negative numbers mean fire in reverse. The greater the
absolute value, the faster the actuators will fire; values are pinned
between -1 and 1. You can use the following constructs in the LOGIC
expressions. Most of them are just like C operators, and the precedence
follows C's precedence.

	left		The left sensor's value.
	right		The right sensor's value.

	E1 + E2		Addition.
	E1 - E2		Subtraction.
	E1 * E2		Multiplication.
	E1 / E2		Division.
	E1 ** E2	Exponentiation.

	E1 < E2		1 if E1 < E2; zero otherwise.
	E1 > E2		Other logical operators are similar.
	E1 <= E2
	E1 >= E2
	E1 == E2
	E1 != E2
	E1 && E2	1 if E1 != 0 and E2 != 0; zero otherwise.
	E1 || E2	1 if E1 != 0 or E2 != 0; zero otherwise.
	!E1		1 if E1 == 0; zero otherwise.

	E1 ? E2 : E3	If E1 != 0, then E2; otherwise E3.

	let VAR = E1 in E2 end
			Introduce a variable binding.
	VAR = E		Set variable's value. Also +=, -=, *=, /=, **=.
			You can set `left', `right', or variables introduced
			with `let'.
	E1, E2		Evaluate E1 for side effects. Return E2.

	pin(E)		Returns value of E pinned to be between 0 and 1.
			Same as (E < 0 ? 0 : (E < 1 ? E : 1)).
	flip(E)		Same as 1 - pin(E).

Each logic option only affects vehicles following the option on the command
line. The default vehicles have the following logic.

	VEHICLE		MIDDLE LOGIC
	v1		middle			(v1 has 1 sensor & 1 actuator.)

	VEHICLE		LEFT LOGIC		RIGHT LOGIC
	v2a		left			right
	v2b		right			left
	v3a		0.3 * flip(left)	0.3 * flip(right)
	v3b		0.3 * flip(right)	0.3 * flip(left)
	v2ap		same as v2a, but sensors detect restricted angles
	v2bp		same as v2b, but sensors detect restricted angles
	v3ap		same as v3a, but sensors detect restricted angles
	v3bp		same as v3b, but sensors detect restricted angles

You can change the world in other ways, but it requires changing the source
code -- specifically, main.cc. You can change how many stationary lights
there are, the kinds of headlights the vehicles have, how many sensors the
vehicles have, how strong the various lights are, and the angles that the
sensors can see, among other things. Here are some examples.


TO CHANGE:	the stationary lights
LOOK IN:	function make_default_vehicles(), around line 557
STATEMENTS:	shelf->add("l", new FixedLight(Point(0, 0), 8, 1));
		shelf->add("timel", new TimedLight(Point(0, 0), -M_PI, M_PI, 8, 1, 320));
		shelf->add("l2a", new FixedLight(Point(-250, 0), 10, 1));
		shelf->add("l2b", new FixedLight(Point(250, 0), 10, 1));
COMMENTS:	Add new lines to add new possible lights to the world. Then
		you can select those lights on the command line by giving
		their names. Arguments to `new FixedLight' are:
	(1) new FixedLight(POSITION, STRENGTH, 1)
	(2) new FixedLight(POSITION, ANGLE1, ANGLE2, STRENGTH, 1)
		The second form makes the light shine only through a
		specified angle range. You can also make a timed light, which
		will shine for only a short period of time:
	(3) new TimedLight(POSITION, ANGLE1, ANGLE2, STRENGTH, 1, DURATION)
		Examples:
		// a bright light
		shelf->add("brightl", new FixedLight(Point(0, 0), 16, 1));
		// a partial light in the upper-right corner
		shelf->add("cornerl", new FixedLight(Point(250, 250), -M_PI, -M_PI/2, 8, 1));


TO CHANGE:	the kinds of lights the vehicles have
LOOK IN:	function main(), around line 600
STATEMENTS:	//Light *headlight = new ThresholdLight(0, -M_PI, M_PI, 6, 1, .08);
		Light *headlight = new Light(0, -2*M_PI/5, 2*M_PI/5, 8, 1);
		//Light *headlight = new Light(0, -M_PI, M_PI, 8, 1);

COMMENTS:	This statement defines the kind of headlight vehicles will 
		have. Arguments to `new Light' are:
	(1) new Light(0, ANGLE1, ANGLE2, STRENGTH, 1)
		ANGLE1 and ANGLE2 are the angles through which the light
		shines. The angle zero is the direction the vehicle is
		heading. STRENGTH is the strength of the headlight.

		You can also make a threshold light, which only turns on
		when there is some light in the vicinity. Its arguments
		are:
	(2) new ThresholdLight(0, ANGLE1, ANGLE2, STRENGTH, 1, THRESHOLD)
		where THRESHOLD is the amount of light that must be in the
		vicinity before the headlight turns on.

		These lights are attached to a Vehicle with the
		Vehicle::make_attachment() method.


TO CHANGE:	the sensors the vehicles have
LOOK IN:	function make_default_vehicles(), around line 518
STATEMENTS:	Sensor *l_sensor = new Sensor(Point(10, -6), -M_PI, M_PI, 1, "left");
		Sensor *r_sensor = new Sensor(Point(10, 6), -M_PI, M_PI, 1, "right");
		//Sensor *l_sensor = new Sensor(Point(10, -6), -3*M_PI/4, M_PI/2, 1, "left");
		//Sensor *r_sensor = new Sensor(Point(10, 6), -M_PI/2, 3*M_PI/4, 1, "right");
		//Sensor *l_sensor = new Sensor(Point(10, -6), -M_PI/2, M_PI/2, 1, "left");
		//Sensor *r_sensor = new Sensor(Point(10, 6), -M_PI/2, M_PI/2, 1, "right");
COMMENTS:	The arguments to `new Sensor' are:
	(1) new Sensor(LOCATION, ANGLE1, ANGLE2, 1, NAME)
		LOCATION is the sensor's location, relative to the center of
		the vehicle. ANGLE1 and ANGLE2 specify the angles the sensor
		is sensitive to.

Please send comments and patches to <kohler@cs.ucla.edu>.
