Difference between revisions of "Self-driving Car"
(→Schedule) |
|||
(19 intermediate revisions by 3 users not shown) | |||
Line 8: | Line 8: | ||
== Gitlab == | == Gitlab == | ||
− | Create a "master" Gitlab project that contains sub-folders of each project. Please provide me the access (username: preet) to your master project so I can peek at all of your source code when needed. The Gitlab will track your commit history so I would also know how much work each person or team is contributing. | + | Create a "master" Gitlab project that contains sub-folders of each project OR a Gitlab project that contains different "master" branches for each controller. Please provide me the access (Gitlab username: preet) to your master project so I can peek at all of your source code when needed. The Gitlab will track your commit history so I would also know how much work each person or team is contributing. |
The folder structure should be: | The folder structure should be: | ||
− | * | + | * TeamX_CmpE_Fall2015 |
*: Sensor | *: Sensor | ||
*: IO | *: IO | ||
*: <other controller projects> | *: <other controller projects> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Parts == | == Parts == | ||
Line 95: | Line 36: | ||
*: Tilt (angle of the car) | *: Tilt (angle of the car) | ||
|- | |- | ||
− | | '''Motor Controller''' | + | | '''Motor and I/O Controller''' |
'''(2 members)''' | '''(2 members)''' | ||
| | | | ||
Line 101: | Line 42: | ||
*: Provide a means to steer, and drive the car | *: Provide a means to steer, and drive the car | ||
* Provide feedback of the speed using a wheel encoder or speed sensor | * Provide feedback of the speed using a wheel encoder or speed sensor | ||
− | |||
− | |||
− | |||
− | |||
* Provide an LCD screen to report car status | * Provide an LCD screen to report car status | ||
*: Errors and communication status | *: Errors and communication status | ||
Line 111: | Line 48: | ||
* Button hard-coded to set a specific destination | * Button hard-coded to set a specific destination | ||
* Provide means to turn on/off the headlights (etc). | * Provide means to turn on/off the headlights (etc). | ||
+ | |- | ||
|- | |- | ||
| '''Communication Bridge + Android''' | | '''Communication Bridge + Android''' | ||
− | '''( | + | '''(2 members)''' |
| | | | ||
* Provide means to communicate and display status on an Android/iPhone device | * Provide means to communicate and display status on an Android/iPhone device | ||
Line 120: | Line 58: | ||
|- | |- | ||
| '''Geographical Controller''' | | '''Geographical Controller''' | ||
− | '''( | + | '''(2 members)''' |
| | | | ||
* Interface to a 5Hz or faster GPS | * Interface to a 5Hz or faster GPS | ||
Line 130: | Line 68: | ||
|- | |- | ||
| '''Central Controller''' | | '''Central Controller''' | ||
− | '''( | + | '''(2 members)''' |
| | | | ||
* This is the primary unit that communicates with every controller to drive the car | * This is the primary unit that communicates with every controller to drive the car | ||
Line 141: | Line 79: | ||
== Communication == | == Communication == | ||
− | Each controller shall provide a means to communicate with the other controllers. Before you read any further, it requires that you have deep knowledge of the CAN bus. CAN is a BROADCAST communication bus, | + | Each controller shall provide a means to communicate with the other controllers. Before you read any further, it requires that you have deep knowledge of the CAN bus. CAN is a BROADCAST communication bus, and the controller or message with the highest priority shall pick a lower CAN message ID. |
=== Recommended CAN Message ID format === | === Recommended CAN Message ID format === | ||
− | We split the | + | We can split the 11-bit CAN message ID into 2 portions, one that dictates the priority of the message (message type), and the other that dictates the priority of the controller. For example, the airbag sensor ECU should use lowest controller ID and lowest message type. |
− | + | The split of message ID can also help filter out unwanted messages from arriving into your microcontroller as the CAN peripheral of the microcontroller will filter out the unwanted data. For example, you can choose to accept all messages from the sensor controller, while making sure you receive no messages from the motor controller. In particular, your CAN hardware filter needs a single EXTENDED GROUP filter. | |
− | |||
− | |||
{| class="wikitable" | {| class="wikitable" | ||
− | |+ CAN Communication Protocol ( | + | |+ CAN Communication Protocol (11-bit CAN ID) |
|- | |- | ||
| Reserved bit | | Reserved bit | ||
− | |||
| Source Controller | | Source Controller | ||
− | | Message | + | | Message type |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
− | | | + | | <code>1-bit : B10</code> |
− | + | | <code>6-bit : B9:B4</code> | |
− | + | | <code>4-bit : B3:B0</code> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |- | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
− | + | === [[DBC Format]] === | |
− | + | DBC format is a well known format to describe the format of a CAN message. This is essentially the schema of the data that is communicated over the CAN bus. Please view the linked [[DBC Format]] article for details before reading further. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== How will communication work? == | == How will communication work? == | ||
− | After startup, begin to send your data messages at the desired periodic rates using the periodic | + | After startup, begin to send your data messages at the desired periodic rates using the periodic scheduler as listed below in the example. Whichever controller wants to listen to your periodic message shall intercept your message and use it for its needs. You can have global variables for the CAN data messages, and tasks should update the data within these messages. |
== Features == | == Features == | ||
Line 268: | Line 111: | ||
* Each controller shall display its version information at startup, for example: | * Each controller shall display its version information at startup, for example: | ||
− | *: " | + | *: printf("Vesion: %s %s\n", __DATE__, __TIME__); |
− | |||
− | |||
− | |||
* Each controller shall use the 2-digit LED display to display meaningful info | * Each controller shall use the 2-digit LED display to display meaningful info | ||
*: Maybe Geo Controller can display # of feet to destination | *: Maybe Geo Controller can display # of feet to destination | ||
*: Central controller can display number of CAN messages received per second. | *: Central controller can display number of CAN messages received per second. | ||
* Each controller shall use the 4-LED lights for some indication | * Each controller shall use the 4-LED lights for some indication | ||
− | *: LED0 should be lit if an error happens (common to everyone) | + | *: LED0 should be lit if an error happens '''(common to everyone)''' |
− | *: Each LED should be labeled about what it means(maybe with a label | + | *: Each LED should be labeled about what it means (maybe with a label maker?) |
=== Robustness === | === Robustness === | ||
Line 283: | Line 123: | ||
Likewise, if you send a message, and it fails (in case the other controller is down), your CAN bus may go to abnormal state and turn off. In this condition, all of your messages will fail, and you will have to handle this. I recommend the following: | Likewise, if you send a message, and it fails (in case the other controller is down), your CAN bus may go to abnormal state and turn off. In this condition, all of your messages will fail, and you will have to handle this. I recommend the following: | ||
− | * | + | * In 1Hz periodic callback, check if the Bus if OFF, and simply reset it |
− | * | + | * Do not reset it in the CAN ISR callback from bus-off since a bad controller can continuously cause errors without the delay of 1Hz |
=== Startup Tests === | === Startup Tests === | ||
Line 297: | Line 137: | ||
* Where is the kill switch? | * Where is the kill switch? | ||
* Can you remotely shut down the car in 3 seconds? | * Can you remotely shut down the car in 3 seconds? | ||
− | |||
* If your controller goes down, will it fully recover to "last known configuration"? | * If your controller goes down, will it fully recover to "last known configuration"? | ||
* If critical sensor data stops coming, how will you stop the car? | * If critical sensor data stops coming, how will you stop the car? | ||
Line 311: | Line 150: | ||
<BR/> | <BR/> | ||
=== Part 1: Basic structure and CAN initialization === | === Part 1: Basic structure and CAN initialization === | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
− | /************** | + | /************** periodic_callbacks.cpp ************/ |
− | |||
#include "can.h" | #include "can.h" | ||
− | + | bool period_init(void) | |
{ | { | ||
/* Initialize CAN Bus and set the acceptance filter(s) */ | /* Initialize CAN Bus and set the acceptance filter(s) */ | ||
CAN_init(can1, 100, 10, 10, NULL, NULL); | CAN_init(can1, 100, 10, 10, NULL, NULL); | ||
+ | |||
/* TODO Initialize acceptance filters */ | /* TODO Initialize acceptance filters */ | ||
CAN_reset_bus(can1); | CAN_reset_bus(can1); | ||
− | + | ||
− | + | return true; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | return | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<BR/> | <BR/> | ||
− | === Part 2: | + | === Part 2: Periodic Parsing Task === |
− | Only one FreeRTOS | + | Only one FreeRTOS periodic function should be responsible to receive CAN messages (while any task can send a CAN message). This receiving task should "route" the incoming messages to the appropriate "consumers" in your code. |
+ | |||
+ | See the [[DBC Format]] article for more sample code related to handling the received messages over the CAN bus. | ||
<syntaxhighlight lang="C"> | <syntaxhighlight lang="C"> | ||
− | + | void period_100Hz(void) | |
− | void | ||
{ | { | ||
can_msg_t msg; | can_msg_t msg; | ||
− | + | // Process all messages that arrived in the last 10ms | |
− | + | while (CAN_rx(can1, &msg, 0)) | |
− | /* TODO | + | { |
− | + | /* TODO: Call auto generated code from DBC parser to parse the message */ | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
} | } | ||
− | |||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− |
Latest revision as of 14:40, 15 July 2016
This project is about a large team getting a car to self-drive to a selected destination. This involves working with an RTOS running on a low power processor and various different processor boards working together over a CAN bus.
Gitlab
Create a "master" Gitlab project that contains sub-folders of each project OR a Gitlab project that contains different "master" branches for each controller. Please provide me the access (Gitlab username: preet) to your master project so I can peek at all of your source code when needed. The Gitlab will track your commit history so I would also know how much work each person or team is contributing.
The folder structure should be:
- TeamX_CmpE_Fall2015
- Sensor
- IO
- <other controller projects>
Parts
Controllers
Given below are the controllers, their duties, and the number of people involved. It is possible that one team gets done with their part, but that doesn't mean your job is done. If you are done, help others. If you are done, and the primary objective is met (the car can self-drive), then add more features. There are many things you can do, and the 16-week semester definitely won't provide an opportunity to sit and relax. Get up and learn!.
Sensor Controller
(2 members) |
|
Motor and I/O Controller
(2 members) |
|
Communication Bridge + Android
(2 members) |
|
Geographical Controller
(2 members) |
|
Central Controller
(2 members) |
|
Communication
Each controller shall provide a means to communicate with the other controllers. Before you read any further, it requires that you have deep knowledge of the CAN bus. CAN is a BROADCAST communication bus, and the controller or message with the highest priority shall pick a lower CAN message ID.
Recommended CAN Message ID format
We can split the 11-bit CAN message ID into 2 portions, one that dictates the priority of the message (message type), and the other that dictates the priority of the controller. For example, the airbag sensor ECU should use lowest controller ID and lowest message type.
The split of message ID can also help filter out unwanted messages from arriving into your microcontroller as the CAN peripheral of the microcontroller will filter out the unwanted data. For example, you can choose to accept all messages from the sensor controller, while making sure you receive no messages from the motor controller. In particular, your CAN hardware filter needs a single EXTENDED GROUP filter.
Reserved bit | Source Controller | Message type |
1-bit : B10
|
6-bit : B9:B4
|
4-bit : B3:B0
|
DBC Format
DBC format is a well known format to describe the format of a CAN message. This is essentially the schema of the data that is communicated over the CAN bus. Please view the linked DBC Format article for details before reading further.
How will communication work?
After startup, begin to send your data messages at the desired periodic rates using the periodic scheduler as listed below in the example. Whichever controller wants to listen to your periodic message shall intercept your message and use it for its needs. You can have global variables for the CAN data messages, and tasks should update the data within these messages.
Features
The first feature to develop is the self-drive capability and everything else comes later. While some people in the team may be focusing on delivering this primary feature, other members can focus on other things such as automatic headlights, variable speed settings through Android interface etc. If your product team fails, then just like it would happen in the industry, you will get laid off, and I will see you again in the course ;(
Quick and Easy Features
These features are mandatory, just to help you debug faster.
- Each controller shall display its version information at startup, for example:
- printf("Vesion: %s %s\n", __DATE__, __TIME__);
- Each controller shall use the 2-digit LED display to display meaningful info
- Maybe Geo Controller can display # of feet to destination
- Central controller can display number of CAN messages received per second.
- Each controller shall use the 4-LED lights for some indication
- LED0 should be lit if an error happens (common to everyone)
- Each LED should be labeled about what it means (maybe with a label maker?)
Robustness
Your project is one project as a whole. So if it doesn't work, do not blame it on "hey, their controller crashed". If a controller crashes it will restart, and you will have live with missing data messages. So your code should be robust, and self-recover from any crashed event or any brief power disruptions.
Likewise, if you send a message, and it fails (in case the other controller is down), your CAN bus may go to abnormal state and turn off. In this condition, all of your messages will fail, and you will have to handle this. I recommend the following:
- In 1Hz periodic callback, check if the Bus if OFF, and simply reset it
- Do not reset it in the CAN ISR callback from bus-off since a bad controller can continuously cause errors without the delay of 1Hz
Startup Tests
Since we rely on multiple controllers, it is critical to be able to test each controller quickly, reliably, and easily. So here is a startup test the Central Controller must process upon each boot:
- Central controller sends a message requesting boot information from each controller
- Central controller checks responses after about 100 ms:
- Each controller must have responded
- Each controller's boot code (normal, abnormal) should be validated.
Considerations
You should consider and design your software for all of these events:
- Where is the kill switch?
- Can you remotely shut down the car in 3 seconds?
- If your controller goes down, will it fully recover to "last known configuration"?
- If critical sensor data stops coming, how will you stop the car?
- How can you quickly discover one or more controllers reaching an error state?
- Log the data on the SD card as much as possible.
- If something wrong happens, you need to know what happened.
- Each controller must log its "startup" time, to debug when a controller crashes and restarts
Grade
Your grade is relative. The best team earns the best grade. Remember than three out of three features working 100% is far better than nine out of ten features working. Focus on less features, with highest quality.
Sample Code
Part 1: Basic structure and CAN initialization
/************** periodic_callbacks.cpp ************/
#include "can.h"
bool period_init(void)
{
/* Initialize CAN Bus and set the acceptance filter(s) */
CAN_init(can1, 100, 10, 10, NULL, NULL);
/* TODO Initialize acceptance filters */
CAN_reset_bus(can1);
return true;
}
Part 2: Periodic Parsing Task
Only one FreeRTOS periodic function should be responsible to receive CAN messages (while any task can send a CAN message). This receiving task should "route" the incoming messages to the appropriate "consumers" in your code.
See the DBC Format article for more sample code related to handling the received messages over the CAN bus.
void period_100Hz(void)
{
can_msg_t msg;
// Process all messages that arrived in the last 10ms
while (CAN_rx(can1, &msg, 0))
{
/* TODO: Call auto generated code from DBC parser to parse the message */
}
}