C4 Model with PlantUML
C4 is a modeling and documentation language developed to express architecture in a powerful way. The C4 model consists of Context, Container, Component and Code level diagrams. In the C4 Model, each level represents a different level of abstraction and it is possible to zoom from the highest abstraction to more detailed one. Thus, you can communicate with stakeholders at different technical levels through different diagrams.
UML diagrams are widely used in architectural representation. While UML diagrams are strong in showing developer level details, they are weak in high level representations. For this reason, almost all of us prefer to draw these diagrams as boxes with color and image in Power Point. In this respect, I found the diagrams of the C4 Model really useful. As a software architect, I think that the C4 model can be used together with UML.
I used Plant UML for drawing C4 Model diagrams. Plant UML is a script-based tool for drawing UML and similar diagrams. The script structure is simple and easy to learn. You may find it difficult compared to the drag-and-drop approach, but when you see that you can add these drawings to the Confuence page with the help of the PlantUML plugin, you will think it’s worth it. Companies developing agile software prefer to keep their software architectures in Confluence environment instead of Word document. All project stakeholders can easily access the architectural diagrams shared via Confluence. When project stakeholders want changes to these drawings, they can update these scripts to reflect the changes.
In this article, I explained the basic features of the diagrams within the scope of C4 by modeling Autoware Auto, the autonomous vehicle library, and the Robot Operating System (ROS2) it uses. The reason I chose this was to see the usability of the C4 model for embedded systems. On the website of the C4 Model, there is a very careful modeling example for a banking application.
Context Diagram
Context diagrams show the interaction of the software with other systems and software in the environment in which it is used. In this diagram our software is located in the middle and its interaction with other systems is shown. This diagram is used for communication between all technical and non-technical project stakeholders. Below is the relationship of Autoware Auto software with the integrator and ROS2.
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Context.puml
' uncomment the following line and comment the first to use locally
' !include C4_Context.puml
title System Context diagram for AutoWare Auto and ROS2
Person(Integrator, "Integrator", "Autonomous Vehicle Developer")System(Autoware_Auto,"Autoware Auto", " Autoware is the world’s first all-in-one open-source software for self-driving vehicles hosted under the Autoware Foundation. The Autoware.Auto project, based on ROS 2, is the next generation successor of the Autoware.AI project, based on ROS 1.")System(Ros2 , "ROS2", "Robot Operating System (ROS) is a set of open source algorithms, hardware driver software and tools developed to develop robot control software. ROS includes mature open source libraries to be used for navigation, control, motion planning, vision and simulation purposes.")
System_Ext(DDS, "DDS", "Data Distribution Service (DDS) is a data centric publish/subscribe middleware used for data transmission in distributed real time systems. ")Rel(Integrator, Autoware_Auto, "Utilizes")
Rel_Neighbor(Autoware_Auto, Ros2 , "Based on")Rel(Ros2 , DDS, "communication middleware")
@enduml
Container Diagram
The Container Diagram shows our top-level services, database, 3. party software and the relationships between them. These diagrams are very good at showing high-end software architecture. These containers represent units that can operate on their own and can be transported to different locations. This inter-container data communication can be DDS, REST, AMQP, gRPC etc. These level diagrams can be used for communication in the software development team (developers, test engineers, and Devops). The following illustration shows the different software components that will be included in Autoware Auto and the relationship between them. (https://www.autoware.org/post/autoware-auto-v1-0-0-release)
Below is the PlantUML script of the diagram shown above:
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml
' uncomment the following line and comment the first to use locally
' !include C4_Container.puml' LAYOUT_TOP_DOWN()
' LAYOUT_AS_SKETCH()
LAYOUT_WITH_LEGEND()title Container diagram for Autoware Auto
Container(Sensing, "Sensing", "Autoware mainly recognizes road environments with the help of LIDAR scanners and cameras.") Container(Localization, "Localization", "The localization contains nodes and libraries which provide an estimate regarding the location of the vehicle using various methods and algorithms")
Container(Perception, "Perception", "filters and segmentation. The filters are nodes and libraries which are part of the filtering pipeline for sensor data. Nodes work as standalone filtering modules or cascaded with other filtering algorithms working on the same sensor data types. Enable sensor data to be grouped into clusters or objects of interest which can provide downstream procsses more information about the environment.")
Container(Planning, "Planning", "Produce a trajectory towards a provided goal. Involved in the planning process in order to alleviate the complexity of the path-planning optimization problem.")Container(Control, "Control", "Nodes and libraries related to the controller functionalities of the vehicle. They enable the autonomous vehicle to follow a reference trajectory appropriately by converting the input trajectory into longitudinal and lateral commands.")
Container(VehicleInterface, "Vehicle Interface", "Sensor/Actuator Drivers")
System_Ext(Vehicle, "Vehicle", "The Autonomous Vehicle")
System_Ext(Sensors, "Sensors", "Lidar, Camera, GPS etc.")Rel(Sensors, Sensing, "Socket, Serial etc.")
Rel(Sensing, Perception, "Sensing Data")
Rel_Neighbor(Perception, Planning, "Surrounding Environment")
Rel_Neighbor(Planning, Control, "Trajectory")Rel(Control, VehicleInterface, "Vehicle Commands")
Rel(VehicleInterface,Control, "Steering, Velocity Feedback")BiRel(VehicleInterface, Vehicle, "Can, Socket, Serial")Rel(Sensing, Localization, "Current Position and Velocity")
Rel(Localization,Perception, "Current Position and velocity")
Rel(Localization,Planning, "Current Position and velocity")
Rel(Localization, Control, "Current Position and velocity")
Rel(VehicleInterface, Localization, "VehicleSensor")@enduml
Component Diagram
Component diagrams go down to the service level and show the software components of the relevant service and the relationships between them. This diagram is used for software architecture and communication between developers. In the C4 model, the components are not stand-alone units.
Below is the PlantUML script of the diagram shown above:
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml
' uncomment the following line and comment the first to use locally
' !include C4_Component.pumlLAYOUT_WITH_LEGEND()title Component Diagram for ROS2 based Autoware Auto ApplicationComponent_Ext(DDS, "DDS Middleware library", "DDS Library from DDS vendor")
Container(usercode, "User Code", "C++", "User code for Vehicle Interface, Perception, Planning etc.")Container_Boundary(app, "ROS2 Components") {
Component(rmw, "RMW", "C++", "ROS middleware Interface")
Component(rcl, "rcl", "C++", "ROS Client Library")
Component(rclCPP, "rclCPP", "C++", "ROS Client Library C++ Wrapper.")
Rel(rmw, DDS, "Uses","Api")
Rel(usercode, rclCPP, "Uses","Api")
Rel(rclCPP, rcl, "Uses","Api")
Rel(rcl, rmw, "Uses","Api")
}@enduml
Code
The C4 model did not define a diagram for the code level and suggested drawing these level diagrams with UML. In this context, class, sequence and state diagrams can be used as code level diagrams.
Below is the PlantUML script of the diagram shown above:
@startuml
participant User_Code
participant RCLCpp
participant RCL
participant RMW
participant DDS
autonumber
User_Code->RCLCpp: Publisher::Publish
RCLCpp->RCL: rcl_publish
RCL->RMW: rmw_publish
RMW->DDS: data_writer.write
@enduml
C4 diagrams in this article:
Another C4 diagrams in this article:
https://github.com/hkutluca/yazilimmimarileri/tree/master/C4Examples