Project Template#
- page project_template
We highly suggest using or at least studying the rc_project_template available at StrawsonDesign/librobotcontrol.
Copying the Template#
The project template source is also included as part of the librobotcontrol package and in installed to /usr/share/robotcontrol/rc_project_template so it can be easily copied and modified. We suggest copying the project and modifying as follows.
Make a Copy#
Make a copy of the project template, rename the folder to your desired project name, and cd to your new directory.
cp -r /usr/share/robotcontrol/rc_project_template ~/new_project_name cd new_project_name
Modify the Project Name#
Change the name of the C source code file to match your project name. Now edit the makefile so it knows to compile the new C file. It will also produce a compiled executable with this new name.
mv rc_project_template.c new_project_name.c nano Makefile
For now, you should only need to change the TARGET variable of the Makefile to match your project. As your project grows you may need to edit this Makefile further as required for your needs.
# This is a general use makefile for librobotcontrol projects written in C. # Just change the target name to match your main source code filename. TARGET = new_project_name # compiler and linker binaries CC := gcc LINKER := gcc . . .
Using the Makefile#
For those unfamiliar with ‘make’ and Makefiles, ‘make’ is a mature and well-documented build tool for compiling source code. If you are interested, lots of good information about the make tool can be found at https://www.gnu.org/software/make/manual/html_node/Introduction.html.
To save the user the time and effort of learning how to create Makefiles, this template contains a simple and generic Makefile which links to the librobotcontrol library and provides the following common make commands:
make make clean make install make uninstall make runonboot
make (to compile)#
This will use gcc to compile the C file you renamed in section 1 and will produce an executable with the same name, but without the ‘.c’ extention. Part of the process is linking this executable to the librobotcontrol shared object. For convenience it also links to the ‘math’ and ‘pthread’ libraries as these are most common. It can be easily modified to link to other libraries by adding to the ‘LDFLAGS’ list in the Makefile.
make clean#
As part of compiling and building process, a ‘.o’ object file was also created along with the final executable. If you are making a backup of your project source files, or are pushing your progress up to a git repository (as you should!!) then it’s helpful to clean up these compiled binary files. Executing ‘make clean’ in your project source directory will clean up these binary files leaving only the source code.
make install#
Normally you would execute your newly-compiled executable from within the same directory that it exists. For example, compiling and executing the project template would look like this:
debian@beaglebone:~$ cd ../rc_project_template/ debian@beaglebone:~/rc_project_template$ make Made: rc_project_template debian@beaglebone:~/rc_project_template$ ./rc_project_template running...
Once you are satisfied with the functionality of your new program, you will want to install the executable in a place where it can be run from anywhere for easy access in the future. This location is typically ‘/usr/local/bin/’ for executables made locally by users. Instead of making a copy there manually, the ‘make install’ command will do this for you. You will have to use ‘sudo’ as the ‘/usr/’ directory has restricted privileges.
debian@beaglebone:~/rc_project_template$ sudo make install debian@beaglebone:~/rc_project_template$ cd ../ debian@beaglebone:~$ rc_project_template running...
make uninstall#
‘make uninstall’ simply deletes the copy of your current project executable from ‘/usr/local/bin/’. It will not delete your source files.
make runonboot#
This ‘runonboot’ command is unique to the Makefile provided in the project template, whereas ‘clean’ ‘install’ and ‘uninstall’ are pretty much universal amongst other Makefiles. This command sets the program to run automatically on boot if the robotcontrol systemd service is enabled, see the Run on Boot section for more details.
Structure of the Project Template#
Instead of try to explain how the template works line-by-line, we’ve tried to comment the code as informatively as possible. The complete C file is included here for easy access. We encourage the user to read it carefully to understand the structure.
/** * @file rc_project_template.c * * This is meant to be a skeleton program for Robot Control projects. Change * this description and file name before modifying for your own purpose. */ #include <stdio.h> #include <robotcontrol.h> // includes ALL Robot Control subsystems // function declarations void on_pause_press(); void on_pause_release(); /** * This template contains these critical components * - ensure no existing instances are running and make new PID file * - start the signal handler * - initialize subsystems you wish to use * - while loop that checks for EXITING condition * - cleanup subsystems at the end * * @return 0 during normal operation, -1 on error */ int main() { // make sure another instance isn't running // if return value is -3 then a background process is running with // higher privaledges and we couldn't kill it, in which case we should // not continue or there may be hardware conflicts. If it returned -4 // then there was an invalid argument that needs to be fixed. if(rc_kill_existing_process(2.0)<-2) return -1; // start signal handler so we can exit cleanly if(rc_enable_signal_handler()==-1){ fprintf(stderr,"ERROR: failed to start signal handler\n"); return -1; } // initialize pause button if(rc_button_init(RC_BTN_PIN_PAUSE, RC_BTN_POLARITY_NORM_HIGH, RC_BTN_DEBOUNCE_DEFAULT_US)){ fprintf(stderr,"ERROR: failed to initialize pause button\n"); return -1; } // Assign functions to be called when button events occur rc_button_set_callbacks(RC_BTN_PIN_PAUSE,on_pause_press,on_pause_release); // make PID file to indicate your project is running // due to the check made on the call to rc_kill_existing_process() above // we can be fairly confident there is no PID file already and we can // make our own safely. rc_make_pid_file(); printf("\nPress and release pause button to turn green LED on and off\n"); printf("hold pause button down for 2 seconds to exit\n"); // Keep looping until state changes to EXITING rc_set_state(RUNNING); while(rc_get_state()!=EXITING){ // do things based on the state if(rc_get_state()==RUNNING){ rc_led_set(RC_LED_GREEN, 1); rc_led_set(RC_LED_RED, 0); } else{ rc_led_set(RC_LED_GREEN, 0); rc_led_set(RC_LED_RED, 1); } // always sleep at some point rc_usleep(100000); } // turn off LEDs and close file descriptors rc_led_set(RC_LED_GREEN, 0); rc_led_set(RC_LED_RED, 0); rc_led_cleanup(); rc_button_cleanup(); // stop button handlers rc_remove_pid_file(); // remove pid file LAST return 0; } /** * Make the Pause button toggle between paused and running states. */ void on_pause_release() { if(rc_get_state()==RUNNING) rc_set_state(PAUSED); else if(rc_get_state()==PAUSED) rc_set_state(RUNNING); return; } /** * If the user holds the pause button for 2 seconds, set state to EXITING which * triggers the rest of the program to exit cleanly. **/ void on_pause_press() { int i; const int samples = 100; // check for release 100 times in this period const int us_wait = 2000000; // 2 seconds // now keep checking to see if the button is still held down for(i=0;i<samples;i++){ rc_usleep(us_wait/samples); if(rc_button_get_state(RC_BTN_PIN_PAUSE)==RC_BTN_STATE_RELEASED) return; } printf("long press detected, shutting down\n"); rc_set_state(EXITING); return; }