## The Motion Module

### Units and orientations

Before we can describe the functions in the Motion Module we have to define the units for distance and angles and the orientations. Distances are expressed in millimeters (mm), angles in tenths-of-degrees. The positive X direction is toward the goal of the guest team. The positive Y direction is to the left of the positive X direction.  Zero degrees is along of the positive X direction, measured counter-clockwise. The zero point for X and Y axes is in the center of the field. Because a picture says more than a thousand words:

Some Motion Module functions have a timing parameter, expressed in milliseconds (ms). But linear speeds are in millimeters per second (mm/s), not in mm/ms or m/s and rotational speeds are in tenths-of-degrees per second. Voltages are expressed in milliVolts.

int MtnStopModule(void);
Stops and exits the Motion Module. The motors will be stopped and set in limp mode (no power to the motors).

int MtnSetSpeedProfile(int max_acc, int max_speed, int max_rotation);
Sets the maximum linear acceleration and speed and the maximum rotation speed.

int MtnMoveDistance(int delta_dist, int delta_angle);
Move delta_dist mm along a circle, covering an arc delta_angle. This function will calculate the radius and the position of the circle. The robot will stop when the given distance has been traveled or when moving takes too long. This function may be called before a previous move command has completed. In that case, the new command will override the older.
The delta_dist and/or delta_angle may be zero. If both are 0, the motor controllers will keep the speed 0. This means the wheels can't turn and pushing the robot by hand is difficult.

int MtnMoveLongDistance(int delta_dist, int delta_angle, int timeout);
The same functionality as MtnMoveDistance, but with an added timeout parameter. Useful for movements which will take a long time to complete, but potentially very dangerous if the timeout is high and the robot is blocked. This can cause the destruction of the power amplifiers.

int MtnMoveContinuous(int speed, int rotation, int timeout);
Move the robot along a circle until timeout has elapsed, or a new move command has been given. The speed parameter specifies the tangential speed along the circle, the rotation the rotational speed around the center point of the circle. This function will calculate the radius and center point of the circle.

int MtnTriggerOnMoveDistDone(int command, int state);
If state is TRUE, tell the Motion Module to send a message command to the caller when a MtnMoveDistance command completes (because the given delta_dist has been reached, or because the timeout has elapsed). See below for the structure of the message. If state is FALSE, tell the Motion Module not to send these messages anymore.

int MtnTriggerOnMoveContDone(int command, int state);
If state is TRUE, tell the Motion Module to send a message command to the caller when a MtnMoveContinuous command completes (because the timeout has elapsed). See below for the structure of the message. If state is FALSE, tell the Motion Module not to send these messages anymore.

int MtnSetOdometer(int x, int y, int angle);
Set the odometer (the position in world coordinates based on the movement of the wheels) to the given x, y position and the angle orientation.
int MtnGetOdometer(int *x, int *y, int *angle, int *speed, int *rotation, struct timeval *stamp);
Get the odometer position x, y, orientation angle, tangential speed, rotational speed rotation and the timestamp. The timestamp stamp gives the moment when the data was received by the Motion Module from the robot controller, not when the data was actually generated!

int MtnGetDisplacement(int *delta_dist, int *delta_angle, struct timeval *stamp);
Get the displacement delta_dist and rotation delta_angle along the circle path since the start of the last move command, and the timestamp stamp for this measurement.

int MtnGetSpeed(int *linear, int *angular, struct timeval *stamp);
Get the current linear and rotational speeds and the timestamp stamp for this measurement.
int MtnSubscribePosition(int rate, int command, int state);
If state is TRUE, tell the Motion Module to send every rate ms a message command with odometer data to the caller. See below for the structure of the message. Do not expect any accurate timing for rate. The timing depends on the activity of the Motion Module & its users and the robot controller. Timing variations of 50 ms are not exceptional. If state is FALSE, tell the Motion Module not to send these messages anymore.

int MtnTriggerOnOdoOut(int x1, int y1, int x2, int y2, int command, int state);
If state is TRUE, tell the Motion Module to send a message command to the caller when the robot's odometer leaves the area bounded by x1, y1, x2 and y2 (x1 < x2, y1 < y2). See below for the structure of the message. Is state is FALSE, tell the Motion Module not to send these messages.

int MtnTriggerOnOdoIn(int x1, int y1, int x2, int y2, int command, int state);
If state is TRUE, tell the Motion Module to send a message command to the caller when the robot's odometer enters the area bounded by x1, y1, x2 and y2 (x1 < x2, y1 < y2). See below for the structure of the message. If state is FALSE, tell the Motion Module not to send these messages.

int MtnGetBatteryState(int *mvoltage, struct timeval *stamp);
Get the mvoltage from the power supply and the timestamp stamp for this measurement.

int MtnTriggerOnBatteryLow(int mvoltage, int command, int state);
If state is TRUE, tell the Motion Module to send a message command to the caller when the voltage of the power supply drops below mvoltage milliVolts. See below for the structure of the message. If state is FALSE, tell the Motion Module not to send these messages.

int MtnSetSonarSegments(int segments[16], int rate, int shots);
Set the number and order of sonars to fire. The segments array specifies the firing sequence. The sonar specified in segments[i] will be fired before that specified in segments[i+1]. If you not want to use all 16 sonars, you can terminate the list by specifying -1 in the array. The sonars not specified in segments will not be fired. The rate sets the time interval between the firing of 2 consecutive  sonars. The shots parameter is currently ignored.

int MtnGetSonarSegment(int segment, long *distance, struct timeval *stamp);
int MtnGetSonarSegments(long distances[16], struct timeval *stamp);
int MtnSubscribeSonars(int rate, int command, int state);
int MtnTriggerOnSonarNear(int distance, int segments[16], int command, int state);
int MtnTriggerOnSonarImpact(int speed, int segments[16], int command, int state);

/* Defines for trigger types */
#define MTN_TRIG_MOVE_DIST 0
#define MTN_TRIG_MOVE_CONT 1
#define MTN_TRIG_ODO_OUT 2
#define MTN_TRIG_ODO_IN 3
#define MTN_TRIG_BATTERY_LOW 4
#define MTN_TRIG_SONAR_NEAR 5
#define MTN_TRIG_SONAR_IMPACT 6
#define MTN_SUBS_POSITION 7
#define MTN_SUBS_SONAR 8

/* Structures for trigger messages */
int type;
};

int type;
int x1;
int y1;
int x2;
int y2;
int crossX;
int crossY;
};

int type;
int mvoltage;
};

int type;
int nearestSegment;
long distances[16];
};

int type;
int x;
int y;
int angle;
int speed;
int rotation;
struct timeval stamp;
};