As some of you might know, we are working full ahead on developing a local positioning system for the Crazyflie 2.0 ecosystem. There are many things to be done and we just took two major step by improving the stabilizer code architecture and moving the position control code into the firmware. Getting the position from an external system is fine and dandy, but we also have to control the pitch, roll and yaw of the Crazyflie to keep its desired position. Up til now we have been running this control algorithm outside the Crazyflie in an external computer, but now we have moved it into the Crazyflie itself. The controller is a simple PID controller and can definitely be improved, but the main purpose of the work has been to improve the architecture in this area. We know there are people in the community working on position related features and we hope the new architecture will make it easier for us all to implement the bits and pieces needed to get an autonomous Crazyflie. The estimation of the position has not been implemented in the firmware yet but the architecture now has support for it.
The general layout of the new architecture is as follow:
- The sensors are gyroscope, accelerometer and pressure sensor. More could and will be added in the future like position and altitude measurement.
- The state estimator calculate an as good as possible estimate of the Crazyflie state using the sensor values. The state contains the Crazyflie orientation (roll, pitch, yaw), its position and speed. Currently the state estimator has complementary filters for the orientation and the altitude. In the near future the full position will be estimated as well.
- The commander generate a setpoint to be followed by the Crazyflie. Currently this is only done by receiving commander packet from the ground using Crazyradio or bluetooth low energy.
- The state controller generates control output to achieve the requested setpoint from the current state.
- Finally the power distribution is translating controls from the controller into driving the actual motors.
This is implemented in stabilizer.c and each block is implemented in there own file. Stabilizer.c used to be very verbose and complex to read and modify, it has now been greatly simplified and the above architecture is implemented in one short loop (see the full code in GitHub):
while(1) { vTaskDelayUntil(&lastWakeTime, F2T(RATE_MAIN_LOOP)); // 1KHz sensorsAcquire(&sensorData, tick); stateEstimator(&state, &sensorData, tick); commanderGetSetpoint(&setpoint, &state); stateController(&control, &sensorData, &state, &setpoint, tick); powerDistribution(&control); tick++; }
Our philosophy with this new architecture is to keep the code as simple as possible and to allow customisation at compile time. The high-level functions have as simple as possible interface and so can be exchanged easily. So if tomorrow, we have a shiny new controller we just have to compile it instead of the current PID controller. We think that this fits the way the Crazyflie is used, as a development tool.
This is just the beginning: there is still some more to clean-up in the functions and we will most certainly enhance the code from feedback. Please tell us if this is useful and how it can be enhanced even more.
Very cool! For anyone who is interested in the set of changes, you can view it on github using:
https://github.com/bitcraze/crazyflie-firmware/compare/6477a3132cbe6a08d0d0eab96e11a0b2089ec6a4…master
so cool. if not analyze the PID control alogrithm?
Could you give an example on how to change its controller? I am looking forward to changing it and also using kinect to send its position and don’t know how to do it.
Hi,
You can inject X/Y/Z in the Crazyflie using these parameters: https://github.com/bitcraze/crazyflie-firmware/blob/master/src/modules/src/sensors_stock.c#L86-L91.
Then activating the position-hold parameter in the commander will activate the controller to keep the X/Y position.
It is mostly a test mode but it should work. This is part of the code that will soon be cleaned up a bit further (ideally we want to be able to send a dedicated position sensor packet).
/Arnaud
Thanks Arnaud!
Sorry if this is not the right place to ask, but how can I inject the x, y and z values inside those parameters? I am running the controller offboard and sending just commands to the CF, but I want to make it run onboard.
Ok! Think I got it! Thanks, man. I appreciate your help.
Hi,
Can you describe/document the setpoint structure? I’m looking to use the crazyflie to perform autonomous flights by using the commanderSetSetpoint (is it the right way?), but I’m kind of clueless about the different mode (for x,y,z,roll,pitch,yaw) and the way it is used to read the structure values (attitude, thrust, velocity, velocity_body, …)
Hi,
You can look at the lib examples, for instance the autonomous sequence example that sends X,Y,Z position setoints: https://github.com/bitcraze/crazyflie-lib-python/blob/master/examples/autonomousSequence.py#L129-L137
If you have special needs in term of setpoints there is now an easy way to add new setpoint packet to the Crazyflie: https://github.com/bitcraze/crazyflie-firmware/blob/master/src/modules/src/crtp_commander_generic.c#L37