Back in June, Pieter suggested that we add a form of 'user hook' in to the arducopter code to simplify the use of user written additions or enhancements to the main branch off the arducopter code.
The problem we had was that every time Jason released new version of the code any changes you may have made for your own pet project would have to get laboriously ported across to the latest version of the code, or you stuck with an old version of the code and missed out on all of the latest and greatest bug fixes, tuning and additions.
We now have a first cut at a 'user hooks' solution included in the main branch of the arducopter code. In each main loop, in the variable declarations, and in the init_ardupilot() function there is now a USERHOOK section.
You can now define in your "APM_config.h" file
- which user hooks you wish to use
- what user functions you wish to run from these hooks
- where your user variables are declared.
There are two files "UserCode.pde" and "UserVariables.h" in the arducopter code where you can write your own functions and declare your own variables. Now when a new version of the main code is released all you have to do to port your code over to the new version is copy over your "UserCode.pde" and "UserVariables.h" files and update the latest "APM_config.h" file to point to your user code.
Here is the relevant section from APM_Config.h"
// agmatthews USERHOOKS
// the choice of function names is up to the user and does not have to match these
// uncomment these hooks and ensure there is a matching function in your "UserCode.pde" file
//#define USERHOOK_FASTLOOP userhook_FastLoop();
#define USERHOOK_50HZLOOP userhook_50Hz();
//#define USERHOOK_MEDIUMLOOP userhook_MediumLoop();
//#define USERHOOK_SLOWLOOP userhook_SlowLoop();
//#define USERHOOK_SUPERSLOWLOOP userhook_SuperSlowLoop();
#define USERHOOK_INIT userhook_init();
// the choice of includeed variables file (*.h) is up to the user and does not have to match this one
// Ensure the defined file exists and is in the arducopter directory
#define USERHOOK_VARIABLES "UserVariables.h"
And in "UserCode.pde" you may have something that looks like this (this example is code for my i2c sonar)
// agmatthews USERHOOKS
void userhook_init()
{
// put your initialisation code here
#if SONAR_TYPE == I2C_SONAR_XL
sonar.init();
Serial.print("SONAR_TYPE:");
Serial.println(SONAR_TYPE);
#endif
}
void userhook_50Hz()
{
// put your 50Hz code here
}
And in "UserVariables.h" you could have something like this (again, my example i2c sonar code)
// agmatthews USERHOOKS
// user defined variables#if SONAR_TYPE == I2C_SONAR_XL
APM_I2CSonar_Class sonar;
#endif
I imagine there are other places where user hooks may be useful, for example somewhere in leds.pde or in the logging code etc.
If you think this is useful or want to see other areas with user hooks let us know
-Andrew
Replies
I am very new to the ArduCopter code (or any project of this size) so I apologize but I am having trouble accessing the variables I declare in UserVariables.h. I declare the variables in UserVariables.h, run some code on them in UserCode.cpp (where they are recognized) and then want to send them down to the ground station using GCS_Common.cpp. The prototype functions have all been uncommented so they are included in the project and like I mentioned I can access these variables in UserCode.cpp but I don't think I am linking the UserVariables.h to GCS_Common.cpp correctly. Can anybody explain how to include the UserVariables.h in the GCS_Common.cpp file so that I can access the variables and send them down to the Ground Station?
Thank You!
Hi Lance,
I am new to the code too and i don't have a clear answer. What i found so far is that you can simply write in your usercode gcs_send_text_P("message"); to send text messages (note that this messages will be stored in program memory, and should.
I also tried to send variable values using gcs_send_text_fmt(PSTR("%o"), variablename()); but the format was not well understood and i only recieved "????????????????????f" on the ground station.
You can see how these function work looking into the GCS_mavlink.pde, if you find how it works, please tell me.
Good luck
Miguel
Andrew,
I have just used the Userhooks and it is awesome! This is really very very helpful.
I have a question - What about the equivalent "blank" framework for sending additional sensor data down the telemetry channel using Mavlink to Mission Planner so that the stream can be viewed and used in Python scripting.
Three questions:
= Does something like this exist? If so where can I find documentation on it?
= Are there existing Mavlink data streams that I can use to get the data back. Using the RC information (which I understand to be the commands from the receiver on the quad) or using the battery voltage come to mind. Clearly, I do not want to use any stream that may have control consequences.
= If this would be useful I could give a shot at developing parts of it - but you would have to team me up with a coach who could guide me an who could review.
Thanks for the help.
Gerrie
A simple way of adding code is great. Perfect for quickly implementing functions and just testing stuff in general.
My only worry is that since hooks makes things easy, users might not know/understand the underlying design. This might lead to code that bogs down the entire system resulting in unpredictable behavior. And since we do not have enough resources with the AVR8 to run a RTOS, I see no realistic way of preventing this in the current design.
I've moved my previous dribble to http://diydrones.com/forum/topics/esc-arming-problem?id=705844%3ATo...
It looks like user hooks is the place to implement custom sensors; I plan on expanding on the battery sensor code to using another pin so that I can monitor two batteries at once, not sure again if I'm barking up the right tree, but the flat variable scope seems like it should make the whole thing a doddle. I'll check back in if I can manage to make it work.
There is another small bug in the userhooks. The mediumloop hook actually runs at 50hz instead of 10hz. The 10hz loop is made by running a switch command with 5 cases at 50hz. So each case is run at 10hz. However the mediumloop userhook is inserted right after the cases, making it run at the full 50hz. It should be inserted into one of the case to make it run at 10hz.
Found this out when integrating my custom "showleds" code into the userhooks. Mediumloop blinking would be way too fast :-)
Also I couldn't disarm my copter anymore ??? Still checking why that is, but arm_motors() is also in the 10hz cases, so it could all be related.
Very cool. I think this is a great idea.
I had thought once that doing something like this for tricks would be useful and have the user code only called when you're int a USER flight mode. So as you're playing around with your new code you can always gets back to standard stabilise.
Very nice !
Still have to find some time to port my ledshow code to the userhooks. Been busy with it already and noticed that the userhook_init() function was never called, but that's fixed now and it's called in system.pde.
Will also make it easier to publish small additions like my ledshow, since I hust have to publish my userhook.pde and userhook.h files and some settings in apm_config.h
Many thanks !