Web technologies in the physical world: Hyperloop regenerative braking

Jimmy Lam
7 min readMar 24, 2021

--

In September of 2020, I entered my fourth and final year as an engineering undergrad at the University of Toronto. I was mostly looking forward to finally graduating but in the meantime, I was also excited to be a part of a multidisciplinary Capstone team. The Capstone project is something that every engineering student must go through before graduating where they get to work with a client from industry to develop an engineering project. Our client was the University of Toronto Hyperloop Team (UTHT) who tasked us with developing a proof of concept of a regenerative braking system on their flagship Pod1. For those of you who are unfamiliar with the term, regenerative braking means recovering spent energy during braking, increasing the range of a vehicle. The project requires many different components that require different engineering expertise and there were many different ways that we could approach the project. As the team’s web development expert, I was excited to see that UTHT is using web technologies such as Angular and Node.js to monitor and control the pod. This article is a documentation of the design process that I went through to create a braking controller for the Hyperloop pod.

A rendering of Pod1
A rendering of Pod1

The requirements

First, let’s talk about the tech stack. Our client’s dashboard is made in Angular 10 and all communication with the pod was to be done through a Node websocket server. Both of which were being built at the time so we were working with the client’s infrastructure team to integrate our design into what was being built. This became our first requirement — to utilize existing technology in our solution. Secondly, one of the primary functions which our client wanted to have was to be able to vary the brake force of the pod. It would have been a lot easier if the brake force was fixed because we can just add a start button and call it done. With this requirement, we have to be thinking about how to best represent brake force intent on the UI. Along with this comes the challenge of how and when the signal should be sent to the pod — this is important because the signal must come in at the right time or the pod can run off the track and be damaged.

Communication

I have done many projects in the past involving WebSocket through the Socket.io library. It’s simple and easy to use so what’s not to like. However, for this project, this just means that I have to learn how to apply all the lower level stuff that has been abstracted away by Socket.io. Luckily it was not as complex as I thought it was going to be. Below is the figure that shows all the connections that we need to work with. Notice how the signal from each client only goes one way

How the clients and server interact with each other

First, let’s define what we have to do: we need to know where information was sent from so that we are able to send the information to the correct client — for example, we don’t want the signal from the UI to be broadcasted back to the UI and vice versa with the pod. In the land of Socket.io, we would have access to a unique id for every connection object which would allow us to create a global JS map object with the id as the key and the client type as the value. Every time there is a new message, we can just look up that id in the table and when we broadcast that message we can look at the table again to identify the correct client type to be sent to.

Socket.io documentation

The socket library we used did not provide the id functionality out of the box so what if we try to implement that ourselves. My original idea was to create a new UUID every time there is a new connection and assign that to the connection object while also storing that id in a global map with the client type associated with the id. That would work and was actually quite easy to implement but aren’t we complicating things here? Well, actually yes, instead of using extra space and global storage we could just assign the client type directly to the connection object instead so that we don’t have to look it up using the id which eliminates the extra storage and also marginally increases the server latency.

The informational flow of the original idea
The improved flow

Another functionality that comes with Socket.io is the named messages — the emit functionality — which is quite useful because the client or the server can catch the specific event and handle it correctly. Again, we had to implement this ourselves and we only have the “message” event to work with. Here we need to figure out what type of message we are getting and the best way to do this is to assign an eventType property to every JSON message. The server would handle all the different eventTypes by using a switch statement — for example, the “connection” event is when we assign the clientType to the connection object and therefore the JSON data also needs to include the clientType with it. Ideally, we would not use a switch statement here because the only event that the server would really care about is the connection event, all other messages should just be simply be passed to the opposite client types. However, since it was difficult to anticipate the needs of the client in the future, we left the switch statement functionality in the final design.

The server code that handles different event types
The informational flow during the connection event

User Interface

Coming from the React world, Angular was quite an interesting experience. Nonetheless, the user experience comes first and how it is implemented in the front-end framework is not the focus here. In the beginning, I thought that the control should be used like a pedal on a car — a car only starts braking when you start pressing on the brake pedal and the more you press the more brake force is applied. And this was implemented in the first few iterations of the design. The idea was to use sliders as a replacement for the brake pedal such that the user has a visual understanding of how much of the maximum brake force is being applied. This mode was nicknamed real-time mode.

Real-time mode component

This design, however, requires the operator to actually pay attention to where they should be braking and be knowledgeable about the stopping distance dependencies with the brake force. This then creates a new problem which is to design a built-in mechanism that initiates the braking automatically after a certain point on the track. Ideally, in the long term, UTHT should have this system implemented but, like most of the engineering projects out there, time constraint was one thing that we have to manage (which let’s just say was difficult because of my seven courses load). This real-time control functionality was then left alone as an exercise for the client.

In the final design, we decided that we cannot just focus on the braking portion of the pod but also the ramp-up to speed. This drives the decision to add additional inputs such as desired acceleration and brake speed and that would all be handled by the pod’s computer instead of relying on the operator to know when to brake making for a safer experience. This mode was aptly named animation control because it was used to control the animation component (a separate deliverable) of this project.

The final UI design

The final design detail about the UI is the user interaction with the control buttons. When a button is clicked — the state should change accordingly to the state of the pod. This means the state change in the UI must come from the pod. To increase the responsive feel, the UI is implemented to update the states immediately with the assumed state but will also update the state once the pod state has been sent back to the UI. This ensures the states are synced up while increasing the responsive feel of the application.

User-initiated event flow
State update flow
Demonstrated real-time control with a Unity simulation of the pod

Conclusion

This capstone project was the highlight of my final year as an engineering undergrad at the University of Toronto. Even though everything would have been so much better if there wasn’t a pandemic and everything must be done remotely (it would have been cool to work on the actual physical pod). I was able to work on my skills as an engineering designer while improving my technical skill as a developer. Furthermore, having to work in a team of multidisciplinary engineering students really helps me to improve my communication and leadership skills. Seeing how web technologies get used in the physical world such as this application also makes me very excited about my future as a web developer because of its seemingly limitless potential.

--

--

Jimmy Lam
Jimmy Lam

Written by Jimmy Lam

Hi! I am a self-taught developer who love to play around with different web technologies

No responses yet