This is not only the last appendix, but the most verbose. By nature this section must express a number of details important to the operation of the program. The most important concept to understand is that this program only defines functions for Sunview to call. Control is then passed to sunview, which interprets mouse and keyboard driven input, and calls my subroutines. This means that functions must be quite well structured.
There are two main data flows handled by Sunview; inputs and outputs. The inputs tend to be from buttons, toggles, menus and text. The buttons tend to trigger function calls. The text, menus and toggles call functions to register a change in value. As will be seen in the program listing, this results in a very elemental function structure to deal with. All outputs tend to be text or lines put into a graphics windows, or text output to the window the program was run from.
The first task the program performs is to set up the various graphics windows used by the user interface. This is done will calls to sunview to define positions of items, and indications of what action each item should trigger. This allows the construction of a sophisticated multi-part user interface. The interface is seen below for the main window. This window shows neural network controls at the top. In the middle the path endpoint buffer can be seen. The bottom shows the Robot display and controls toggles. After all of these were defined, a number of functions were devised to support sunview’s calls.
Figure L.1: Main Window for User Interface
L.2 Description of Functions in Neural Network Window:
A number of items are presented in the Neural Network window to empower the user to control the application of the neural network. The upper line reports whether a network is loaded, the number of the trajectories in the training set, and if the net has been trained since loading. Along the left hand side are controls for handling the neural network.
The first item on the left hand side is the neural network file name. This file name will be the target, or source, of a neural network file. There are three buttons below this which will load or save with the file name, or erase the entire neural network and training set. Below these, there are two more text inputs for setting the number of layers, and the width of the hidden layers. These may only be used before a network is created or loaded. Under this there are another four buttons. These buttons allow creation of a neural network, creation of a training set from all the endpoints in the buffer, addition of the current endpoint in the buffer, and clearing of the training set.
For training, the number of iterations, the smoothing rate, and the learning rate may be entered on the text lines on the bottom left hand side of the Neural Network window. The last two buttons on the left hand side allow training, and testing of the neural network with the settings. In the other regions of the screen there are miscellaneous items of varying importance.
The centre of the screen hosts locations for setting the neural network inputs and outputs. Note that the combination of inputs is not fixed, but there may only be one output type. Also, the only Network type made available to the user was the sigmoid. It is very easy to add other network paradigms to this list, but this was deemed unnecessary for current experimentation.
The time step may be entered on a text line at the bottom right of this window. This will update all time steps used by the program, for robot control. A file name input, and two buttons appear at the bottom right of the screen. These items are used for saving, and loading the training set from an arbitrary disk file. Finally, in the bottom right hand corner, a ‘Quit’ button appears. This button will cause the program to exit.
There are some general notes about operation of this window, in general. All of the inputs which affect the configuration of the network may not be changed when a neural network is loaded. These items are ‘Layer width’, ‘Total Layers’, ‘Network inputs’, Network Output’, and ‘Network Type’. This also means that these should all be preset before clicking on the ‘Make Neural Network’ button. The functions for the training set may be changed at any time.
Every item in this window is saved with the neural network, except the neural network file name.
L.3 Description of Functions in Path Endpoint Window:
The Path Endpoints are visible through the central windows, referred to as the ‘Buffer Control Window’. The first items in this window are the path endpoint file name, and two buttons for loading and saving to the file. The other buttons control actions on the path endpoint buffer. The buffer is visible on the right hand side, as a list. As can be seen in the figure, the list shows the start and stop joint angles for the robot paths. At the left side of the list a count number is assigned for reference. The highlighted line is the line currently pointed to for all operations.
The buttons allow various operations on the list. The ‘Up List’ and ‘Down List’ buttons allow movement of the pointer through the list. The ‘Swap Current’ button will swap the start and end joint angles in the robot window for the current buffer line. If the ‘Insert’ button is used the start and end in the robot window will be inserted into the current line, and the other elements moved down. ‘Delete’ will erase the current line, and move the other lines forward by one position.
The start or end points in the Robot window are updated to the current robot position when the ‘Choose a Start Point’, or ‘Choose a Stop Point’ buttons are used. To go even further, the path may be generated for the current endpoints by clicking on the ‘Show Path of Current’ button. The display will trace out the arm positions along the path, as directed by the current motion planner. The final button is the ‘Analysis of Path’ button. This button will call up the graphing window, which operates on the current path endpoints.
L.4 Description of Functions in Robot Window:
The robot window actually acts as a catch all for many functions not devoted to either the neural network, or path endpoint maintenance. Both options visibly present in the control window are the ‘Motion Planner’ menu, and the ‘Options’ toggles. A two link manipulator is shown in the graphics window to the right. This window allows the user to directly position the manipulator, see motions, and look at positions in joint and cartesian coordinates.
The motion planner choices are quite simple, any motion planner chosen is used as the default for all path planning operations. Most of the functions are self explanatory, but others require a description. The ‘From File’ motion planner will use the training trajectories stored in the training set file, described in the neural network window. This allows paths to be generated (which might have taken minutes to find), saved to a training file, and then recalled quickly for examination. If this function is not used, then the motion plan is regenerated for every graph or motion, which may be very slow in some cases.
The ‘NN Path Track’ will cause the robot to try and track a moving goal in the right hand side of the robot work space. This was done to evaluate the operation of the robot as a traditional control system. If any details are desired about the other path planning functions, the reader is referred to the thesis body, subroutine descriptions, and source code.
If the mouse pointer is moved into the robot window, the robot position will be refreshed on the screen. While the left mouse button is held down the robot arm may be moved in the work space. This motion will be cartesian, or joint based, depending upon toggle settings. The joint coordinates and cartesian coordinates are displayed on the upper part of the robot window. The start and end positions are also recorded in this window.
The ‘Options’ toggles on the left hand side are quite simple. If the ‘Joint Control’ toggle is set, then any mouse movement of the robot will be in joint coordinates, otherwise the motions will be cartesian. The ‘Elbow Down’ toggle is used to drive the elbow up/elbow down control when the robot is moved in cartesian coordinates. The ‘Point Training’ toggle was put here for convenience, but this toggle will select between point and set training for the neural network.
When constructing training sets, the ‘Path Reverse’ toggle will mean that paths are generated between start and stop positions, as well as stop and start. This allows generation of more complete training sets. The ‘Optimal’ toggle will cause some routines to use slower algorithms which come up with more optimal solutions. This also causes torque outputs to be scaled on the neural network. The ‘Sim. fin.’ toggle will cause kinematic motion plans to stop both joints simultaneously. This will not often be used.
The settings of the ‘Motion Planner’ menu, and the ‘Options’ toggles are saved with the neural network. This allows easy generation, or recall of training data when the user interface is not used.
Figure M.2: Auxiliary Window for Graphing Functions
L.5 Description of Functions in Graphing Window:
There are obviously two sections to this window. In the upper half, the controls are available. The bottom half displays the graphs. The graph windows on the bottom are quite self explanatory, but their use is not.
On the right hand side, the ‘Graph Area Choice’ menu is provided. This menu will direct the graph to appear in a particular window. This allows simultaneous displays of data, in a customized configuration. The joint joint(s) to be displayed may be selected in the ‘Graph Joints’ menu. The type of data to be plotted in the window may be selected in the ‘Plot Type’ menu. All of the choices in this menu will result in a line plots, except for ‘Mean Error’, which will give histograms. Graphs of both line plots and histograms may be seen in the Graph Window figure.
To actually produce a graph, the ‘Plot’ button is used. This button will generate a trajectory, then plot the required data, for the required joints, in the specified window. For the histogram, the training set is compared against the neural network output, and then may be drawn in any window (for one joint only).
In the event the graph data needs to be exported, the ‘File’ button may be used in place of ‘Plot’. This will direct the desired data to the file name which also appears in the graph control window. A ‘Quit’ button also appears in this window. When the user is done graphing, this button may be used to remove the graph window.
L.6 Windows and Applications Setup Subroutines:
main() - This serves as the main junction for the program. The dynamics routine is set up here. The Sunview graphics are also initialized here. If the graphics have been initialized without problem, control is passed to Sunview. Sunview handles all the calling of functions, as predefined in the setup routines.
screen_init() - acts as a terminal point for calling all setup subroutines, in particular the neural network window, the path endpoint window, the robot control window, the robot drawing window, and the pop-up graph window. A refresh of the screen is also done here before control goes to sunview.
nw_init() - The neural network control window is define here. This is the uppermost window. As can be seen in earlier figures, this window defines a number of neural network related toggles, buttons, and text items.
bw_init() - Path endpoints control is handled by this window. There are actually two windows here. One window controls buttons and text related to path endpoints. The other window is used for displaying part of the list of path endpoints. This list is controlled to do current displays of the path endpoint list in a clear and concise form.
rw_init() - A robot is drawn in the bottom window. Beside this window a list of toggles, and a menu are given. These are both defined in this subroutine. The robot will actually be drawn by another subroutine, which will be defined later.
gw_init() - A window has been set up separately from the main window. This is set up for the purposes of displaying graphs of results. This window has been set up with the idea of allowing a combination of user directed graphs of any attribute. Thus, the window has been defined as a combination of six small canvases, and one large one. By referring to the description above, the reader will achieve an appreciation for the power of this window.
plot_on() - The Graph Window is commonly not visible. When this function is called, the window will become visible, and the user will be able to user the graphing utilities until the ‘plot_off()’ function is called.
plot_off() - This will hide the Graphing Window.
plot_current() - This routine will call an appropriate graphing function after setting up the options. These options include graph of position, velocity, acceleration, torque or error histograms, the graph window to draw in, the joints to use. This calls the line plots separately from the histograms. When the line plot is called, it is generated for a path based on the current path endpoints. When an error histogram is called, the neural network testing subroutine is called, for every point in the training trajectory array, and the error results are used.
file_data() - This function is set up to deposit the graph results in a file name specified. This function will choose the data, and joints of interest, and write these values to a data file. This function will allow any data used for a graph to be exported to another graphing package.
plot_line() - This function will produce a line graph of the specified parameters and joints in the specified window. The graphs are prescaled, and give approximations of the data scale. The joint number will be labelled on the graph, and the graph will be labelled appropriately. The axis are also given numbers to show the magnitude of the line graph. This program is only capable of graphing position, velocity, acceleration and torques.
plot_hist() - A histogram of errors may be plotted with this function. These graphs are also self scaling to fit the histogram. The reader should recognize that the only time an error histogram is of any use is when comparing a neural network output to the ideal. This plots a histogram of all errors, as placed in the training trajectory list be the neural network testing subroutine. All histograms are appropriately labelled.
L.8 Path Endpoint Maintenance Subroutines:
buf_load() - The path endpoint file name is obtained from the screen. it is then used to load the path endpoint files, and the list on the screen is updated.
buf_save() - Path endpoints are saved to the file named on the text item in the buffer window.
buf_down() - Move current pointer down path endpoint list (toward end of array), then refresh screen.
buf_up() - Move current pointer up path endpoint list (toward start of array), then refresh the screen.
buf_delete() - Delete the path endpoints indicated by the current pointer. The screen is then refreshed.
buf_insert() - Call the insert function to open a new spot at the current path endpoint position, insert the current start/end positions, and then refresh the screen.
buf_show() - Part of the path endpoint list is displayed, with the current path endpoints highlighted. This is done directly on the screen, in the buffer window.
L.9 Training Trajectory Array Subroutines:
buf_tload() - Training trajectories are loaded from disk. The file used is as named in the Training set text input, in the neural network window. After loading, the screen is refreshed.
buf_tsave() - The training trajectory file is saved to the file named specified in the neural network training set input.
redo_robot() - The current start and stop positions for the robot are swapped with the current path endpoints, in the path endpoint array. The two affected windows are then redrawn to reflect the change.
L.10 Robot Maintenance Subroutines:
stop_robot() - The current robot position will be stored in temporary variables which are used to directly input the stop position for a robot path. The robot window will be refreshed to reflect the change in this value.
start_robot() - The current robot position will be stored in temporary variables which may be used to update the start position for a robot path in the path endpoint array. The robot window will also be redrawn.
robot_move() - When the mouse moves into the robot window this routine will be called. This will only result in a refresh of the robot position. If the left mouse button is pushed the robot will track the mouse movements in cartesian, or joint space, depending upon which flag is set. The robot is continuously redrawn to display the cartesian and joint coordinates of the robot. The robot position is used to set the user selected start and stop points.
draw_robot() - A rendering of the two link manipulator will be made by this routine. The routine will also provide text which describes the robot joint coordinates, cartesian end effector coordinates, and current start and stop points. This function should allow easy, interactive updates by the user. The robot function can also be called with color. If the color is 0, then the previous drawings will be erased, if the color is 1, then they will be preserved.
draw_path() - Using a trajectory generated from the current path endpoints, the robot path will be drawn. Before this is done, the system time step is read from the text string on the screen. The path is made to appear as a number of arm configurations by drawing the arm at a number of positions, without erasing the previous drawing. This will remain until some event triggers a redraw. A flag which has been set will instruct the subroutine to erase the entire window before drawing.
L.11 Neural Network Maintenance Subroutines:
n_display() - A refresh of the neural network window is made by this routine. All of the test, menus, toggles and report strings are updated, based upon internal configurations.
n_load() - The neural network file name is retrieved from the screen, and is used to load the neural network file, the neural network screen is updated afterwards.
n_save() - The neural network file name is retrieved from the screen, and the neural network is saved with it.
n_add() - A set of path endpoints is taken from the path endpoint array, and used to generate a trajectory, which is then added to the training trajectory array. The neural network screen is then updated.
n_clear() - The neural network training trajectory array is erased, and the screen is refreshed.
n_new() - The neural network is erase, as well as the training trajectory array. The screen is then refreshed.
n_build() - All of the path endpoints in the array are used to construct a training trajectory set, with the current path generation algorithm. The time step of the system is retrieved from the screen before this function is executed. After the training set is updated, the neural network window is refreshed.
n_create() - Neural network width, and number of hidden layers are taken from the screen, and the routine to build a neural network is called. After this the screen is updated.
n_train() - The system time step, number of training iterations, learning rate, and smoothing factors are obtained from the screen. A message is sent to the screen to indicate training is occurring, and the training routine is called. When complete the message is replaced, and the neural network window is refreshed.
n_test() - The time step of the system is obtained, and the neural network testing subroutine is called. This routine will produce a comparison between the ideal data in the training trajectory array, and the neural network output. The results are returned through global variables, and are printed in the text window the application was started from.
L.12 Sunview Interface Subroutines:
texter() - This routine registers a notification that an updated text string has been received by Sunview. Otherwise it serves no purpose.
choice_log() - Sunview notifies this routine when any of the toggles or menus has been selected. The routine will select the input received and perform the appropriate update to any global flags and variables. In one case action is taken also. This action is in the form of redrawing the robot to reflect changes in joint configurations (i.e. elbow up to elbow down).
killer() - This routine terminates Sunview, which in turns returns control of the program to the main executive routine. This in turn ends execution of the program.
* ROBOT TRAJECTORY TRAINING PROGRAM
* This program is intended to provide a user interface for neural network
* controllers for 2 link manipulators. The interface includes trajectory
* file maintenance tools, neural network maintenance tools, Graphing tools
* and general controls. This program uses Sunview, on Sun computers.
* Some general comments about this program are that it is heavily laden
* with sunview functions. It is not the intension to comment these to
* simplicity. Thus, for particular concerns the sunview manuals should be
* This program is intended to only pass data between the user and the
* subroutines. Thus, the routines are quite redundant, but essential for
* This program is expected to be applied towards the M.E.Sc. thesis of
* Mr Hugh Jack, B.E.Sc. at the University of Western Ontario.
#include <suntool/sunview.h> /* Numerous header files */
#include "rt_def.c" /* Basic Defs. for all functions */
#include "rt_dyn.c" /* Dynamics of the manipulator */
#include "rt_net.c" /* Trajectory planning network func. */
#include "rt_fun.c" /* Robot specific functions */
#define PICWIN_X 500 /* Robot window dimensions */
#define BUFWIN_X 300 /* Dimensions of buffer window */
#define PLOWIN_X 250 /* Plotting viewport dimensions */
#define PLOSET_X 60 /* boundary around graphs */
#define HIST_RES 10 /* Resolution of Histogram */
#define BUF_1_COL 40 /* Width of first col. of buffer win.*/
static Frame main_window, /* The main program window */
gw_win; /* The graphing Window */
static Panel nw_win, /* Panel of neural control buttons */
pc_win, /* The panel for plot controls */
rc_win, /* The panel for robot controls */
cw_win; /* Window for buffer controls */
static Canvas bw_win, /* Window for buffer display */
rw_win, /* Window for robot display */
plot_1, /* Displays for smaller plots */
plot_big; /* Big Plotting window */
static Pixwin *rw_canvas, /* canvas for drawing robot */
*current_graph, /* holds the current plot window */
*bw_canvas, /* Canvas to draw the buffer */
*graph_1, /* Canvas’ for displays of plots */
*graph_big; /* Canvas for display of large plot */
static Panel_item men_1, /* Menu for */
nw_mes1, /* Message for network and training set stat */
nw_mes2, /* Message for training status */
text_6, /* Text for network file name */
text_7, /* Text for buffer file name */
text_8, /* Text for raw data file name */
text_9, /* Text for system time step */
text_10; /* Text for name of training set file */
/* An icon for the program (my own special creation) */
0x0000,0x0000,0x0000,0x0000,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FE7,0xFF9F,0xFFFF,0xFFFE,0x7FC3,0xFF0F,0xFFFF,0xFFFE,
0x4081,0x0204,0x0FFF,0xFCFE,0x7F81,0xFE07,0xFFFF,0xF0FE,
0x7FC3,0x7F0F,0xFFFF,0xC27E,0x7FE7,0xBD9F,0xFFFF,0x0E7E,
0x7FFF,0xDBFF,0xFFFE,0x3F3E,0x7FFF,0xE7FF,0xFFFE,0x7F3E,
0x7FFF,0xE7FF,0xFFFE,0x7F9E,0x7FFF,0xDBFF,0xFFFC,0xFF0E,
0x7FE7,0xBD9F,0xFFFC,0xFF6E,0x7FC3,0x7F0F,0xFFFC,0xFF6E,
0x4081,0x0204,0x0FF9,0xFFFE,0x7F81,0xFE07,0xFFF9,0xFFFE,
0x7FC3,0x7F0F,0xFFF9,0xFFFE,0x7FE7,0xBD9F,0xFFF3,0xFFFE,
0x7FFF,0xDBFF,0xFFF3,0xFFFE,0x7FFF,0xE7FF,0xFFF3,0xFFFE,
0x7FFF,0xE7FF,0xFFE7,0xFFFE,0x7FFF,0xDBFF,0xFFE7,0xFFFE,
0x7FE7,0xBD9F,0xFFE7,0xFFFE,0x7FC3,0x7F0F,0xFF00,0x00FE,
0x4081,0x0204,0x0F00,0x00FE,0x7F81,0xFE07,0xFF00,0x00FE,
0x7FC3,0xFF0F,0xFF00,0x00FE,0x7FE7,0xFF9F,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x0000,0x0000,0x0000,0x0000,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xF807,0xC00F,0xFFFE,
0x7FFF,0xFCF3,0xDCEF,0xFFFE,0x7FFF,0xFCF9,0xFCFF,0xFFFE,
0x7FFF,0xFCF9,0xFCFF,0xFFFE,0x7FFF,0xFCF9,0xFCFF,0xFFFE,
0x7FFF,0xFCFB,0xFCFF,0xFFFE,0x7FFF,0xFC07,0xFCFF,0xFFFE,
0x7FFF,0xFC1F,0xFCFF,0xFFFE,0x7FFF,0xFC8F,0xFCFF,0xFFFE,
0x7FFF,0xFCC7,0xFCFF,0xFFFE,0x7FFF,0xFCE3,0xFCFF,0xFFFE,
0x7FFF,0xFCF1,0xFCFF,0xFFFE,0x7FFF,0xFCF8,0xFCFF,0xFFFE,
0x7FFF,0xF87C,0x703F,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x7FFF,0xFFFF,0xFFFF,0xFFFE,
0x7FFF,0xFFFF,0xFFFF,0xFFFE,0x0000,0x0000,0x0000,0x0000
DEFINE_ICON_FROM_IMAGE(frame_icon, rt_icon); /* First function to define */
Panel_setting texter(); /* A text echo routine for text input */
void buf_delete(), /* Functions for Trajectory buffer control */
n_add(), /* Functions for Trajectory buffer control */
plot_current(), /* Functions for plot control */
choice_log(), /* aknowledge and update toggles or menus */
draw_path(), /* Draws a trajectory based upon buffer */
redo_robot(), /* Pulls line from trajectory buffer */
robot_move(), /* Lets mouse move robot on screen */
start_robot(), /* Picks the start point of the robot */
stop_robot(); /* Picks the stop point of robot traj. */
int nw_init(), /* Graphics initialization routines */
buf_show(), /* draw lines of buffer on screen */
killer(), /* stops the graphics and uqits program */
draw_robot(), /* draws the robot in one configuration */
screen_init(); /* Does complete initialization */
static int plot_x = PLOWIN_X, /* Size of plot window */
int argc; /* Window Environment variables */
* This is obviously the main juntion loop for major execution of the user
* interface. This will initialize the screen, and the sunview routnies,
* and then pass control to Sunview. Sunview will call the various routines
* written to support this application.
* Variables: argc = number of input pointers
* argv = dual pointer to input
* Returns: An error code if error has occured.
error = screen_init(argc, argv); /* Initialize all */
window_main_loop(main_window); /* Start window control */
printf("Setup Error: Sunview");
exit(error); /* Return error status to caller*/
int argc; /* Window Environment variables */
* All of the graphics utilities are initialized in this section. This is
* done by making calls to other subroutines which initialize various
* parts of the user interface.
* Variables: argc = number of input pointers
* argv = dual pointer to input
* Returns: An error code if error has occured.
batch_mode = 1; /* Allow training Count Output */
* Set up main window, and all sub windows.
main_window = window_create(NULL, FRAME, FRAME_ARGS, argc, argv,
WIN_Y, 0, FRAME_LABEL, "Robot Trajectory (by Hugh Jack 1990)",
* Set up graphing pop up window.
gw_win = window_create(main_window, FRAME,
FRAME_LABEL, "Trajectory Graphs", 0);
* Draw current status on screen.
draw_robot(theta1, theta2, 1);
* All control buttons for the neural network, and program control, are
* setup and defined in this section.
* Returns: An error code if error has occured.
* Create main window for control of Neural Network and other
nw_win = window_create(main_window, PANEL, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(0), WIN_COLUMNS, 49, 0);
* Create message locations for echo of status.
nw_mes1 = panel_create_item(nw_win, PANEL_MESSAGE,
PANEL_LABEL_STRING, "Neural Net: Set Size = 0 : No Net\000",
PANEL_ITEM_X, ATTR_COL(0), PANEL_ITEM_Y, ATTR_ROW(0), 0);
nw_mes2 = panel_create_item(nw_win, PANEL_MESSAGE, PANEL_LABEL_STRING,
"Not Trained", PANEL_ITEM_X, ATTR_COL(50), PANEL_ITEM_Y,
* Create text inputs for network parameters, and training.
text_6 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(1), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, file, PANEL_LABEL_STRING, "File Name :",
PANEL_NOTIFY_PROC, texter, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Load", 0, 0),
PANEL_NOTIFY_PROC, n_load, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(7),
PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Save", 0, 0),
PANEL_NOTIFY_PROC, n_save, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(14),
PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "New ", 0, 0),
text_1 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(3), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_1, PANEL_LABEL_STRING, "Layer Width :",
PANEL_NOTIFY_PROC, texter, 0);
text_2 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(4), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_2, PANEL_LABEL_STRING, "Total Layers:",
PANEL_NOTIFY_PROC, texter, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(5), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Make Neural Net ", 0, 0),
PANEL_NOTIFY_PROC, n_create, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(6), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Build Training Set", 0, 0),
PANEL_NOTIFY_PROC, n_build, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(7), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Add Current to Set", 0, 0),
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(8), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Clear Training Set", 0, 0),
PANEL_NOTIFY_PROC, n_clear, 0);
text_3 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(9), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_3, PANEL_LABEL_STRING, "Iterations :",
PANEL_NOTIFY_PROC, texter, 0);
text_4 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(10), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_4, PANEL_LABEL_STRING, "Smooth Rate :",
PANEL_NOTIFY_PROC, texter, 0);
text_5 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(11), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_5, PANEL_LABEL_STRING, "Learn Rate :",
PANEL_NOTIFY_PROC, texter, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(12), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Train with set ", 0, 0),
PANEL_NOTIFY_PROC, n_train, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(13), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Test with set ", 0, 0),
PANEL_NOTIFY_PROC, n_test, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(75),
PANEL_LABEL_Y, ATTR_ROW(13), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Quit", 0, 0),
PANEL_NOTIFY_PROC, killer, 0);
* Create text input for system time step
text_9 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(45),
PANEL_LABEL_Y, ATTR_ROW(8), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_7, PANEL_LABEL_STRING, "Time step (s) :",
PANEL_NOTIFY_PROC, texter, 0);
* Create Buttons and text input for training set file
text_10 = panel_create_item(nw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(45),
PANEL_LABEL_Y, ATTR_ROW(10), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, str_6, PANEL_LABEL_STRING, "Training Set File :",
PANEL_NOTIFY_PROC, texter, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(45),
PANEL_LABEL_Y, ATTR_ROW(11), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Load Set", 0, 0),
PANEL_NOTIFY_PROC, buf_tload, 0);
panel_create_item(nw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(55),
PANEL_LABEL_Y, ATTR_ROW(11), PANEL_LABEL_IMAGE,
panel_button_image(nw_win, "Save Set", 0, 0),
PANEL_NOTIFY_PROC, buf_tsave, 0);
* Create toggles and menu choices.
tog_2 = panel_create_item(nw_win, PANEL_TOGGLE,
PANEL_LABEL_X, ATTR_COL(27), PANEL_LABEL_Y, ATTR_ROW(1),
PANEL_LABEL_STRING, "Network Inputs:",
PANEL_LAYOUT, PANEL_VERTICAL, PANEL_DISPLAY_LEVEL,PANEL_CURRENT,
PANEL_CHOICE_STRINGS, "Bias Neuron", "Position", "Velocity",
"Acceleration", "Target", "Difference", "Torque", 0,
PANEL_NOTIFY_PROC, choice_log, 0);
men_2 = panel_create_item(nw_win, PANEL_CHOICE,
PANEL_LABEL_X, ATTR_COL(45), PANEL_LABEL_Y, ATTR_ROW(1),
PANEL_LAYOUT, PANEL_VERTICAL, PANEL_LABEL_STRING,
"Network Output:", PANEL_CHOICE_STRINGS, "Position", "Velocity",
"Acceleration", "Torque", 0, PANEL_NOTIFY_PROC, choice_log, 0);
men_1 = panel_create_item(nw_win, PANEL_CHOICE,
PANEL_LABEL_X, ATTR_COL(63), PANEL_LABEL_Y, ATTR_ROW(1),
PANEL_LAYOUT, PANEL_VERTICAL, PANEL_LABEL_STRING,
"Network Type:", PANEL_CHOICE_STRINGS, "Sigmoid",
0, PANEL_NOTIFY_PROC, choice_log, 0);
* The trajectories are described in terms of endpoints. These are kept
* track of in this window. This window also allows control of the
* information by the use of buttons.
* Returns: An error code if error has occured.
* Define a panel and title for buffer control.
cw_win = window_create(main_window, PANEL, WIN_BELOW, nw_win,
WIN_X, 0, WIN_COLUMNS, 36, 0);
panel_create_item(cw_win, PANEL_MESSAGE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(0), PANEL_LABEL_STRING,
* Define a text item for text input.
text_7 = panel_create_item(cw_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(1), PANEL_VALUE_DISPLAY_LENGTH, 10,
PANEL_VALUE, b_file, PANEL_LABEL_STRING, "Buffer File:",
PANEL_NOTIFY_PROC, texter, 0);
window_set(cw_win, PANEL_CARET_ITEM, text_7, 0);
* Buttons to load/save trajectory buffer.
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Load", 0, 0),
PANEL_NOTIFY_PROC, buf_load, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(16),
PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Save", 0, 0),
PANEL_NOTIFY_PROC, buf_save, 0);
* Define buttons for other forms of buffer related functions.
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(3), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Choose a Start Point", 0, 0),
PANEL_NOTIFY_PROC, start_robot, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(4), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Choose a Stop Point ", 0, 0),
PANEL_NOTIFY_PROC, stop_robot, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(5), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Show Path of Current", 0, 0),
PANEL_NOTIFY_PROC, draw_path, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(6), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Analysis of Path ", 0, 0),
PANEL_NOTIFY_PROC, plot_on, 0);
* Define buttons and messages for buffer control.
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(28),
PANEL_LABEL_Y, ATTR_ROW(2), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Up List ", 0, 0),
PANEL_NOTIFY_PROC, buf_up, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(28),
PANEL_LABEL_Y, ATTR_ROW(3), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Down List ", 0, 0),
PANEL_NOTIFY_PROC, buf_down, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(28),
PANEL_LABEL_Y, ATTR_ROW(4), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Swap Current", 0, 0),
PANEL_NOTIFY_PROC, redo_robot, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(28),
PANEL_LABEL_Y, ATTR_ROW(5), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Insert ", 0, 0),
PANEL_NOTIFY_PROC, buf_insert, 0);
panel_create_item(cw_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(28),
PANEL_LABEL_Y, ATTR_ROW(6), PANEL_LABEL_IMAGE,
panel_button_image(cw_win, "Delete ", 0, 0),
PANEL_NOTIFY_PROC, buf_delete, 0);
* Define a window for display of the buffer
bw_win = window_create(main_window, CANVAS, WIN_BELOW, nw_win,
WIN_RIGHT_OF, cw_win, WIN_WIDTH, BUFWIN_X+1,
bw_canvas = canvas_pixwin(bw_win);
* Draw lines and headers for buffer display box.
pw_vector(bw_canvas, 0, 0, BUFWIN_X, 0, PIX_SRC, 1);
pw_vector(bw_canvas, BUFWIN_X, 0, BUFWIN_X, BUFWIN_Y, PIX_SRC, 1);
pw_vector(bw_canvas, BUFWIN_X, BUFWIN_Y, 0, BUFWIN_Y, PIX_SRC, 1);
pw_vector(bw_canvas, 0, BUFWIN_Y, 0, 0, PIX_SRC, 1);
pw_vector(bw_canvas, 0, 30, BUFWIN_X, 30, PIX_SRC, 1);
pw_vector(bw_canvas, BUF_1_COL, 0, BUF_1_COL, BUFWIN_Y, PIX_SRC, 1);
pw_vector(bw_canvas, (BUFWIN_X+BUF_1_COL)/2, 0,
(BUFWIN_X+BUF_1_COL)/2, BUFWIN_Y, PIX_SRC, 1);
pw_text(bw_canvas, 5, 15, PIX_SRC, NULL, " #");
pw_text(bw_canvas, BUF_1_COL+5, 15, PIX_SRC, NULL, " from (ang 1&2)");
pw_text(bw_canvas, (BUFWIN_X+BUF_1_COL)/2+5, 15,
PIX_SRC, NULL, " to (ang 1&2)");
* The window for the display of the 2 link manipulator is set up here.
* Returns: An error code if error has occured.
rc_win = window_create(main_window, PANEL, WIN_BELOW, cw_win,
WIN_X, 0, WIN_COLUMNS, 19, 0);
panel_create_item(rc_win, PANEL_MESSAGE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(0), PANEL_LABEL_STRING,
tog_3 = panel_create_item(rc_win, PANEL_CHOICE,
PANEL_LABEL_X, ATTR_COL(0), PANEL_LABEL_Y, ATTR_ROW(1),
PANEL_LABEL_STRING, "Motion Planner:", PANEL_LAYOUT, PANEL_VERTICAL,
PANEL_CHOICE_STRINGS, "Max. Vel.", "Max. Acc.", "Coupled Path",
"Opt. Torque", "Simple path", "Network", "From File", "NN Path Track", 0,
PANEL_NOTIFY_PROC, choice_log, 0);
tog_1 = panel_create_item(rc_win, PANEL_TOGGLE,
PANEL_LABEL_X, ATTR_COL(0), PANEL_LABEL_Y, ATTR_ROW(12),
PANEL_LABEL_STRING, "Options:", PANEL_LAYOUT, PANEL_VERTICAL,
PANEL_DISPLAY_LEVEL, PANEL_CURRENT, PANEL_CHOICE_STRINGS,
"Joint Control", "Elbow Down", "Point Training", "Joint Limits",
"Path Reverse", "Optimal", "Sim. fin.", 0,
PANEL_NOTIFY_PROC, choice_log, 0);
* Create main Robot Window and define it as a canvas.
rw_win = window_create(main_window, CANVAS, WIN_BELOW, cw_win,
WIN_BELOW, bw_win, WIN_X, ATTR_COL(19), WIN_WIDTH, PICWIN_X+1,
WIN_HEIGHT, PICWIN_Y+1, WIN_EVENT_PROC, robot_move, 0);
window_set(rw_win, WIN_CONSUME_PICK_EVENT, LOC_DRAG, 0);
rw_canvas = canvas_pixwin(rw_win);
* Draw a box around the window.
pw_vector(rw_canvas, 0, 0, PICWIN_X, 0, PIX_SRC, 1);
pw_vector(rw_canvas, PICWIN_X, 0, PICWIN_X, PICWIN_Y, PIX_SRC, 1);
pw_vector(rw_canvas, PICWIN_X, PICWIN_Y, 0, PICWIN_Y, PIX_SRC, 1);
pw_vector(rw_canvas, 0, PICWIN_Y, 0, 0, PIX_SRC, 1);
* The window for control of the plots, the windows for each plot, and the
* associated buttons and toggles are set up here.
* Returns: An error code if error has occured.
* Initialize the plotting window control panel
pc_win = window_create(gw_win, PANEL,
PANEL_LABEL_Y, ATTR_ROW(0), WIN_COLUMNS, 49, 0);
* Set up Buttons for control window panel
panel_create_item(pc_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(0), PANEL_LABEL_IMAGE,
panel_button_image(pc_win, "Plot", 0, 0),
PANEL_NOTIFY_PROC, plot_current, 0);
panel_create_item(pc_win, PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(1), PANEL_LABEL_IMAGE,
panel_button_image(pc_win, "File", 0, 0),
PANEL_NOTIFY_PROC, file_data, 0);
panel_create_item(pc_win,PANEL_BUTTON, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(8), PANEL_LABEL_IMAGE,
panel_button_image(pc_win, "Done", 0, 0),
PANEL_NOTIFY_PROC, plot_off, 0);
* Set up toggles and menus for plotting window.
men_3 = panel_create_item(pc_win, PANEL_CHOICE,
PANEL_LABEL_X, ATTR_COL(40), PANEL_LABEL_Y, ATTR_ROW(0),
PANEL_LAYOUT, PANEL_VERTICAL, PANEL_LABEL_STRING,
"Graph Area Choice", PANEL_CHOICE_STRINGS, "Top Left",
"Top Right", "Middle Left", "Middle Right", "Bottom Left",
"Bottom Right", "The Big One", 0,
PANEL_NOTIFY_PROC, choice_log, 0);
men_4 = panel_create_item(pc_win, PANEL_CHOICE,
PANEL_LABEL_X, ATTR_COL(10), PANEL_LABEL_Y, ATTR_ROW(0),
PANEL_LAYOUT, PANEL_VERTICAL, PANEL_LABEL_STRING,
"Plot Type", PANEL_CHOICE_STRINGS, "Position", "Velocity",
"Acceleration", "Mean Error", "Torque", 0,
PANEL_NOTIFY_PROC, choice_log, 0);
men_5 = panel_create_item(pc_win, PANEL_CHOICE,
PANEL_LABEL_X, ATTR_COL(25), PANEL_LABEL_Y, ATTR_ROW(0),
PANEL_LAYOUT, PANEL_VERTICAL, PANEL_LABEL_STRING, "Graph Joints",
PANEL_CHOICE_STRINGS, "Joint 1", "Joint 2", "Both", 0,
PANEL_NOTIFY_PROC, choice_log, 0);
text_8 = panel_create_item(pc_win, PANEL_TEXT,
PANEL_NOTIFY_LEVEL, PANEL_NONE, PANEL_LABEL_X, ATTR_COL(0),
PANEL_LABEL_Y, ATTR_ROW(7), PANEL_VALUE_DISPLAY_LENGTH, 15,
PANEL_VALUE, dater_file, PANEL_LABEL_STRING, "Data File Name :",
PANEL_NOTIFY_PROC, texter, 0);
* Set up windows for graphical display.
plot_1 = window_create(gw_win, CANVAS, WIN_BELOW, pc_win, WIN_X, 0,
WIN_WIDTH, PLOWIN_X+1, WIN_HEIGHT, PLOWIN_Y+1, 0);
current_graph = graph_1 = canvas_pixwin(plot_1);
plot_2 = window_create(gw_win, CANVAS, WIN_BELOW, pc_win, WIN_RIGHT_OF,
plot_1, WIN_WIDTH, PLOWIN_X+1, WIN_HEIGHT, PLOWIN_Y+1, 0);
graph_2 = canvas_pixwin(plot_2);
plot_3 = window_create(gw_win, CANVAS, WIN_BELOW, plot_1, WIN_X, 0,
WIN_WIDTH, PLOWIN_X+1, WIN_HEIGHT, PLOWIN_Y+1, 0);
graph_3 = canvas_pixwin(plot_3);
plot_4 = window_create(gw_win, CANVAS, WIN_BELOW, plot_2, WIN_RIGHT_OF,
plot_3, WIN_WIDTH, PLOWIN_X+1, WIN_HEIGHT, PLOWIN_Y+1, 0);
graph_4 = canvas_pixwin(plot_4);
plot_5 = window_create(gw_win, CANVAS, WIN_BELOW, plot_3, WIN_X, 0,
WIN_WIDTH, PLOWIN_X+1, WIN_HEIGHT, PLOWIN_Y+1, 0);
graph_5 = canvas_pixwin(plot_5);
plot_6 = window_create(gw_win, CANVAS, WIN_BELOW, plot_4, WIN_RIGHT_OF,
plot_5, WIN_WIDTH, PLOWIN_X+1, WIN_HEIGHT, PLOWIN_Y+1, 0);
graph_6 = canvas_pixwin(plot_6);
plot_big = window_create(gw_win, CANVAS, WIN_BELOW, plot_4, WIN_BELOW,
plot_5, WIN_X, 0, WIN_WIDTH, 2*PLOWIN_X+1,
graph_big = canvas_pixwin(plot_big);
* The plot window is normally off. This function will turn it on.
window_set(gw_win, WIN_SHOW, TRUE, 0);
* The visibility of the graphing window will be turned off when this routine
window_set(gw_win, WIN_SHOW, FALSE, 0);
* The Appropriate graphing routine will be called, and the appropriate
* setups will be done based upon the current state of the graph options.
strcpy(wrk, (char *)panel_get_value(text_9));
* Determine graph type and graph title
if((joints_plot == JOINT_1) && (data_plot == POSITION)){
sprintf(dummy, "Joint 1 Position");
if((joints_plot == JOINT_1) && (data_plot == VELOCITY)){
sprintf(dummy, "Joint 1 Velocity");
if((joints_plot == JOINT_1) && (data_plot == ACCELERATION)){
sprintf(dummy, "Joint 1 Acceleration");
if((joints_plot == JOINT_1) && (data_plot == TORQUE)){
sprintf(dummy, "Joint 1 Torque");
if((joints_plot == JOINT_1) && (data_plot == MEAN_ERROR)){
sprintf(dummy, "Joint 1 Mean Error");
if((joints_plot == JOINT_2) && (data_plot == POSITION)){
sprintf(dummy, "Joint 2 Position");
if((joints_plot == JOINT_2) && (data_plot == VELOCITY)){
sprintf(dummy, "Joint 2 Velocity");
if((joints_plot == JOINT_2) && (data_plot == ACCELERATION)){
sprintf(dummy, "Joint 2 Acceleration");
if((joints_plot == JOINT_2) && (data_plot == TORQUE)){
sprintf(dummy, "Joint 2 Torque");
if((joints_plot == JOINT_2) && (data_plot == MEAN_ERROR)){
sprintf(dummy, "Joint 2 Mean Error");
if((joints_plot == BOTH) && (data_plot == POSITION)){
sprintf(dummy, "Joint 1 & 2 Position");
if((joints_plot == BOTH) && (data_plot == VELOCITY)){
sprintf(dummy, "Joint 1 & 2 Velocity");
if((joints_plot == BOTH) && (data_plot == ACCELERATION)){
sprintf(dummy, "Joint 1 & 2 Acceleration");
if((joints_plot == BOTH) && (data_plot == TORQUE)){
sprintf(dummy, "Joint 1 & 2 Torque");
if((joints_plot == BOTH) && (data_plot == MEAN_ERROR)){
sprintf(dummy, "Joint 1 & 2 Mean Error");
* Call for normal line graph if desired
if((end_of_buffer > 0) && (data_plot != MEAN_ERROR)){
get_trajectory(t_number, buffer[buffer_point].t1_start,
buffer[buffer_point].t2_start,
buffer[buffer_point].t2_end, t_set, end_train, &n);
plot_line(p_type, dummy, current_graph, t_set, end_train, n);
* Call for normal histogram of errors if desired.
if((net_loaded_flag == 1) &&(end_train > 0) && (data_plot==MEAN_ERROR)){
plot_hist(p_type, dummy, current_graph, t_set, 0, end_train);
* This function is intended to save the current path to disk, so that
* the information may be manipulated by a graphing package. Each
* point is written twice for line graphs. This will allow square
* (non-continuous) functions to be written, The information will just
* be redundant for linear graphs. The errors for a histogram will
static double tt1, tt2, tt1_d, tt2_d, tt1_n, tt2_n;
strcpy(dater_file, (char *)panel_get_value(text_8));
file_ptr = fopen(dater_file, "w");
* Write file for normal line graph if desired
if((end_of_buffer > 0) && (data_plot != MEAN_ERROR)){
get_trajectory(t_number, buffer[buffer_point].t1_start,
buffer[buffer_point].t2_start,
buffer[buffer_point].t2_end, t_set, end_train, &n);
for(i = end_train; i < end_train+n; i++){
tt1_n = t_set[i+1].t1_position;
tt2_n = t_set[i+1].t2_position;
if(tt1_d==0.0) tt1_d = t_set[i].t1_acceleration;
if(tt2_d==0.0) tt2_d = t_set[i].t2_acceleration;
tt1_n = t_set[i+1].t1_velocity;
tt2_n = t_set[i+1].t2_velocity;
tt1_d = t_set[i].t1_acceleration;
tt2_d = t_set[i].t2_acceleration;
if(data_plot == ACCELERATION){
tt1 = t_set[i].t1_acceleration;
tt2 = t_set[i].t2_acceleration;
tt1_n = t_set[i+1].t1_acceleration;
tt2_n = t_set[i+1].t2_acceleration;
fprintf(file_ptr, "%f,%f,%f\n",
(double)(T_STEP*(i - end_train)), tt1, tt2);
if((tt1_d == 0.0) && (tt2_d == 0.0)){
fprintf(file_ptr, "%f,%f,%f\n",
(double)(T_STEP*(i + 1 - end_train)),
} else if((tt1_d == 0.0) && (tt2_d != 0.0)){
fprintf(file_ptr, "%f,%f,%f\n",
(double)(T_STEP*(i + 1 - end_train)),
} else if((tt1_d != 0.0) && (tt2_d == 0.0)){
fprintf(file_ptr, "%f,%f,%f\n",
(double)(T_STEP*(i + 1 - end_train)),
(double)(T_STEP*(i - end_train)), tt1);
(double)(T_STEP*(i+1-end_train)),tt1);
(double)(T_STEP*(i - end_train)), tt2);
(double)(T_STEP*(i+1-end_train)),tt2);
* Write file for normal histogram of errors if desired.
if((end_train > 0) && (data_plot == MEAN_ERROR)){
for(i = 0; i < end_train; i++){
if(joints_plot == BOTH) fprintf(file_ptr, "%f\n%f\n",
t_set[i].t1_error, t_set[i].t2_error);
if(joints_plot == JOINT_1) fprintf(file_ptr, "%f\n",
if(joints_plot == JOINT_2) fprintf(file_ptr, "%f\n",
void plot_line(type, title, plotter, points, start, n)
* The normal graphs for joint position, velocity, and acceleration are
* drawn here. This function will draw the graph to the window named
* Variables: type = what the graph is to represent
* title = the title which is to appear on the graph
* plotter = the pixwin which will hold the graph
* points = the array of path data
* start = the start position in the path data
* n = the number of points to be plotted
static int i, /* a counter variable */
t_axis, /* The zero indicator line */
y1_1, /* Work variables for graph segments */
flag_1, /* indicate which joint is graphed */
static double maxy, /* max and min values for graph */
static char tex_1[50], /* work variables for text strings */
flag_1 = 0; /* Set flags to false */
maxy = -999999999.0; /* Set max and min to extremes */
* Find max and min ranges for graph data
if((type == T_POSITION) || (type == T1_POSITION)){
for(i = start; i < start+n; i++){
if(points[i].t1_position > maxy) maxy = points[i].t1_position;
if(points[i].t1_position < miny) miny = points[i].t1_position;
if((type == T_POSITION) || (type == T2_POSITION)){
for(i = start; i < start+n; i++){
if(points[i].t2_position > maxy) maxy = points[i].t2_position;
if(points[i].t2_position < miny) miny = points[i].t2_position;
if((type == T_VELOCITY) || (type == T1_VELOCITY)){
for(i = start; i < start+n; i++){
if(points[i].t1_velocity > maxy) maxy = points[i].t1_velocity;
if(points[i].t1_velocity < miny) miny = points[i].t1_velocity;
if((type == T_VELOCITY) || (type == T2_VELOCITY)){
for(i = start; i < start+n; i++){
if(points[i].t2_velocity > maxy) maxy = points[i].t2_velocity;
if(points[i].t2_velocity < miny) miny = points[i].t2_velocity;
if((type == T_ACCELERATION) || (type == T1_ACCELERATION)){
for(i = start; i < start+n; i++){
if(points[i].t1_acceleration > maxy)
maxy = points[i].t1_acceleration;
if(points[i].t1_acceleration < miny)
miny = points[i].t1_acceleration;
if((type == T_ACCELERATION) || (type == T2_ACCELERATION)){
for(i = start; i < start+n; i++){
if(points[i].t2_acceleration > maxy)
maxy = points[i].t2_acceleration;
if(points[i].t2_acceleration < miny)
miny = points[i].t2_acceleration;
if((type == T_TORQUE) || (type == T1_TORQUE)){
for(i = start; i < start+n; i++){
if(points[i].t1_torque > maxy)
if(points[i].t1_torque < miny)
if((type == T_TORQUE) || (type == T2_TORQUE)){
for(i = start; i < start+n; i++){
if(points[i].t2_torque > maxy)
if(points[i].t2_torque < miny)
if((type == T_ERROR) || (type == T1_ERROR)){
for(i = start; i < start+n; i++){
if(points[i].t1_error > maxy) maxy = points[i].t1_error;
if(points[i].t1_error < miny) miny = points[i].t1_error;
if((type == T_ERROR) || (type == T2_ERROR)){
for(i = start; i < start+n; i++){
if(points[i].t2_error > maxy) maxy = points[i].t2_error;
if(points[i].t2_error < miny) miny = points[i].t2_error;
maxy += 1.0; /* expand range to loosen space */
scale = (double)(plot_y - 2*PLOSET_Y)/(maxy - miny);
scale_x = (double)(plot_x - 2*PLOSET_X)/(double)(n-1);
pw_writebackground(plotter, 0, 0, plot_x, plot_y, PIX_SRC);
* Draw on zero axis if in range
if((maxy > 0.0) && (miny < 0.0)){
t_axis = plot_y - PLOSET_Y + miny*scale;
pw_vector(plotter, PLOSET_X, t_axis, plot_x-PLOSET_X,
pw_vector(plotter, plot_x-PLOSET_X, t_axis+5,
plot_x-PLOSET_X, t_axis-5, PIX_SRC, 1);
pw_vector(plotter, plot_x/2, t_axis + 5,
plot_x/2, t_axis-5, PIX_SRC, 1);
pw_text(plotter, PLOSET_X-30, t_axis, PIX_SRC, NULL, "0.0");
* Draw the rest of the graph axis
pw_vector(plotter, PLOSET_X, plot_y-PLOSET_Y, plot_x-PLOSET_X,
pw_vector(plotter, plot_x-PLOSET_X, plot_y-PLOSET_Y,
plot_x-PLOSET_X, plot_y-PLOSET_Y-5, PIX_SRC, 1);
pw_vector(plotter, plot_x/2, plot_y-PLOSET_Y,
plot_x/2, plot_y-PLOSET_Y-5, PIX_SRC, 1);
pw_vector(plotter, PLOSET_X, PLOSET_Y, PLOSET_X, plot_y-PLOSET_Y,
pw_vector(plotter,PLOSET_X, PLOSET_Y, PLOSET_X+5, PLOSET_Y, PIX_SRC, 1);
pw_vector(plotter, PLOSET_X, plot_y/2, PLOSET_X+5,
* Put title and values on graphs.
pw_text(plotter, PLOSET_X, 15, PIX_SRC, NULL, title);
sprintf(tex_1, "%7.2f\000", maxy);
sprintf(tex_2, "%7.2f\000", miny);
sprintf(tex_3, "%7.2f\000", (double)(n*T_STEP));
pw_text(plotter, 0, PLOSET_Y, PIX_SRC, NULL, tex_1);
pw_text(plotter, 0, plot_y-PLOSET_Y, PIX_SRC, NULL, tex_2);
pw_text(plotter, PLOSET_X, plot_y-5, PIX_SRC, NULL, tex_4);
pw_text(plotter, plot_x-2*PLOSET_X, plot_y-5, PIX_SRC, NULL, tex_3);
* Draw the graph with line segments
for(i = start; i < start+n-1; i++){
* Find start and stop height of data line segment
if((type == T_POSITION) || (type == T1_POSITION)){
y1_1 = (points[i].t1_position-miny)*scale;
y2_1 = (points[i+1].t1_position-miny)*scale;
if((points[i].t1_velocity == 0.0) &&
(points[i+1].t1_velocity == 0.0)) y2_1 = y1_1;
if((type == T_POSITION) || (type == T2_POSITION)){
y1_2 = (points[i].t2_position-miny)*scale;
y2_2 = (points[i+1].t2_position-miny)*scale;
if((points[i].t2_velocity == 0.0) &&
(points[i+1].t2_velocity == 0.0)) y2_2 = y1_2;
if((type == T_VELOCITY) || (type == T1_VELOCITY)){
y1_1 = (points[i].t1_velocity-miny)*scale;
y2_1 = (points[i+1].t1_velocity-miny)*scale;
if((points[i].t1_acceleration == 0.0) &&
(points[i+1].t1_acceleration == 0.0)) y2_1=y1_1;
if((type == T_VELOCITY) || (type == T2_VELOCITY)){
y1_2 = (points[i].t2_velocity-miny)*scale;
y2_2 = (points[i+1].t2_velocity-miny)*scale;
if((points[i].t2_acceleration == 0.0) &&
(points[i+1].t2_acceleration == 0.0)) y2_2=y1_2;
if((type == T_ACCELERATION) || (type == T1_ACCELERATION)){
y1_1 = (points[i].t1_acceleration-miny)*scale;
y2_1 = (points[i+1].t1_acceleration-miny)*scale;
if((type == T_ACCELERATION) || (type == T2_ACCELERATION)){
y1_2 = (points[i].t2_acceleration-miny)*scale;
y2_2 = (points[i+1].t2_acceleration-miny)*scale;
if((type == T_TORQUE) || (type == T1_TORQUE)){
y1_1 = (points[i].t1_torque-miny)*scale;
y2_1 = (points[i+1].t1_torque-miny)*scale;
if((type == T_TORQUE) || (type == T2_TORQUE)){
y1_2 = (points[i].t2_torque-miny)*scale;
y2_2 = (points[i+1].t2_torque-miny)*scale;
if((type == T_ERROR) || (type == T1_ERROR)){
y1_1 = (points[i].t1_error-miny)*scale;
y2_1 = (points[i+1].t1_error-miny)*scale;
if((type == T_ERROR) || (type == T2_ERROR)){
y1_2 = (points[i].t2_error-miny)*scale;
y2_2 = (points[i+1].t2_error-miny)*scale;
pw_vector(plotter,(int)(scale_x*(i-start)+PLOSET_X),
(int)(scale_x*(i-start+1)+PLOSET_X),
plot_y-PLOSET_Y-y2_1, PIX_SRC, 1);
pw_vector(plotter,(int)(scale_x*(i-start)+PLOSET_X),
(int)(scale_x*(i-start)+PLOSET_X),
plot_y-PLOSET_Y-y_1, PIX_SRC, 1);
pw_vector(plotter,(int)(scale_x*(i-start)+PLOSET_X),
(int)(scale_x*(i-start+1)+PLOSET_X),
plot_y-PLOSET_Y-y2_2, PIX_SRC, 1);
pw_vector(plotter,(int)(scale_x*(i-start)+PLOSET_X),
(int)(scale_x*(i-start)+PLOSET_X),
plot_y-PLOSET_Y-y_2, PIX_SRC, 1);
if(flag_1 == 1) pw_text(plotter, plot_x-PLOSET_X+5,
plot_y-PLOSET_Y-y2_1, PIX_SRC, NULL, "joint 1");
if(flag_2 == 1) pw_text(plotter, plot_x-PLOSET_X+5,
plot_y-PLOSET_Y-y2_2, PIX_SRC, NULL, "joint 2");
void plot_hist(type, title, plotter, points, start, n)
* The histogram of network errors are drawn in this section. This will
* also chanel the graph to the window named "plotter".
* Variables: type = what the histogram is to represent
* title = the title which is to appear on the histogram
* plotter = the pixwin which will hold the histogram
* points = the array of path errors
* start = the start position in the path array
* n = the number of errors to be plotted
static int i; /* a counter work variable */
static double maxy, /* variables for max and min errors */
division; /* range of errors in a histogram cnt*/
static char tex_1[50], /* Work strings for graph labels */
static int count[HIST_RES], /* counts of errors in a range */
height; /* maximum count of errors in a range */
maxy = -999999999.0; /* set max and min at extremes */
for(i = start; i < start+n; i++){
if(points[i].t1_error > maxy) maxy = points[i].t1_error;
if(points[i].t1_error < miny) miny = points[i].t1_error;
for(i = start; i < start+n; i++){
if(points[i].t2_error > maxy) maxy = points[i].t2_error;
if(points[i].t2_error < miny) miny = points[i].t2_error;
* count errors in different ranges of histogram
for(i = 0; i < HIST_RES; i++) count[i] = 0;
division = (maxy-miny)/HIST_RES*1.001;
for(i = start; i < start+n; i++){
count[(int)((points[i].t1_error-miny)/division)]++;
for(i = start; i < start+n; i++){
count[(int)((points[i].t2_error-miny)/division)]++;
* Find maximum number of errors counted in one range
for(i = 0; i < HIST_RES; i++){
if(count[i] > height) height = count[i];
* find scale values for graphing
scale = (double)(plot_y - 2*PLOSET_Y)/(double)(height);
scale_x = (double)(plot_x - 2*PLOSET_X)/(double)(HIST_RES - 1);
pw_writebackground(plotter, 0, 0, plot_x, plot_y, PIX_SRC);
pw_vector(plotter, PLOSET_X, plot_y-PLOSET_Y, plot_x-PLOSET_X,
pw_vector(plotter, plot_x-PLOSET_X, plot_y-PLOSET_Y,
plot_x-PLOSET_X, plot_y-PLOSET_Y-5, PIX_SRC, 1);
pw_vector(plotter, PLOSET_X, plot_y-PLOSET_Y,
PLOSET_X, plot_y-PLOSET_Y-5, PIX_SRC, 1);
pw_vector(plotter, plot_x/2, PLOSET_Y, plot_x/2, plot_y-PLOSET_Y,
pw_vector(plotter, plot_x/2-5, PLOSET_Y, plot_x/2+5,PLOSET_Y,PIX_SRC,1);
pw_vector(plotter, plot_x/2-5, plot_y/2, plot_x/2+5,
* Put titles on graphs, including numbers on axis
pw_text(plotter, PLOSET_X, 15, PIX_SRC, NULL, title);
sprintf(tex_1, "%d\000", height);
sprintf(tex_4, "%7.2f\000", miny);
sprintf(tex_3, "%7.2f\000", maxy);
pw_text(plotter, plot_x/2+9, PLOSET_Y, PIX_SRC, NULL, tex_1);
pw_text(plotter, plot_x/2+9, plot_y-PLOSET_Y, PIX_SRC, NULL, tex_2);
pw_text(plotter, PLOSET_X, plot_y-5, PIX_SRC, NULL, tex_4);
pw_text(plotter, plot_x-2*PLOSET_X, plot_y-5, PIX_SRC, NULL, tex_3);
for(i = 0; i < HIST_RES; i++){
pw_vector(plotter, (int)(scale_x*i+PLOSET_X-8),
(int)(plot_y-PLOSET_Y-scale*count[i]),
(int)(plot_y-PLOSET_Y-scale*count[i]), PIX_SRC, 1);
pw_vector(plotter, (int)(scale_x*i+PLOSET_X-8),
(int)(plot_y-PLOSET_Y-scale*count[i]),
(int)(plot_y-PLOSET_Y), PIX_SRC, 1);
pw_vector(plotter, (int)(scale_x*i+PLOSET_X+8),
(int)(plot_y-PLOSET_Y-scale*count[i]),
(int)(plot_y-PLOSET_Y), PIX_SRC, 1);
* The buffer for the set of test (or training) trajectories is loaded from
strcpy(b_file, (char *)panel_get_value(text_7));
* The trajectory endpoints will be save to a file with this subroutine.
strcpy(b_file, (char *)panel_get_value(text_7));
* The buffer for the set of test (or training) trajectories is loaded from
strcpy(t_file, (char *)panel_get_value(text_10));
b_tload(t_file, 0, &end_train);
* The trajectory endpoints will be save to a file with this subroutine.
strcpy(t_file, (char *)panel_get_value(text_10));
* This moves the pointer to the trajectory buffer, down the list. It will
* cause the visible list to be updated to the new item.
* MOVES POINTER UP TRAJECTORY LIST
* The pointer will be moved to the top of the list. The display will be
* REMOVES TRAJECTORY AT CURRENT POINTER
* The trajectory in the buffer (at the current pointer) will be deleted
* from the list. This is irreversible.
* INSERT DISPLAYED TRAJECTORY AT CURRENT LOCATION
* The points indicated as start and stop on the screen will be entered
* into the trajectory list, at the current pointer position. The other
* trajectories will be bumped down.
* This routine will list trajectories in a structured box, on the screen.
* The current pointer will be indicated also.
* Returns: returns error indication
line; /* line work variable */
static char tex_1[20], /* work strings */
* loop to generate the buffer line display window contents
for(i = buffer_point - 3; i < buffer_point +4; i++){
* Find current line and assign text
line = 110 + 20*(i-buffer_point);
if((i < 0) || (i >= end_of_buffer)){
sprintf(tex_2, " ---, ---\000");
sprintf(tex_3, " ---, ---\000");
sprintf(tex_1, " %3d\000", i);
sprintf(tex_2, "%7.2f,%7.2f\000",
buffer[i].t1_start, buffer[i].t2_start);
sprintf(tex_3, "%7.2f,%7.2f\000",
buffer[i].t1_end, buffer[i].t2_end);
* Fill in text for buffer display window
pw_text(bw_canvas, 2, line, PIX_SRC, NULL, tex_1);
pw_text(bw_canvas, BUF_1_COL+5, line, PIX_SRC, NULL, tex_2);
pw_text(bw_canvas, (BUFWIN_X+BUF_1_COL)/2+5, line,
pw_vector(bw_canvas, 0, 95, BUFWIN_X, 95, PIX_SRC, 1);
pw_vector(bw_canvas, 0, 115, BUFWIN_X, 115, PIX_SRC, 1);
* GET END POINT FOR NEW TRAJECTORY
* When entering endpoints graphically, this routine will be called
* by Sunview, and will log the end point as the current robot config.
if(current.t1_end > 180.0) current.t1_end -= 360.0;
if(current.t1_end < -180.0) current.t1_end += 360.0;
if(current.t2_end > 180.0) current.t2_end -= 360.0;
if(current.t2_end < -180.0) current.t2_end += 360.0;
draw_robot(theta1, theta2, 1);
* Get Strart Point for New Trajectory
* When entering endpoints graphically, this routine will be called
* by Sunview, and will log the start point as the current robot config.
if(current.t1_start > 180.0) current.t1_start -= 360.0;
if(current.t1_start < -180.0) current.t1_start += 360.0;
if(current.t2_start > 180.0) current.t2_start -= 360.0;
if(current.t2_start < -180.0) current.t2_start += 360.0;
draw_robot(theta1, theta2, 1);
* PULL CURRENT BUFFER TRAJECTORY INTO CURRENT BUFFER
* The line which is highlighted on the buffer window will be moved
* into the Start/Stop window, so that it may be manipulated.
v1 = buffer[buffer_point].t1_start;
v2 = buffer[buffer_point].t2_start;
v3 = buffer[buffer_point].t1_end;
v4 = buffer[buffer_point].t2_end;
buffer[buffer_point].t1_start = current.t1_start;
buffer[buffer_point].t2_start = current.t2_start;
buffer[buffer_point].t1_end = current.t1_end;
buffer[buffer_point].t2_end = current.t2_end;
draw_robot(theta1, theta2, 1);
void robot_move(canvas, event)
Canvas canvas; /* Sunview variables */
* ALLOW GRAPHIC UPDATE OF ROBOT POSITION
* The Robot appears visibly on the screen. To allow the user to move
* the robot with the mouse, and update the new position on the screen
* this routine will be called by sunview when the mouse is moved
* inside the robot window. The robot will only be moved when a button
* Update robot if mouse drag is detected
if(event_id(event) == LOC_DRAG){
* Move by end of gripper on screen
kin_forward(theta1, theta2, &x_global, &y_global);
draw_robot(theta1, theta2, 0);
x_global -= 1.0*(x_old - x_new);
y_global += 1.0*(y_old - y_new);
x_global, y_global, elbow_flag);
draw_robot(theta1, theta2, 0);
theta1 += 1.0*(x_old - x_new);
theta2 += 1.0*(y_old - y_new);
if(theta1 > 180.0) theta1 = theta1 - 360.0;
if(theta2 > 180.0) theta2 = theta2 - 360.0;
if(theta1 < -180.0) theta1 = theta1 + 360.0;
if(theta2 < -180.0) theta2 = theta2 + 360.0;
if(theta1 > 360.0) theta1 = theta1 - 360.0;
if(theta2 > 360.0) theta2 = theta2 - 360.0;
if(theta1 < -360.0) theta1 = theta1 + 360.0;
if(theta2 < -360.0) theta2 = theta2 + 360.0;
draw_robot(theta1, theta2, 1);
double t1, t2; /* Angle in degrees */
int COLOR; /* allows robot to be drawn in back ground color. */
* The current robot window will be updated by this routine. This includes
* redrawing the robot, printing the current, and start and stop positions
* along with the current x, y, position of the robot.
x0, /* Position of robot base */
x1, /* Position of elbow joint */
x2, /* Position of end effector */
static char tex_1[50], /* Text work strings */
* Find locations of robot joints
x1 = x0 + (int)(LENGTH_1 * cos(-t1*PI/ 180.0));
y1 = y0 + (int)(LENGTH_1 * sin(-t1*PI/ 180.0));
x2 = x1 + (int)(LENGTH_2 * cos((-t1-t2)*PI/ 180.0));
y2 = y1 + (int)(LENGTH_2 * sin((-t1-t2)*PI/ 180.0));
* Create text strings for robot position
sprintf(tex_1, "theta 1 = %7.2f deg \000", t1);
sprintf(tex_2, "theta 2 = %7.2f deg \000", t2);
sprintf(tex_3, "x = %d \000", (x2 - x0));
sprintf(tex_4, "y = %d \000", (y0 - y2));
sprintf(tex_5, "start (%6.1f,%6.1f) \000",
current.t1_start, current.t2_start);
sprintf(tex_6, "end (%6.1f,%6.1f) \000",
current.t1_end, current.t2_end);
* Clear robot window if not in path trace mode
pw_writebackground(rw_canvas, 1, 1, PICWIN_X, PICWIN_Y,PIX_SRC);
* Put text on screen and draw robot
pw_text(rw_canvas, pos_x, pos_y, PIX_SRC, NULL, tex_1);
pw_text(rw_canvas, pos_x, pos_y + 15, PIX_SRC, NULL, tex_2);
pw_text(rw_canvas, pos_x, pos_y + 30, PIX_SRC, NULL, tex_3);
pw_text(rw_canvas, pos_x, pos_y + 45, PIX_SRC, NULL, tex_4);
pw_text(rw_canvas, pos_x+200, pos_y, PIX_SRC, NULL, tex_5);
pw_text(rw_canvas, pos_x+200, pos_y + 15, PIX_SRC, NULL, tex_6);
pw_vector(rw_canvas, x0, y0, x1, y1, PIX_SRC, COLOR);
pw_vector(rw_canvas, x1, y1, x2, y2, PIX_SRC, COLOR);
pw_vector(rw_canvas, x0-10, y0, x0+10, y0, PIX_SRC, COLOR);
pw_vector(rw_canvas, x0, y0-10, x0, y0+10, PIX_SRC, COLOR);
* The path of the robot will be drawn with this subroutine. The robot will
* not be erased, but left as a record of the path trace.
static int i, /* work counter */
strcpy(wrk, (char *)panel_get_value(text_9));
* Draw path if there is a current trajectory
* Generate a path from a trajectory
get_trajectory(t_number, buffer[buffer_point].t1_start,
buffer[buffer_point].t2_start,
buffer[buffer_point].t2_end, t_set, end_train, &n);
* Erase the robot then draw all the arms on the path
draw_robot(theta1, theta2, 0);
for(i = end_train; i < n+end_train; i++){
draw_robot(t_set[i].t1_position,t_set[i].t2_position,1);
* Set flag to erase screen before next arm draw
* DISPLAY CURRENT N.N. SETTINGS
* The current setting of the Neural Network parameters are displayed by
* this routine. This routine may also recover some data from Sunview
* and fill the appropriate variables with their values.
* If the net is newly loaded, this will update the display
sprintf(str_3, "%d", n_iterations);
panel_set(text_3, PANEL_VALUE, str_3, 0);
sprintf(str_4, "%f", n_smooth);
panel_set(text_4, PANEL_VALUE, str_4, 0);
sprintf(str_5, "%f", n_learn);
panel_set(text_5, PANEL_VALUE, str_5, 0);
sprintf(str_7, "%lf", T_STEP);
panel_set(text_9, PANEL_VALUE, str_7, 0);
panel_set(text_10, PANEL_VALUE, str_6, 0);
panel_set(text_9, PANEL_VALUE, wrk, 0);
panel_set(text_10, PANEL_VALUE, wrk, 0);
* Set net width and layers to original values if net is already made
sprintf(str_1, "%d", n_width);
panel_set(text_1, PANEL_VALUE, str_1, 0);
sprintf(str_2, "%d", n_layers);
panel_set(text_2, PANEL_VALUE, str_2, 0);
* If the input is new, then get the input training parameters
strcpy(str_3, (char *)panel_get_value(text_3));
strcpy(str_4, (char *)panel_get_value(text_4));
strcpy(str_5, (char *)panel_get_value(text_5));
strcpy(wrk, (char *)panel_get_value(text_9));
panel_set(text_9, PANEL_VALUE, wrk, 0);
strcpy(wrk, (char *)panel_get_value(text_10));
panel_set(text_10, PANEL_VALUE, wrk, 0);
* Reformat the training parameters, and output them to the screen
sprintf(str_3, "%d", n_iterations);
panel_set(text_3, PANEL_VALUE, str_3, 0);
sprintf(str_4, "%f", n_smooth);
panel_set(text_4, PANEL_VALUE, str_4, 0);
sprintf(str_5, "%f", n_learn);
panel_set(text_5, PANEL_VALUE, str_5, 0);
* Set the toggles and menus to the current variable info
panel_set_value(men_1, n_type-SIGMOID);
panel_set_value(men_2, n_output-POSITION);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 0, n_bias, 0);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 1, n_position, 0);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 2, n_velocity, 0);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 3, n_acceleration, 0);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 4, n_target, 0);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 5, n_difference, 0);
panel_set(tog_2, PANEL_TOGGLE_VALUE, 6, n_torque, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 1, elbow_flag, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 2, 0, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 3, train_up, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 4, train_alt, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 5, train_opt, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 6, train_sim, 0);
panel_set(tog_1, PANEL_TOGGLE_VALUE, 2, 1, 0);
panel_set_value(tog_3, t_number - CASE_1);
* Put network and training set status on the screen
sprintf(tex, "Neural Net: Set Size = %d : No Net\000",
sprintf(tex, "Neural Net: Set Size = %d : Net Loaded\000",
panel_set(nw_mes1, PANEL_LABEL_STRING, tex, 0);
* The named neural network is loaded with routine. The relevant data is
* also recovered from the ’extra string’ storage capability of the
strcpy(file, (char *)panel_get_value(text_6));
* load file and set variables in sunview
* The neural network may be saved with these routines. The important data
* is also saved with the extra string functions of the neural network
* Get network file name and save file
strcpy(file, (char *)panel_get_value(text_6));
* ADD A PATH TO THE TRAINING SET
* The training set will be appended by the current trajectory path.
* This is the only path which will be added.
strcpy(wrk, (char *)panel_get_value(text_9));
* Add a trajectory to the path training set
nt_add(buffer[buffer_point].t1_start, buffer[buffer_point].t2_start,
buffer[buffer_point].t1_end, buffer[buffer_point].t2_end);
* The current Neural Network Training Set Will be wiped out.
* Call function to wipe out path training set
* The currently configured neural network will be wiped out. This
* will also wipe out the training set. This does not change the options
* Call function to wipe neural net, then reset message
panel_set(nw_mes2, PANEL_LABEL_STRING, "Not Trained", 0);
* The old training set will be wiped out and replaced with a new one.
* This training set will consist of all trajectory paths described by
* contents of the current trajectory buffer.
strcpy(wrk, (char *)panel_get_value(text_9));
* Call function to create path training set from entered parameters
* A new neural network will be built, based upon the current options entered.
strcpy(str_1, (char *)panel_get_value(text_1));
strcpy(str_2, (char *)panel_get_value(text_2));
* Create net with parameters and function
* The current training set is used to train the neural network.
strcpy(wrk, (char *)panel_get_value(text_9));
* Get the training parameters, and update variables
strcpy(str_3, (char *)panel_get_value(text_3));
strcpy(str_4, (char *)panel_get_value(text_4));
strcpy(str_5, (char *)panel_get_value(text_5));
* Display messages and train network, if net loaded and set prepared
if((end_train > 0) && (net_loaded_flag == 1)){
panel_set(nw_mes2, PANEL_LABEL_STRING, "Training", 0);
panel_set(nw_mes2, PANEL_LABEL_STRING, "Done Training", 0);
* The network is tested, using the current network configuration, and the
* current training set. This does not alter the network, but finds the
strcpy(wrk, (char *)panel_get_value(text_9));
* If error status available, print errors to screen
printf("Joint 1 average error = %f \n", n1_error);
printf("Joint 1 deviation = %f \n", n1_deviation);
printf("Joint 2 average error = %f \n", n2_error);
printf("Joint 2 deviation = %f \n", n2_deviation);
printf("Both Joint average error = %f \n", net_average_error);
printf("Both Joint deviation = %f \n", net_deviation);
Panel_setting texter(item, event)
* A TEXT VALUE RETURN ROUTINE FOR SUNVIEW
* Sunview requires a value returned when text is entered. This function
return(panel_text_notify(item, event));
void choice_log(item, value, event)
* Sunview will call this routine to deliver the output option. This option
* will determine what the network will use as output.
* Update the value for network output
if(value == 0) n_output = POSITION;
if(value == 1) n_output = VELOCITY;
if(value == 2) n_output = ACCELERATION;
if(value == 3) n_output = TORQUE;
panel_set_value(men_2, value);
* Update the value for network activation function
if(value == 0) n_type = SIGMOID;
panel_set_value(men_1, value);
* Update the trajectory planning method
if(value == 0) t_number = CASE_1;
if(value == 1) t_number = CASE_2;
if(value == 2) t_number = CASE_3;
if(value == 3) t_number = CASE_4;
if(value == 4) t_number = CASE_5;
if(value == 5) t_number = NETWORK;
if(value == 6) t_number = SET_FILE;
if(value == 7) t_number = NN_TRACK;
panel_set_value(tog_3, value);
* Update the input types to the network
if((item == tog_2) && (net_loaded_flag == 0)){
n_bias = (int)panel_get(tog_2, PANEL_TOGGLE_VALUE, 0);
n_position = (int)panel_get(tog_2,
n_velocity = (int)panel_get(tog_2,
n_acceleration = (int)panel_get(tog_2,
n_target = (int)panel_get(tog_2, PANEL_TOGGLE_VALUE, 4);
n_difference = (int)panel_get(tog_2, PANEL_TOGGLE_VALUE, 5);
n_torque = (int)panel_get(tog_2, PANEL_TOGGLE_VALUE, 6);
* Update the value for special flags
x_y_flag = (int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 0);
elbow_flag = (int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 1);
train_alt = (int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 4);
train_sim = (int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 6);
v1 = (int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 3);
v2 = (int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 5);
if((int)panel_get(tog_1, PANEL_TOGGLE_VALUE, 2) == TRUE)
draw_robot(theta1, theta2, 0);
kin_forward(theta1, theta2, &x, &y);
kin_inverse(&theta1, &theta2, x, y, elbow_flag);
draw_robot(theta1, theta2, 1);
* Update the value for which joint is to be plotted
if(value == 0) joints_plot = JOINT_1;
if(value == 1) joints_plot = JOINT_2;
if(value == 2) joints_plot = BOTH;
panel_set_value(men_5, value);
* Update the value for joint information to be plotted
if(value == 0) data_plot = POSITION;
if(value == 1) data_plot = VELOCITY;
if(value == 2) data_plot = ACCELERATION;
if(value == 3) data_plot = MEAN_ERROR;
if(value == 4) data_plot = TORQUE;
panel_set_value(men_4, value);
* Update the current window which is to be plotted in.
if(value == 0) current_graph = graph_1;
if(value == 1) current_graph = graph_2;
if(value == 2) current_graph = graph_3;
if(value == 3) current_graph = graph_4;
if(value == 4) current_graph = graph_5;
if(value == 5) current_graph = graph_6;
panel_set_value(men_3, value);
* The Sunview windows will be halted when this routine is called, and as a
* result, the program will end.