distributed indoor cycling › ~cs230 › projectpresentationswin2010 › final... ·...

8
Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction: We built a distributed training system in which multiple cyclists can train together from the comfort of their homes. Our idea is inspired by the recent popularity of connecting indoor exercise bicycles to google maps, earth, and street-view. These basic systems allow cyclists to sit on their stationary bike and pedal their way through a map or virtual environment displayed on a laptop screen. Our goal was to connect multiple such systems and have them communicate so that users can observe the location of other riders and compete head-to-head. This was implemented in a distributed manner with message-passing, in which we carefully attempt to synchronize the start and end of the race. System: The central part of our system is a python server running on each machine. This program controls the flow of data between the local bicycle, the browser, and the opponents connected over the network. The main thread serves regular requests from the browser, while separate threads (separate classes) are used to monitor input from the Arduino and the connection to an opponent. The server can be in one of three states: ‘setup,’ ‘ready,’ and ‘racing.’ When the server program is started, a browser is opened, connections are made to the Arduino and an opponent, and the server enters the ‘setup’ state. In the browser, users see a

Upload: others

Post on 06-Jul-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

Distributed Indoor CyclingDavid Fooshee Peter Sadowski

March 21, 2011 Introduction:We built a distributed training system in which multiple cyclists can train together from the comfort of their homes. Our idea is inspired by the recent popularity of connecting indoorexercise bicycles to google maps, earth, and street-view. These basic systems allow cyclists to sit on their stationary bike and pedal their way through a map or virtual environment displayed on a laptop screen. Our goal was to connect multiple such systems and have them communicate so that users can observe the location of other riders and compete head-to-head. This was implemented in a distributed manner with message-passing, in which we carefully attempt to synchronize the start and end of the race.

System:The central part of our system is a python server running on each machine. This program controls the flow of data between the local bicycle, the browser, and the opponents connected over the network. The main thread serves regular requests from the browser, while separate threads (separate classes) are used to monitor input from the Arduino and the connection to an opponent. The server can be in one of three states: ‘setup,’ ‘ready,’ and ‘racing.’

When the server program is started, a browser is opened, connections are made to the Arduino and an opponent, and the server enters the ‘setup’ state. In the browser, users see a

Page 2: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

map and are asked to select a start and end address for the race. Submission of a route triggers the server to decide with the opponent on a race route (the route is determined by whatever server is determined to be the ‘leader’), and the server enters the ready state.

As the server enters the ready state it sends the selected race route to the browser,

which then downloads the map data from the Google Maps API and calculates a geometrical representation of the route. This representation allows us to make quick updates to the map visualization from a simple 1-dimensional distance along the route. This ready state also gives the users a minute to see the route and prepare themselves for the race to begin. The race starts when the leader server sends a ‘START’ signal to the opponent, analogous to the firing a starting pistol. The opponent has a fixed time to acknowledge that it has received this signal; otherwise a false start is declared, and we return to the ready state.

Page 3: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

Upon entering the ‘race’ state, all participants have distance zero from the starting line.

Each server polls the local Arduino at regular intervals and sends short UDP update messages to the opponent. Each server then updates the browser with the 1-dimensional distance of both the opponent and the local rider. The browser detects when the local rider has crossed the finish line, and this activates a race_end routine in which we ensure that the local rider has indeed won the race (by calling a global snapshot). Victory requires an acknowledgement that the opponent has not crossed the finish line. If the snapshot cannot determine a definite winner, then we call the race a tie.

Page 4: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

Training inside on a rainy day. Web programming details:We used html and javascript code for our display in the browser. This code uses the Google Maps API to calculate routes between addresses and display map data (note that this basic functionality does not require a Google Maps API key). We make requests to the python server using the XMLHttpRequest function every 300 milliseconds. Increasing the rate of these update requests made our visualization smoother, but sometimes the requests would get ‘congested,’ causing awkward delays. Possible solutions to this would be a smart way of controlling the request rate or optimizing the way in which the server processes and replies to these requests,

Page 5: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

but the quick solution was to accept these slower updates. Communications details:Each Python server has its own instance of a Connection class to handle communication of UDP messages to and from the opponent. Each instance of the Connection module contains two smaller classes: a UDP socket server and client. Upon initialization of a Connection, a small GUI window is displayed requesting the IP address of the opponent we wish to connect to. Once the user has input an IP, we continue initializing the connection by spawning a new thread in which the UDP server listens continuously for incoming packets on a certain hard-coded port. A UDP client socket is also initialized, which will be used to send messages to the opponent’s UDP server.

After initializing the Connection, we are ready to send and receive messages between the users’ machines. Each message is a tuple of the form (integer, string). These tuples are python objects encoded to a byte string form using Python’s ‘pickle’ module prior to sending, and are similarly decoded upon receipt. For the majority of messages, the tuple contains (<number of wheel rotations>, <system state string>), where a typical message soon after the start of the race might be (8, “UPDATE”). This indicates that the racer’s wheel has rotated eight times, and that the message is a standard progress update. The system state strings are used to keep track of the Connection’s state, and some types of state may not be sent in messages, e.g. the “WIN” state. Special (non-”UPDATE”) message statuses include the following:

● “INIT” - Indicates the Connection has been configured and is in a pre-race state. ● “ID” - Used in leader election. Each user randomly chooses an integer ID and sends it to

the opponent for comparison. The system with greatest ID is leader.● “READY” - Indicates that the rider’s system is at a metaphorical start line, ready to begin

the race.● “GOAL” - Indicates that the rider has arrived at the finish line and is claiming that she

has won the race. This must be acknowledged by the opponent with either a “GRATS” or “TIE” message.

● “GRATS” - If the Connection receives a “GOAL” message from the opponent, we must check to see if our current state is also “GOAL”. If not, then the opponent has won, and we confirm her win by sending a “GRATS” message (as in “congrats”).

● “TIE” - If the Connection receives a “GOAL” message from the opponent, and we have already set our own state to “GOAL”, then the race is called a tie, and we respond with this message.

In addition to sending progress update messages during the race, the connection

handles a few other boundary cases, as hinted at in the list above. For example, if the Python server on a user’s machine believes it has won the race, it will ask the Connection to claim that it has reached the goal. A “GOAL” message is sent to the opponent, who will then respond with “GRATS”, indicating a win, if his own state is not “GOAL”. Alternatively, he will respond with “TIE” if his state is also “GOAL”.

At the beginning of the race, the Connection performs leader selection, wherein we generate a random integer ID between 1 and 1x10^8, and send this to the opponent. IDs are

Page 6: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

compared and the greater is chosen as leader. In the event of an ID collision, we halt program execution after suggesting that the riders open some champagne to celebrate their lucky day.

The Connection also keeps track of last known opponent state and progress. The Python server can poll the Connection for this information as needed to update the local browser view of our opponent’s progress. Firmware details:We used a reed switch and magnet from a standard bicycle computer ($10), and connected this to an Arduino Uno programmable microcontroller ($30). The magnet is attached to the spokes of a bicycle, and when it passes by the reed switch, closes a circuit. The Arduino is programmed to count the number of times the circuit closes, allowing us to count wheel rotations.

Our circuit is a very simple loop from the Arduino’s digital pulse width modulation output to ground. We programmed this in the open-source Arduino environment.

Our reed switch and magnet (left), connected to breadboard and Arduino. The Arduino uses standard USB to communicate with the computer.

Page 7: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

Here you can see the reed switch mounted to the bicycle frame with zip ties, while the magnet is mounted to the wheel spoke. As the wheel turns, the reed switch passes close to the switch and

closes the circuit.

Conclusion and future work:We constructed a distributed indoor cycling system that allows users to race other users remotely via the internet using a stationary bicycle, a programmable microcontroller (Arduino), and our own server and communications software -- along with the Google Maps interface -- running on a laptop or desktop. The system was a success, and proved to be an interesting mixture of Python, Javascript, and Arduino programming, along with some electrical wiring and bicycle knowledge. Though we are proud of the system and had a blast racing each other with it, we do have several ideas for future improvements.

Our first goal for future work is to streamline some of the rough edges around our user interface. For example, we would like to display the race result -- win, loss, or tie -- in a larger and clearer way, and within the browser window itself as opposed to in the race log. We might also change the IP address selection pop-up to be a field within the browser, as opposed to a separate Tk window.

The next goal is to implement turning. Currently the race route is one-dimensional. We would like riders to be able to choose a direction at each intersection, instead. Ideally, this would be accomplished by having the Arduino receive input from a handlebar switch, or some other sensor that would indicate the desired direction of a turn without requiring the rider to modify his position. This system would also allow “free-riding” or touring of available roads on the map. We envision being able to freely explore new areas with street view or 3D view. Additionally, with this improvement in place, a user’s choice of which roads to take over the course of a longer race could be an important factor in deciding race outcome, as opposed to the current method in which race outcome is solely a function of wheel rotations.

Page 8: Distributed Indoor Cycling › ~cs230 › projectpresentationswin2010 › final... · 2011-03-22 · Distributed Indoor Cycling David Fooshee Peter Sadowski March 21, 2011 Introduction:

Demo video:http://www.youtube.com/watch?v=ueCgHuNcm-0