Acknowledgments I would like to thank Mr Arno Barnard for his guidance throughout the entirety of this project, and for never minding my ramblings when I go to his office to think out loud on a weekly basis. I would also like to extend gratitude to MTN and Trinity Telecommunications for their technical training and financial support. The completion of this project also required much patience from Tamsyn Lunt, which I thank her for, but also for always being caring and supportive no matter my mood swings or selfish behaviour. Her sharp wit has also lightened the mood on many a critical occasion. Lastly, I would like to thank my parents, Leon and Sariana Dykman, for providing me with a world of opportunities and always encouraging me to make the most of it. I am endlessly grateful. i Declaration of own work I, the undersigned, hereby declare that the work contained in this report is my own original work unless indicated otherwise. Signature Date ii Abstract This project aims to provide a solution that aids decision makers in effective fund allocation when infrastructure upgrades are targeted, specifically when said infrastructure is to be improved for persons with disabilities. It is done by developing a mobile, battery powered route logging device, based on the Arduino Uno microcontroller, which transmits route data to a web application via a GSM modem. The data is then processed so that it may be visually categorised based on the traffic each section of the route generates. Lastly, the visually categorised data is displayed on a map. A fully functional prototype system is developed with success that suggests it could be a viable solution in the commercial arena. iii Opsomming Hierdie projek poog om ʼn oplossing te bied wat besluitnemers in staat sal stel om fondse so effektief as moontlik te allokeer wanneer dit kom by die opgradering van infrastruktuur vir persone met gestremdhede. Dit word gedoen deur die ontwikkeling van ʼn draagbare, battery gedrewe roete toestel, gebaseer op die Arduino Uno mikrobeheerder, wat gebruikers se roetes kan opneem en dan na ‘n web platform stuur deur middel van ʼn GSM modem. Hierdie roete data word dan verwerk sodat dit visueel geklassifiseer kan word voordat dit op ʼn kaart vertoon word. Die sukses waarmee ʼn ten volle funksionele prototipe stelsel ontwikkel is dui daarop dat dit moontlik ʼn oplossing in die kommersiële arena kan bied. iv Contents 1. 2. Introduction 1.1. Problem Description and Project Background 1 1.2. Suggested Solution 1 1.3. Project Layout 2 1.4. Requirements 2 Literature study 2.1. Satellite Navigation Systems 3 3 2.1.1. Galileo 3 2.1.2. GLONASS 4 2.1.3. GPS 4 2.1.4. NMEA 0183 Interface Standard 5 2.2. Wireless Communication 6 2.2.1. GSM Communication 7 2.2.2. Trintel SMART Platform 7 2.3. JavaScript 8 2.4. Meteor Web Application Platform 9 2.5. Database Solutions 9 2.5.1. 2.6. MongoDB 10 Mapping Solutions 11 2.6.1. Google Maps 11 2.6.2. OpenStreetMap 12 2.6.3. Practical Testing 13 Software Algorithms 13 2.7. 2.7.1. The Least Squares Method 13 2.7.2. The Haversine Formula 14 2.7.3. The Orientation Method for Line Intersections 15 2.8. Arduino Libraries 15 2.8.1. Arduino TinyGPS Library 15 2.8.2. Arduino SD Library 16 2.9. Serial Communication 2.9.1. 3. 1 ASCII High-Level Design 16 16 17 3.1. System Overview 17 3.2. Administrative Structure 17 v 3.3. 4. 5. 6. Technical Specifications 17 3.3.1. Logging Device 17 3.3.2. Web Application 18 Hardware Design and Component Selection 19 4.1. Required Components 19 4.2. Component Selection 19 4.2.1. Microcontroller 19 4.2.2. GPS Receiver 23 4.2.3. Storage 24 4.2.4. Power Supply 24 4.3. AirLink GL6100 Power Consumption 25 4.4. RS232 and TTL Serial Communication 26 Software Design 27 5.1. Microcontroller Programming 27 5.2. Communicating with the Trintel SMART Platform 29 5.3. Web Application Overview 30 5.3.1. Login Page 31 5.3.2. Map Display Page 31 5.3.3. Data Management Page 31 5.4. Sectioning routes 31 5.5. Boundary Boxes 34 5.6. Intersections 35 5.7. Heat Mapping the Data 38 Implementation, Testing and Results 6.1. Power Usage and Battery Life 39 39 6.1.1. Power Consumption 39 6.1.2. Battery Life 40 6.1.3. Power Saving 40 6.2. Average Section Positions 41 6.3. Boundary Boxes and Intersections 41 6.4. Practical Data Flow 42 6.5. Arduino Shield PCB Design 43 6.6. Panic button 44 7. Conclusion 45 8. References 46 Appendix A: Project Planning Schedule 46 vi Appendix B: Project Specification 54 Appendix C: Outcomes Compliance 57 Appendix D: FreeMove User Manual 58 Appendix E: Cost of Components 62 Appendix F: Motivation for Adafruit GPS Shield 63 Appendix G: Calculating the Distance between Coordinates 64 Appendix H: Power Consumption versus Processor Speed 67 Appendix H: Schematic for PCB Design 68 Appendix I: Arduino Uno Code 71 Appendix J: FreeMove Web Application Folder Structure 74 Appendix K: FreeMove Web Application Code 75 vii List of Figures Figure 1: Possible positions detected using 2 satellites (left) and 3 satellites (right) [26] 3 Figure 2: Horizontal position error histogram [8] 5 Figure 3: MTN network coverage [10] 6 Figure 4: A simple view of the variable history of an asset on the Trintel SMART platform 7 Figure 5: A simple Venn diagram representation of web applications with JavaScript [12] 8 Figure 6: Google searches for NoSQL database management systems [25] 11 Figure 7: NoSQL skills listed on LinkedIn [25] 11 Figure 8: Total number of connector downloads according to the Jaspersoft Big Data Index, for document storage data stores [25] 11 Figure 9: Intersecting line that satisfy Condition 1 [42] 15 Figure 10: Example of RS232 data transmission with no parity bit [47] 16 Figure 11: A simple system overview diagram 17 Figure 12: A simple visualisation of product use flow 17 Figure 13: An example Arduino sketch in the proprietary IDE 27 Figure 14: A simple flowchart representation for reading the GPS receiver 28 Figure 15: The UART settings used for the Uno microcontroller 29 Figure 16: The process of sectioning data 33 Figure 17: Bounding box representation 34 Figure 18: A simple example of sections with (left) and without (right) their bounding boxes displayed 35 Figure 19: Distance for possible intersection 36 Figure 20: Explaining this application of Pythagoras' theorem 37 Figure 21: Example effect demonstrating a section (with count 1) being partially intersected. All distances are in metres. 37 Figure 23: A visual example of the different section heat levels - from most traffic on the left to least traffic on the right 38 Figure 24: An explanation for the bounding box size choices 42 Figure 25: The potential Arduino shield's PCB layout 43 Figure 26: Process flow for potential panic button 44 Figure 27: The FreeMove welcome page 58 Figure 28: Signing into a new or existing FreeMove account 58 Figure 29: The error message when a user tries to navigate the web application without logging in 58 Figure 30: A successful sign in message 58 Figure 31: The FreeMove navigation bar 59 Figure 32: The data upload box on the FreeMove web application 59 Figure 33: The login page from Trintel's platform 59 Figure 34: The "Data" tab on the Trintel platform 60 Figure 35: A visual example of the different section heat levels - from most traffic on the left to least traffic on the right 61 Figure 36: Selecting which data is displayed 61 Figure 37: Triangle XYZ [85] 64 Figure 38: Unit sphere coordinates [85] 64 Figure 39: Final steps for spherical cosine law [85] 65 viii Figure 40: Performance comparison of spherical distance calculation methods [88] 66 Figure 41: ICC versus Frequency for the TI AHC00 [90] 67 Figure 42: (a) Counter-clockwise, (b) clockwise and (c) collinear orientation of 3 points [42] 68 Figure 43: Intersecting line that satisfy Condition 1 [42] 68 Figure 44: Intersecting collinear lines that satisfy Condition 2 [42] 68 Figure 45: Folder structure for the web application 74 ix List of Tables Table 2: Power supply options Table 3: Power usage of the AirLink GL6100 modem Table 4: Power usage of the logging device Table 5: Battery comparison Table 6: Motivation for Adafruit Ultimate GPS Logger Shield 25 26 39 40 63 x 1. Introduction Providing infrastructure that allows persons with disabilities to move safely and independently is a priority for both local and national governments and other non-profit organisations in South Africa. It is, however, extremely costly to upgrade infrastructure to fulfil these needs, and the parties interested in doing so are often very limited in their financial capability. The efficient allocation of funds is therefore critical in order to extract the maximum benefit from that which is available. The aim of this project is to provide interested parties with a way of gathering data about the routes used by persons with disabilities, and then presenting this data to them in a manner that allows for sensible interpretation. 1.1. Problem Description and Project Background The government has identified persons with disabilities as “one of the most marginalized and vulnerable groups” [1] in South Africa, and as such is trying to help these people (born into both wealthy and poor families) to live as independently and sustainably as possible. A part of this mission involves improving infrastructure in a way that allows persons with disabilities to have freedom of movement, in the sense that they can safely move from point A to point B without the help of others. The steps taken include equipping traffic lights at pedestrian crossings with speakers that beep to let those with sight disabilities know when it is safe to cross the road, ramps that allow wheelchair users to ascend or descend ledges, and specially designed contours on sidewalks that guide those with limited sight. The problem is that there is very little data available about the actual usage of said infrastructure, as well as the transportation routes of persons with disabilities. This means that the organisations that plan these infrastructure upgrades cannot properly optimise the spending of their very limited resources. 1.2. Suggested Solution The objectives of this project, as broadly described above, will be achieved by producing a portable, battery-powered route logging device, codename FreeMove, which relevant people can carry with them for an extended period of time. The device will then periodically transmit their route data to a central command station, from where the data can be downloaded to any computer that is authorised and connected to the internet. The route data will be completely anonymised before it can be viewed by anyone that is not part of the authorised technical staff. The data will also be visualised, on a webpage, in a manner that allows it to be easily interpreted in order to allow people to make more informed decisions about the upgrading of infrastructure. 1 1.3. Project Layout Chapter 1 handled the introduction to the project as well as a problem description. Chapter 2 provides the literature study that provides background information and research that was done in order to complete the project successfully. Chapter 3 describes the high-level design of the project by providing a system overview and the functional specifications for thereof. Chapter 4 handles the hardware design and component selection for this project. Chapter 5 explains all the software design that were taken in order to create a functional system. Chapter 6 discusses how the system was integrated, and what results were obtained after some testing. Finally, Chapter 7 analyses the success of the project based on the starting requirements, and provides a conclusion. 1.4. Requirements Some primary requirements for the success of this project were agreed upon by the author and Mr Arno Barnard at the start thereof, as per Appendix B. These are now listed. The logging device must be portable. The logging device must be battery operated. A Trintel-based system must be used to collect, display and distribute the data collected by the logging device. The collected data must be visualised and displayed on a map. The core requirements were then extended during the project planning phase by the author to improve the usefulness and validity of the project. The added requirements are listed below. The logging device must have a reasonable battery life between charge cycles. The logging device must be as small and light as possible. The logging device must be cheap to produce. The logging device must be made from components that are easily sourced in South Africa. The logging device must log route data in such a manner that the invasion of the person carrying its privacy is as minimally invaded as possible. The logging device has to be realisable by a single person in a relatively short space of time. The route data must be anonymised before any unauthorised person has access thereto. The route data must be visualised in a manner which allows it to be easily interpreted in a useful way. 2 2. Literature study In this section, some of the key concepts upon which the success of this project relies is investigated in detail using external and specialised sources. 2.1. Satellite Navigation Systems Satellite navigation systems are made possible by constellations of artificial satellites that orbit the earth. These satellites transmit information about their own location, as well as the precise time of transmission. [2] This information can then be used by small electronic receivers to determine their own locations by comparing the locations of 3 or more satellites with the time it took to get the message from the satellite to the receiver. This last step is possible by comparing the time the message was sent with the time it was received, according to the receiver’s internal clock. If only a single satellite’s signal is received, the receiver can only be determine that its position is a certain distance from the satellite – represented by the green sphere in Figure 1. If two satellites’ transmissions are received, the receiver can then be sure it is on the line where the spheres of the two satellites intersect, as represented by the circle on the same sketch. If a third satellite is introduced, the receiver can then pinpoint its own location to one of either two positions. One of these positions will not be on the earth’s surface, and therefore invalid, and so the receiver determines its position. Using more satellites will improve the accuracy of the determined position, especially if altitude is also of concern. Figure 1: Possible positions detected using 2 satellites (left) and 3 satellites (right) [26] There are three primary satellite navigation systems currently available, namely Galileo, GLONASS and GPS. Each of these options are now investigated, and a conclusion is drawn about which is most suited to this project. 2.1.1. Galileo The Galileo project is an effort by the European Union to create a satellite navigation system that is run independently from the American and Russian counterparts. It is suggested that the primary reason for its creation is because Europe has become too dependent on satellite navigation to rely on other countries to provide it, since these countries could easily decide to block Europe’s access thereto. It is estimated that about 3 6-7% of European GDP (Gross Domestic Product, an important economic indicator) is reliant on satellite navigation. [3] The first four satellites were successfully launched by October 2012, allowing the system to be tested and validated. It was originally planned that the system would become operational for civilian use by 2014, but progress has been slower than expected. Satellites number 5 and 6 were launched on the 22nd of August, 2014, but their orbits were not correctly circularised [4]. This means that the Galileo project is not yet operational for civilian use, and as such cannot yet be considered as a solution for this project. 2.1.2. GLONASS GLONASS (or “Globalnaya navigatsionnaya sputnikovaya sistema”, which translates to “Global Navigation Satellite System”) is satellite-based navigation system operated by the Russian Aerospace Defence Forces. The purpose of the project is to allow Russia to have an independent navigation system in place, should conflict or another reason lead to America blocking or scrambling their use of the GPS system. It also allows for receivers that can connect to both GPS and GLONASS satellites for increased accuracy. [5] The project was started in 1976 by the Soviet Union, and by October 2011 the system had reached a 24 satellite constellation capable of global coverage. This was ensured by a substantial financial backing from the Vladimir Putin presidency for the Russian Federal Space Agency. It was made free for civilian use in 2007. [5] The relative infancy of the system, which his only been fully operational on a global scale for three years at the time of writing, means that there are fewer receivers on the market that connect to the Russian satellites than to the American GPS counterparts. Neither Adafruit nor Sparkfun, two of the largest online electronics hobby stores in the world, sell any GLONASS compatible receivers. All of the other hardware components, as described in section 4.2 on page 19, can be found at both these stores. This has led to the discounting of GLONASS as a serious option for this project, especially given the timeframe of the project and the relative inexperience of the author. Exotic parts with little online support were actively avoided. 2.1.3. GPS GPS (Global Positioning System) was developed, and funded, by the United States Department of Defence in 1973. It was originally for their use only because of fears that it could be used by terrorists and other unwanted entities [6]. That changed after the Korean Airlines Flight 007 was shot down by a Soviet Union anti-aircraft airplane in 1983 after it accidently crossed into their territory en route from New York City to Seoul. President Ronal Reagan, of the United States of America, promised that GPS would be available for international civilian use once it became fully operational. This happened in 1993. [7] In terms of horizontal location accuracy, the U.S. government claim that high quality receivers should have an error margin of smaller than ~3.5𝑚, as shown in Figure 2. This value, together with update frequency, does however differ based on the GPS receiver module used. 4 Figure 2: Horizontal position error histogram [8] GPS is widely used as the satellite navigation system of choice. There are many GPS receivers available on the market at reasonable prices. Both the Adafruit and Sparkfun online stores have a selection of GPS receivers that are compatible with the Arduino Uno, or a similar microcontroller system, available for less than $40. GPS is an appropriate satellite navigation solution for the following reasons: GPS receivers are widely available at affordable prices. GPS has global coverage, and as such would work equally well anywhere in the world. GPS provides sufficient horizontal accuracy for the logging device to be able to track a person’s routes in satisfactory detail for this project. 2.1.4. NMEA 0183 Interface Standard NMEA is short for National Marine Electronics Association, which is the organisation that developed this communications standard. It defines an electrical interface and data protocol for equipment communications – specifically marine equipment. [9] The standard applies to various GPS receivers, such as the GlobalTop FGPMMOPA6H which is used for this project – as explained in section 4.2.2 on page 23. It is important to understand the standard used, because it not only describes the format of the information received from the GPS receiver, but also what exactly is received. This standard requires information to be sent serially using specific ASCII string formats, one of which is applicable to GPS receivers. The information encased in the comma separated string includes the position of the receiver (in terms of latitude, longitude and altitude), the land speed at which the receiver is moving, the current time and date, and whether or not the receiver has a valid satellite fix. 5 2.2. Wireless Communication The wireless communication of this project will be done via a Sierra Wireless AirLink GL6100 GSM modem. It makes use of quad band GPRS for transmissions, and accepts data from a RS232 serial port. The modem accesses the GPRS network by using a standard, commercially available, cell phone SIM card. South Africa boasts far reaching GSM network coverage, since the technology is used by the major cell phone network operators in the country. The GPS route logger will almost exclusively be used in urban areas where GSM coverage is all but guaranteed. This leads to GSM networks being an appropriate choice for the wireless communications required in this project. The mobile operator of choice for the SIM card required by the modem is MTN. This is primarily the case because the SIM card was supplied for this, project free of charge, by Trintel, but MTN also provide more than adequate network coverage in the metropolitan areas of South Africa, as can be seen in Figure 3. Figure 3: MTN network coverage [10] The modem is operated by using Trintel’s specifically developed AT (Attention) commands, called AWTDA commands. These commands are in the form of an ASCII text string transmitted serially, and as such can be produced by the microcontroller of choice (the Arduino Uno) without any difficulties. When used successfully, the AWTDA commands allow the route logging device to interact with Trintel’s so-called “SMART platform”. This means that if data is sent using the preceding command it can easily be accessed on Trintel’s website at smart.trintel.co.za. The platform also allows for events to be sent to the server, which can then either activate an SMS or an email alert. According to the datasheet, the GL6100 modem requires a minimum of 5V voltage to guarantee successful communication, with a maximum current draw at this voltage level given as 2A. This power usage is way out of line with the rest of the peripherals used in this device, when current draw in the 20mA to 50mA range is the norm. It would seriously impede battery life if the modem drew 2A of current every time a transmission is made. 6 This would imply that a solution would have to be designed where the modem was not part of the mobile device, but this would degrade both the user friendliness and reliability of the product, because users would need to connect the mobile device to the modem before it can upload data to the cloud. The modem was tested, however, which revealed that the maximum power dissipation stated in the datasheet was overly conservative. The test and results can be seen in section 4.3 on page 25. 2.2.1. GSM Communication Global System for Mobile (GSM) communication is a cell phone technology that is used by about 3 billion people globally to place wireless calls, according to the GSM Association (GSMA). This makes it the most widely used wireless communications method in the world, and GSM coverage is generally better in rural areas than that of the competing CDMA technology. GSM communication requires a Subscriber Identity Module (SIM) card, which attaches an identification number to each GSM device. This number can then be used to identify from which device data transmissions are originating. [11] 2.2.2. Trintel SMART Platform The SMART platform was developed by Trinity Telecommunications (Trintel) in order to allow users to easily monitor and control telemetry devices wirelessly. The data from said devices (called ‘assets’) gets uploaded to the web platform is the form of a variable. Figure 4: A simple view of the variable history of an asset on the Trintel SMART platform The history of each data variable is maintained, so that value changes can be tracked over time. These changes, or simply the current values, can be displayed on a dashboard page using so-called ‘widgets’. These widgets allow users to visualise and display data in an intuitive manner that allows for quick interpretation. Assets are also able to trigger events on the platform, or the other way around. It is possible because the platform is able to send data downstream, towards the asset, as well. This means that both the asset and the platform can react to predefined circumstances. An example of a predefined trigger would be an asset being told by the platform to adjust the power being supplied to an element in a geyser once the water temperature is detected as above a certain threshold by the platform. An example of the asset triggering a response on the platform would be if the asset sends an event trigger to the platform 7 based on the water temperature, from where the platform can then react by for example sending an SMS to a specified number. 2.3. JavaScript The author was not at all familiar with JavaScript before the start of this project, but some research revealed it to be necessary in order to create the functional and interactive web application that this project requires. Web applications, that run client-side as opposed to server-side, are built with three primary components, namely: HTML (or HyperText Markup Language) is the standard markup language used for web pages. It has embedded information that tell web browsers how to structure and display a web page. CSS (or Cascading Style Sheets) is used to customise the visual look and feel of the web page, defining things like text fonts and sizes, button shapes and background colours. JavaScript is a client-side scripting language that allows web developers to design interactive web applications with scripts that run asynchronously within the users’ browsers. HTML Page, structure and content Modern Web Applications Base level interactivity JavaScript CSS Scriptable page manipulation Page design / Look and feel High level interactivity Simple interactivity Figure 5: A simple Venn diagram representation of web applications with JavaScript [12] JavaScript (or JS, for short) is an object orientated coding language primarily used in web development for client-side scripting in web applications. Unlike the name suggests, it is unrelated to the Java coding language. It was originally called LiveScript, but the developers (Netscape) decided to rename it after Java shot to popularity in the 1990s. This is regarded by many as purely a marketing tactic, as it coincided with Netscape adding Java support to their web browser, the late Netscape Navigator. [13] Although JS originally only operated on the client side of a web application, Node.js [14] has allowed it to be used on the server side as well. This means that the backend as well 8 as the frontend of the web application can be written in JavaScript, and as such it is only necessary to learn a single language in order to create a high quality web application. The web applications that can be built with JavaScript come in almost endless shapes and sizes, but it is useful and relevant to this project because of a few reasons. The primary reasons are as follows: 1. There are many tutorials on JavaScript available on the internet free of charge, many of them published by recognised universities [15][16][17]. 2. It allows the implementation of user authentication. 3. It can be used in conjunction with an industry standard database solution, such as MongoDB [18]. Please refer to section 2.4 for more information. 4. There are recognised solutions available for displaying maps with information on them, as is discussed in section 2.6 on page 11. 5. JavaScript, in combination with HTML5 (the most recent revision of the HTML standard), makes incorporating file uploads into a web application relatively simple. 2.4. Meteor Web Application Platform The accompanying web application for this website will be based on the Meteor platform. Meteor is an open-source JavaScript-based platform for creating web applications as simply and quickly as possible [19]. Meteor is fully JavaScript compatible, which means that all the APIs [20] are available on both the client and the server side of the application, so no functionality is lost when compared to a pure JavaScript solution. Meteor has numerous advantages over a “vanilla” JavaScript web application, however. The platform allows for reactive page updates – meaning that pages will update automatically when data in the database is changed. Meteor also updates and renders templates individually, rather than full pages, for a much more responsive feel when compared to traditional webpages. Crucially, Meteor also allows the access to sensitive data to be controlled very effectively. This is very important for this specific project, as the client should only be allowed to access the logged route data if the user has privileged access to do so. It is very important to protect the privacy and safety of users taking part in the logging process of this project. Meteor’s so-called Smart Packages allow for the adding of various extra functions with relative ease, meaning that features such as user accounts and access, mapping widgets and professional notifications can be implemented by someone with limited web development experience (such as the author of this document). 2.5. Database Solutions There are two major classes of database management systems (DBMS) popular today, namely SQL (Structured Query Language) and NoSQL (Not Only SQL) systems. SQL is a language used to interact with relational databases. The language enables the use of many functions used to manage, store or retrieve data. Relational databases 9 comprise of tables with rigid columns, or fields. Each data entry should have a value in every field, and the system does not deal well with data where the fields are not static. [21] NoSQL refers to a non-relational manner in which data storage and retrieval is handled, as opposed to the relational manner in which SQL based solutions approach this. A NoSQL database does not always maintain referential integrity, and it favours low latency above all. [22] The database management required for this project is relatively simple, as coordinates are simply stored along with a few other values, such as the timestamp for each coordinate, or the section it belongs to (more on sections later). An SQL-based solution would be perfectly adequate, since the data stored in the database will always maintain a standard format. All coordinates will possess over the exact same attributes. NoSQL, on the other hand, is also more than capable of providing the storage solution for this project. NoSQL systems can also handle data with rigid attributes, although the structure is not so easy to visualise if viewing the data after it is stored. The structure is, however, known because it is chosen. NoSQL generally reacts better to horizontal performance scaling than SQL, but it is highly unlikely that this will be of any significance given that the database performance (in terms of the time it takes to load all the data) is not critical to the success of the project at all, as it will only be relevant while new data is being added. Since there is very little to separate the two, the reasons for choosing to implement a NoSQL system rather than a SQL system were trivial in the end, namely: The author developed a slight personal bias for NoSQL systems (specifically the document-storage variety, as discussed in the following subsection) after some limited hands-on experience with both SQL and NoSQL implementations. Research suggested that it could be beneficial to the author to develop some familiarity with MongoDB (a NoSQL database management system), as it is one of the most popular database management skills currently advertised by IT professionals on LinkedIn. Please see the following subsection for more information on this point. 2.5.1. MongoDB MongoDB is an open-source, NoSQL database management solution. MongoDB uses what is referred to as “Document-Orientated Storage”. This is a data model where so-called documents are stored in the database. These documents have one or more named fields which are dynamic and can be defined differently for each document. These fields can contain anything from variables to arrays of objects. Documents themselves do not behave completely unlike objects. These documents are then stored in so-called collections, so that it is simple to retrieve relevant data when required. MongoDB is one of the leading NoSQL solutions currently available. It has received at least 3 times as many Google searches than any other NoSQL data management system, many more professionals on LinkedIn[23] list MongoDB in their profile than any other 10 NoSQL database management system, and Japersoft[24] lists MongoDB as the top performer in their Big Data Index. This is a difficult aspect to measure concretely, but the abovementioned statistics provide a substantial argument. [25] Figure 6: Google searches for NoSQL database management systems [25] Figure 7: NoSQL skills listed on LinkedIn [25] Figure 8: Total number of connector downloads according to the Jaspersoft Big Data Index, for document storage data stores [25] Figures Figure 6 to Figure 8 show that there is clearly some value in investing the time to get a proper understanding of how to use MongoDB, which makes it an apt choice as the database solution for this project. Almost more important, however, is its opensource nature. This means that it can be obtained and used free of charge – regardless of how successful or unsuccessful the project eventually is. 2.6. Mapping Solutions There are two main options available to handle the mapping display of this project, namely Google Maps [26] and OpenStreetMap [27]. 2.6.1. Google Maps Google Maps is a web based mapping service provided by Google [28] that allows third party websites to embed their service via the Google Maps API [29]. The embedded map then downloads the map tiles from Google’s servers as they are needed, depending on the embedded map’s bounds and zoom level. The page does not have to be reloaded for new tiles to show, instead they download individually and appropriately as the user pans and zooms on the map. 11 Third party websites may make use of this service free of charge, unless “you consistently generate a high amount of traffic” when “you will need to pay for extra usage” [29]. Google defines this as a website generating more than 25 000 “map loads” [30] per day consecutively for 90 or more days. It is extremely unlikely that this project will ever generate that kind of web traffic, but it is still worth noting that it may result in some costs should the product become surprisingly successful. There is currently no advertisement from Google involved with making use of this service, but Google does reserve the right to display ads in the future. This is again something that is unlikely to become a reality in the immediate future, but it is worth taking note of. 2.6.2. OpenStreetMap OpenStreetMap [27] (referred to as OSM from here onwards) is a community built and driven mapping service. The idea is to create a map of the entire world that is free to use and is created by a voluntary community, much like what is done at Wikipedia [31]. The data provided by this mapping service can be used at no cost as long as OSM is given credit therefor. This is easily done with a tiny link in the bottom of the mapping widget, and is of no detriment to this particular project. This service is also free from advertisements. In order to use the OSM data on a third-party website (like that of the web application for this project) there are two popularly used JavaScript libraries, namely Leaflet and OpenLayers. Leaflet Leaflet [32] (also referred to as Leaflet.js or LeafletJS) is a widely used JavaScript library for creating interactive maps on websites or web applications by combining it with OSM or another mapping service. It is also an open-source project, which means that all the source code is available and the library is free to use. The documentation on the project’s official website [32] is well organised and easy to follow, with enlightening examples and tutorials thrown in for good measure. This means that even someone with next to no experience with JavaScript or mapping APIs (like the author of this document) can get a simple map, complete with basic markers or polylines, up in running in minimal time. Leaflet has a map controller that can be implemented to allow the user to change map data, but specifically it allows users to select the visible layers. This is relevant to this project as it would allow users to choose to view data from different categories individually or together in any possible combination. The library places focus on being “mobile friendly” – meaning that the interactive maps created using Leaflet display and work as expected on mobile devices and implement features such as multi-touch zooming. This is of minimal consequence for this project though, as it is not expected that many users will wish to visit the web application from a mobile device, but nevertheless it allows for more flexibility should the direction of the project change somewhat with time. 12 OpenLayers OpenLayers [33], like Leaflet, is an open-source JavaScript library used to display interactive and dynamic maps on websites or web applications. The library is not biased towards any map provider, and can be used to display, among others, Google Maps or OpenStreetMap map data. Since the Google Maps API [29] is more than adequate for use with Google Maps, OpenLayers is investigated as an option for the display of OSM map data. There is an impressive amount of examples on the official OpenLayers website (207 at the time of writing [34]), but it is not sensibly organised (alphabetically instead of categorically) which means that finding an example on a specific topic of interest is not always an intuitive process. There is an extensive API available for developers to view [35], but again the navigation of this document is (in the opinion of the author) tedious and often frustrating. 2.6.3. Practical Testing Since the literature study provided no clear answers as to which mapping solution would be best suited to for the needs of this project, it was decided to create a basic implementation of each option. This allowed for a more first-hand assessment of the strengths and weaknesses of each solution. The goal here was to implement a simple interactive map in the Meteor environment that could draw routes based on data in the MongoDB database. In the end, there was almost no difference between using the different solutions and as such it mostly came down to personal preference. OpenStreetMap was chosen ahead of Google Maps simply because there was no chance that it would be commercialised and start costing money, unlike Google Maps where a future subscription fee is not impossible. In terms of auxiliary libraries used to access OSM, the author preferred the way in which the documentation for Leaflet was set up, and that ended up as the main reason why it was chosen over OpenLayers as there was so little to differentiate between the two. 2.7. Software Algorithms 2.7.1. The Least Squares Method The Least Squares Method is a regression model that is often accredited to the great German mathematician Carl Friedrich Gauss, who claims to have investigated this way of data fitting as early as 1794, but it seems likely that French mathematician Legendre was in fact first to publish it in 1805. [36][37][38] This method is essentially an algorithm that is used to calculate the line that would best represent a number of, somehow related, data points by finding the values that would produce the smallest total error when each error, or discrepancy between the line and each point, is squared and summed. In the context of this project, it is used to calculate the straight line that best represents a number of latitude/longitude coordinates. The following formulae were used to calculate the straight line that would best describe the coordinates: 13 𝑚= (∑ 𝑥)(∑ 𝑦) 𝑛 (∑ 𝑥)2 ∑(𝑥 2 ) − 𝑛 ∑ 𝑥𝑦 − (1) Where m is the slope of the new line, n is the number of coordinates and x and y represent each coordinate’s latitude and longitude, respectively. 𝑏 = 𝑦̅ − 𝑚𝑥̅ (2) Where b is the latitude-intercept of the new line, and 𝑥̅ and 𝑦̅ represent the mean values of the latitude and longitude, respectively, of each coordinate. The slope, m, and latitude-intercept, b, are then used to compute the definition of the new straight line that will represent the collection of coordinates. The linear equation used to calculate the coordinates of this new line is shown next. 𝑦 = 𝑚𝑥 + 𝑏 (3) All the variables have the same meanings as before, except that the actual latitudes and longitudes are used instead of their mean values. The start and end of this line segment is defined by the latitude of the first and last coordinates in the segment. From there, the above linear equation is used to calculate the matching longitude values, as well as any coordinate values that appear in the segment. 2.7.2. The Haversine Formula The haversine formula is used to calculate the distance between two coordinate points, described by their latitude and longitude values, along the outside of a sphere. It is a specific case of the general Law of Cosines. The derivation of the haversine formula, as well as the differences between it and the Law of Cosines, is available in Appendix G. Please see this appendix for a more in-depth analysis of the formula. The haversine formula is more complex to implement in JavaScript than the Law of Cosines, and as such there is a performance penalty. The performance penalty is offset by the fact that it is regarded as more accurate than the Spherical Law of Cosines when working with distances where accuracy of a few meters is required [39][40][41]. The processing power on the server is also more than capable of handling such calculations, and therefore it is of little consequence for this particular implementation. The distance calculation code will only run when data is being added to the database, and as such a few milliseconds, or even a few seconds, performance difference may be dismissed. The performance differences between the haversine formula and the Law of Cosines is also discussed in more detail, along with test data, in Appendix G. As the performance impact is negligible to the success of this project, the haversine formula will be used because of the increased accuracy when compared to the Spherical Law of Cosines when calculating the distance between two coordinates on the earth’s surface. 14 2.7.3. The Orientation Method for Line Intersections The so-called ‘orientation method’, as described by Dr Patrick Prosser of the University of Glasgow [42], is used to determine whether or not two line segments intersect one another. This is a very important step when trying to determine whether a newly generated route section crosses a previously generated section’s bounding box area. Figure 9: Intersecting line that satisfy Condition 1 [42] Please refer to the example in Figure 9 for the short explanation of the orientation method. If the line segments defined by points (p1, q1, p2) and (p1, q1, q2), respectively, have different orientations, as do those defined by points (p2, q2, p1) and (p2, q2, q1), two lines intersect. Lines can also intersect while perfectly collinear, but that situation is extremely unlikely in this application. Please see Appendix I for a much more detailed explanation of the orientation method. 2.8. Arduino Libraries The Arduino Uno is selected as the microcontroller system of choice for the mobile logging device. Please see section 4.2.1 on page 19 for an in-depth explanation on why it is chosen. This subsection discusses two of the core software libraries investigated and implemented on the Arduino Uno during this project. 2.8.1. Arduino TinyGPS Library TinyGPS [43] is an Arduino library, created by Mikal Hart, that allows users to easily access information from a GPS receiver that applies the NMEA standard, as explained in section 2.1.4 on page 5. The library provides an object that can be given the NMEA GPS data serially, one character at a time, as the GPS receiver generates it. This object will then return a ‘true’ value when a valid NMEA sentence has been parsed, which then allows the program to execute functions only when a new, complete sentence has been received. This object can then be queried in order to retrieve the information given by the GPS receiver. These various functions will then return the data, such as position or time, in a sensible format. The library also avoids any unnecessary floating point operations. This is done because the Arduino Uno is based on the 8-bit Atmel ATmega328P processor. The processor cannot compute 32-bit floats natively, and so there is a severe penalty in terms of required resources when a program does require to use this variable type. The fact that the library avoid floating point operations is useful, not because the processing speed is an issue, but rather because battery life is so crucial for this project. Using less resources means that the processor drains less battery, so making use of performance optimal code has a direct influence on the device’s power usage. 15 2.8.2. Arduino SD Library As the name suggests, this is an Arduino software library that helps users to write and read data to and from an SD storage card. This library is an extension of sdfatlib, another SD library for the Arduino, written by William Greiman. [44]. 2.9. Serial Communication Serial communication is to be used for data communication between the microcontroller and the AirLink GL6100 modem. The Arduino Uno uses TTL (TransistorTransistor Logic) serial, while the modem uses RS232 serial. A UART (or Universal Asynchronous Receiver / Transmitter) is used as a parallel to serial converter in each device. Data can be fed to the UART in parallel, but it is then converted so that it may be sent serially. On the other side, it is received serially and converted back to a parallel format. This is done so that a minimal number of physical wires is required between the two devices. In this case, a single wire is used for data transfer in each direction, therefore only two wires are required between the two devices. [45] The transmission consists of a start bit, the data bits, a stop bit, and then an optional parity bit. This parity bit indicates whether the number of bits sent was even or odd, and as such functions as a very simple form of error detection. [46] Figure 10: Example of RS232 data transmission with no parity bit [47] The communication protocol for RS232 and TTL serial is the same, but the voltage levels used to represent the logical values of the signal do differ. The RS232 serial specifies that a logical ‘1’ has a voltage of between -3V and -25V, while a logical ‘0’ has a voltage level of between +3V and +25V. The standard allows for an undefined state to exist between the values of -3V and +3V. TTL serial represents a logical ‘1’ with the VCC voltage of the system (normally 3.3V or 5V), while a logical ‘0’ is represented by the ground voltage of the system. The difference in voltage levels used by each standard means that voltage conversion would have to take place between the two devices in order to allow for successful data communication. 2.9.1. ASCII The American Standard Code for Information Interchange (ASCII) is a globally accepted standard whereby numerous letters and symbols are referred to by numerical codes in a 7-bit format. The 8th bit in the byte is used as a parity bit for error detection purposes. [48] This is also the standard which the AirLink GL6100 uses to decode instructions. 16 3. High-Level Design In this chapter, the high-level design of the system is presented. 3.1. System Overview The complete system of this project is explained visually, in a very simple high-level manner, in Figure 11. Figure 11: A simple system overview diagram 3.2. Administrative Structure Upon showing official identification, the logging device is handed to the user User carries logging device on their person Logging data is automatically uploaded to cloud System administrator transfers data from Trintel SMART to FreeMove web application END PHASE Logging device is set up according to user disability LOGGING PHASE START PHASE The administrative structure is an important design step in this project, as it determines the background with which all other considerations must be made. The steps of the life cycle of a single user’s routing efforts are outlined in Figure 12. User returns logging device after logging period System administrator uploads routing data from SD card to web application Web application automatically determines which coordinates have not been uploaded to web database yet Figure 12: A simple visualisation of product use flow 3.3. Technical Specifications The technical specifications were drawn up by using the project requirements given in section 1.4 on page 2. 3.3.1. Logging Device The mobile logging device must weigh less than 500 grams in order to not be overly intrusive to its wearer. 17 The logging device must have outer dimensions of smaller than 100mm x 80mm x 30mm, and have a flat, rectangular shape for the same reason as the preceding point. Although the packaging for the device is outside of the scope of this project, it must be conceivable that the device could be packaged to said dimensions. The logging device has to be cheaper than R1500 to produce in South Africa so that it may be commercially viable. The logging device must be able to run from a single charge of its power source for at least 12 hours. o If the power source is a 9V battery, this equates to a power consumption of about 0.3375W. (Please see section 4.2.4 on page 24 for an explanation of battery life calculations.) o If the power source is four 1.5V AA batteries in series, this power consumption equates to about 1.25W. (Please see section 4.2.4 on page 24 for an explanation of battery life calculations.) The logging device must be able to track a user’s travel route by recording GPS coordinates at a rate of at least 0.25Hz. The update rate was decided upon after some experimentation by walking around with GPS receivers in order to estimate how far the average person would move in a second. The logging device must be able to save the GPS coordinates (as well as the time at which each coordinate was logged) to an external storage device of minimal size, such as a microSD card. The logging device must be able to communicate the abovementioned GPS data to the AirLink GL6100 GSM modem via RS232 serial, with or without peripheral ICs. This project would benefit from the immediate and wireless communication provided by the modem, as it would prevent data loss in the event that a logging device is lost or broken before its data could be manually uploaded. Data that is received near real-time also opens up other development options, such as a panic button – as discussed in section 6.6 on page 44. The modem was also sponsored and set up for the project by MTN and Trintel, which means it added no financial strains. 3.3.2. Web Application The web application has to allow users to create unique profiles, with both a username and a password. The web application must only make route data available to a person who has been given the privilege by a system administrator. The web application must anonymize all route data before it is made visible to anyone beside authorised system administrators in order to protect the privacy of those whose tracks are stored. The web application must divide route data into sections, over which traffic may be counted. The web application must visualise the traffic over each section by using, for example, colour intensity and line thickness. 18 4. Hardware Design and Component Selection This section handles all the hardware design steps that allowed the fulfilment of the goals set at the beginning of this project. This involves choosing components and integrating them, acknowledging power usage and the issues involved with that, as well as focussing on the general user friendliness of the prototype product. 4.1. Required Components The following list of components has been deemed necessary after studying the lists of requirements carefully. The reasoning behind each choice is also listed. Microcontroller: A microcontroller of some sort is required to control all the necessary sensors and log the data to some form of storage, before it is uploaded to the central command station. GPS receiver: A Global Positioning System (GPS) receiver is required in order to accurately and easily track the wearer’s movements. Storage: External storage is required in order to store the GPS coordinates until it can be uploaded to the central command station. Power supply: A battery solution has to be found to power the device. Wireless communication: A modem of some sort is required in order to upload the GPS routing data to Trintel’s web service. Communication between components: An integrated circuit (IC) solution is required to allow the microcontroller (TTL serial) to communicate with the modem (RS232 serial). There are many options available for each of these components. These options will be explored and compared in the section 4.2 of this report. 4.2. Component Selection 4.2.1. Microcontroller There are several microcontroller systems capable as functioning as part of the mobile logging device for this project. After some careful research, the options were narrowed down to the Arduino Uno, Beaglebone Black, Raspberry Pi, Texas Instruments MSP430 and TinyDuino. The abovementioned options are now further examined in order to determine which is most suited to this particular project. Arduino Uno The Arduino Uno Revision is a microcontroller board based on the ATmega328 microcontroller. The Uno is promoted as the mainstream Arduino board, which means that there is a vastly superior number of accessories available for it in comparison to the other Arduino products, and most tutorials and resources assume that this model is used. The large scale support for the Uno, combined with no need for any of the features made available exclusively by some of the other products in the range, the availability in South 19 Africa (see [49]–[52]) and the low retail price of less than R300 (again, see [49]–[52]) made the Uno the Arduino product of choice. According to the manufacturer’s website, the Uno features “14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analogue inputs, a 16 MHz ceramic resonator, a USB connection, a power jack, an ICSP header, and a reset button.” [53] The aforementioned specifications more than meet the minimum requirements, since the microcontroller will not be expected to perform any complex calculations. In fact, the relatively slow processor (when compared to the other microcontroller options) is ideal as minimal power usage is integral to the success of this project. Please refer to Appendix H for a detailed analysis of the relation between power usage and processor speed. The stock Uno can operate with an input voltage of between 7V and 12V, meaning that a 9V battery provides an easy early start for testing. However, there are many guides on the internet (such as the one referenced at [54]) that suggest it is entirely possible to replace the stock 7805 5V voltage regulator with one that provides 3.3V output. This means that if a regulator such as the Texas Instruments LM1117 800mA low-dropout linear regulator is used an input voltage of as little as 4.3V is required to provide a stable 3.3V to the system [55]. This means that, theoretically and ideally, three AA batteries which provide 1.5V each could power the system when placed in series, since: 𝑉 = 1.5 ∙ 3 = 4.5𝑉 > 4.3𝑉 This is an advantage over having to use a 9V battery, since AA or even AAA batteries would typically last longer. Please see section 4.2.4 for a detailed explanation on different battery solutions. The Uno has been tested to draw 46.5mA when not driving any external logic, and is not placed into “sleep mode” with software[56]. This means that the power usage in such a scenario (and using the stock 5V setup) would be as follows [57]: 𝑃 = 𝑉 ∙ 𝐼 = 5𝑉 ∙ 46.5𝑚𝐴 = 232.5𝑚𝑊 The physical dimensions of the Uno PCB are listed as having a maximum length and width of 6.86cm and 5.33cm, respectively [53]. Beaglebone Black The BeagleBoard BeagleBone Black is a “low-cost, community-supported development platform for developers and hobbyists” based around a 1 GHz Cortex A8 processor [58]. This board has been commercially available since 2013 [59] and has a recommended retail price (RRP) of $55 (or about R585 [60]). In South Africa, however, the Black sells for closer to R900 [61]. This development board offers a general purpose computer running Linux, with two PRU 32-bit microcontrollers and some input and output (I/O) pins (2x 46 pin headers, to be exact) in order to connect to external sensors and expansion devices. The device also provides 512MB DDR3 RAM, 4GB on-board flash storage, HDMI output and Ethernet capabilities. [58] The board needs 210-460mA current at 5V voltage, depending on the tasks being employed and what speed the processor is running at, in order to operate [62]. The power (P=VI [57]) consumption is now calculated for both the best and worst case scenarios. 20 𝑃 = 𝑉 ∙ 𝐼 = 5𝑉 ∙ (210𝑚𝐴 𝑡𝑜 460𝑚𝐴) = 1.05𝑊 𝑡𝑜 2.3𝑊 It is, however, possible to run the BeagleBone Black with a lower voltage if 5V voltages are not required elsewhere in the system for expansion devices. In fact, it is manufactured and sold with a Texas Instruments TPS65217C based power management IC which allows for 3.7V Lithium-Polymer (LiPo) rechargeable batteries to power the device. The physical dimensions of the Beaglebone Black is 8.76cm by 5.84cm. Raspberry Pi The Raspberry Pi (from here on referred to simply as “Pi”) is more than a microcontroller – it is a fully fledged personal computer, capable of running a Linux operating system and performing general computing tasks such as playing videos or editing documents. The Pi model B, which is the most readily available version of the development board, comes with a 700 MHz ARMv6 CPU, 512 MB of RAM and a Broadcom VideoCore IV video processor. It has 8 general purpose digital I/O pins, a UART and a SPI bus. There is also HDMI video and audio output, and an Ethernet port for networking. The model B draws between 700-1000mA at 5V, “depending on which peripherals are connected” [63], which equates to 3.5W – 5W of power consumption (P=VI [57]). The physical dimensions of the Pi is 8.56cm by 5.6cm – very similar to that of the Beaglebone Black. It sells for around R665 from reputable online retailers in South Africa [64][65]. Texas Instruments MSP430 The MSP430 is a line of low-power, value-driven microprocessor systems developed by Texas Instruments (TI). The model that was singled out as a potential solution for this project is the MSP-EXP430G2, which is the most basic and affordable version of the MSP430 that TI offers. It is based on a 16MHz processor with 512B RAM and 16kB of flash memory for programs. The board provides both 8 digital and analogue I/O pins. The device is advertised for an incredible $9.99 on TI’s website [66], significantly less than any other listed option. In South Africa, however, it sells for closer to R200 [67]. The MSP430 has been tested to consume as little as 1mW power, when all of the on-board LEDs are disabled [68], which also makes it the most power-friendly of the options listed. The MSP430 has recently exchanged an Eclipse-based programming environment for one based on the open-source Energia prototyping platform. Energia is credited with allowing Arduino programs to be directly ported to the MSP430, and it provides a crossplatform solution that works on Linux, OS X and Windows. The platform does not, however, support the user generated Arduino libraries, but many have been ported to work on the MSP430. [69] TinyDuino The TinyDuino is microcontroller system based on the same Atmega328P processor as the Arduino Uno, but it runs at a slower 8MHz clock frequency. The entire TinyDuino board comes in dimensions of only 20mm x 20mm, but it does not include a USB programmer to load programs onto the device. 21 The device sells for $20 on the TinyDuino website without the USB programmer, or $40 for a basic starter kit which includes both the processor and the programmer. The system is not for sale from any local South African distributors. Tiny Circuits, the company that produces the TinyDuino, claim that most Arduino programs will run on the TinyDuino without any modifications, but Arduino shields to not fit on the device because of size miss matches. TinyDuino does have shields developed specifically for it, but the range of these is still quite limited. There is, importantly for this project, a GPS shield produced by the company, but it is out of stock at the time of writing with no estimated time for new stock arrivals. Conclusion The Beaglebone Black and Raspberry Pi are by far the fastest and most versatile of the systems investigated, but their excessive power consumption (1W – 2.3W for the Black and 3.5W for the Pi, respectively) immediately rule them out for this project. The specifications listed in section 3.3 on page 17 state that the device should be able to run on batteries for at least 12 hours, a feat which would prove difficult for either of these systems. They are also more expensive than the other options, with prices of R900 and R665 for the Black and the Pi, respectively. The TinyDuino comes in an impressively small package, and it has the technical capabilities to complete this project, but there are two reasons for its dismissal. Firstly, and most importantly, the TinyDuino would have to be imported from its American producers. This is an issue because there are serious time constraints on the project, and many horror stories are told about products getting stuck at the South African customs office for indefinite periods. Secondly, at $40 dollars before any shipping costs are added, it is relatively expensive when compared to the Arduino Uno and TI MSP430 – especially since the AirLink GL6100 modem and the GPS receiver will likely make the small size of the microcontroller obsolete as they are significantly larger. The form factor of the TinyDuino also means that it is not compatible with many Arduino Uno accessories. In terms of power consumption, the TI MSP430 is streets ahead of any other option listed. The system uses about 30mW without any modifications [68], while the second best option, the Arduino Uno, uses about 230mW after it is heavily modified to reduce power consumption [56]. The MSP430 is also the cheapest solution available, at about R200. The second best choice in terms of pricing is once again the Arduino Uno, which sells for about R300 in South Africa. A major drawback of the MSP430 is that it does not support all of the user-generated software libraries available to the Arduino Uno, and only some of the accessories. Granted, it is possible to complete this project using a MSP430 as the base, but given the time constraints and the minimal relevant experience of the author, the lack of widespread support, compared to that offered by the Arduino solution, is a definite caveat. The Arduino Uno offers a more all-round solution. It is not the cheapest or the most power efficient solution on offer, but it performs admirably in both these areas. The Uno is also stocked by various distributors in South Africa, and availability is not an issue. 22 The Uno provides enough I/O pins to allow for communication with all the required sensors and peripherals. The area in which the Uno excel above all else, however, is support. There is a vast amount of learning material available free of charge on the internet, ranging from introductory tutorials on generating a blinking LED program to specific lessons on how to read a GPS receiver using the built-in UART. There are various user-generated software libraries to make tasks such as reading an SD card straightforward using an Arduino Uno. Hobbyist shops sell Arduino Uno specific peripherals, or “shields”, that simply attach to the device using header pins to perform almost any function imaginable, from determining position using GPS receivers [70] to the amount of radiation in the air [71]. Thus, based on availability, performance, power consumption, price, size and support, the Arduino Uno was chosen as the microcontroller system of choice to act as the base for the portable logging device developed for this project. 4.2.2. GPS Receiver The various factors impacting the choice of GPS receiver used for this project are briefly discussed here, in order to explain why the selected component is an appropriate choice. The antenna of the module determines the accuracy of the receiver. A good antenna allows the receiver to read weaker signals, sometimes as weak as -165dBm, in areas where the signal reception is not very good. Urban areas with many tall buildings, for example, tend to have poor satellite reception. A sensitive antenna would mean that the logging device is able to track routes in dense cities where satellite visibility is limited. For the purpose of this project, the physical size and layout of the receiver is of great import, since the logging device has to be small and light in order for someone to consider carrying the device around all day with minimal disruption to their routines and comfort. This means that the form factor of the products were also given serious consideration. Power usage is another concern, since the mobile route logging device will be powered by batteries, and having the maximum time between necessary charges is important in order to build a user friendly and cost efficient prototype. The ease of use was also considered, in the sense that it was estimated how long it would take to integrate said GPS receiver into a working route logging device in conjunction with an Arduino Uno. This was a consideration mainly because of time constraints for the development of a prototype product, and as such as large a time buffer as possible had to be allowed for to enable possible troubleshooting of unforeseen problems that could (or will, probably) arise. Lastly, the price of the unit also plays a major role. The success of this project relies on a very affordable product that is aimed at providing aid to a market segment that has extremely limited financial capabilities. In fact, this is the main reason for the very existence of this project. An expensive route logging device would be counterproductive, to say the least. With the aforementioned criteria in mind, the GPS receiver chosen is the Adafruit Ultimate GPS Logger Shield (henceforth referred to simply as the ‘Adafruit GPS shield’). 23 This product is based on the GlobalTop FGPMMOPA6H (also referred to simply as ‘PA6H’) GPS receiver module. The unit has an ideal form factor, as it is simply attached to the top of a Uno using header pins. The components on the shield are already wired correctly to allow an easy setup which merely involves connecting the 5V voltage pin, ground pin and the required digital I/O pins from the Uno appropriately. The ease of setup should lead to minimal time lost to debugging before a simple system can be successfully implemented. Another attractive feature of the Adafruit shield is that it has an integrated microSD card slot, which has also been connected with the appropriate ICs for easy setup. This integration helps to justify the price of the shield, as it covers two of the components required for this project in full. There are no extra capacitors or resistors needed, or any other so-call “hidden costs”. The unit is also widely used, which has led to a large support base on the internet as well as many documented stories of its successful implementation, meaning that the product may be purchased with confidence that it will function as advertised. The shield uses minimal power (20mA current draw at 5V), and it is sold for R781.00 in South Africa. The choice is further justified in Table 5, which can be found in Appendix F. 4.2.3. Storage Some form of storage is required in case there is an issue with the wireless transmission, such as a loss of signal or technical issues on Trintel’s side. The data is relatively small in size, however, with each coordinate saved taking up 28 bytes as calculated in section 5.2 on page 29. This means that if a coordinate is stored each second, 24 hours’ data would total the following: 𝑇𝑜𝑡𝑎𝑙 𝑓𝑖𝑙𝑒 𝑠𝑖𝑧𝑒 = 24ℎ𝑟𝑠 × 60𝑚𝑖𝑛𝑠 × 60𝑠𝑒𝑐𝑠 × 28𝑏𝑦𝑡𝑒𝑠 = 2419200 𝑏𝑦𝑡𝑒𝑠 = 2.42 𝑚𝑒𝑔𝑎𝑏𝑦𝑡𝑒𝑠 The preceding calculation shows that thousands and thousands of coordinate entries still only result in a small text file by modern standards. This means that using a microSD card of a very modest size, such as is easily done with the Adafruit Ultimate GPS Logger Shield, and would allow the device to store weeks’ worth of routing data. For example, a year’s worth of data would be equal to 2.42 𝑀𝐵 × 365 𝑑𝑎𝑦𝑠 = 883.3 𝑀𝐵. This implies that if each device was equipped with a 1 gigabyte micro-SD card, it would be able to contain all the routing data for that user for a year – which is in all probability much longer than a user will keep a logging device. A 1 gigabyte micro-SD card would therefore allow each user to store the entirety of their routing data with the logging device on a single storage device. When the user then returns the logging device, an administrator can upload all the data to the FreeMove website by simply dragging and dropping the data files, and the system will then ensure that all the routing data is in fact added to the database. 4.2.4. Power Supply The Arduino Uno requires an input voltage of at least 6V in order for normal functionality to be guaranteed, according to the datasheet. This means that there are three options, in terms of commercially available battery solutions, that stand out. These options are tabulated in Table 1. 24 The microcontroller will be run from a conventional commercial 9V battery in the beginning, since this allows for immediate development of the most crucial features of the product. The 9V battery has a convenient form factor, is easily acquirable at a modest price, and it does not require any special casing in order to get it to work with the Arduino Uno. Table 1: Power supply options Option Voltage 1x 9V Battery [72] 4x AA Battery [73] 4x AAA Battery [74] 9V Capacity (at constant 100mA discharge current) 450mAh 4 x 1.5V = 6V 2500mAh 4 x 1.5V = 6V 1000mAh Dimensions Weight 48.5mm x 24.5mm x 17.5mm 202mm x 58mm x 58mm 178mm x 42mm x 42mm 45.6g 23g x4 = 92g 11.5g x4 = 46g This is only a temporary solution, however, as the option with 4 AA batteries in series is clearly the best choice. The AA batteries, and even the AAA batteries, provide a much larger capacity than the 9V battery does – if at a reduced voltage level.Consider a situation where the device requires 100mA, and assume that the current required by the voltage regulator is negligible. If a 9V battery setup is used, and power is defined by P=VI [57], the power consumed by the device is P = VI = 9V*0.1A = 0.9W. A typical 9V alkaline battery setup would therefore 450𝑚𝐴ℎ last for about 𝑡 = 100𝑚𝐴 = 4.5 ℎ𝑜𝑢𝑟𝑠. If four AA alkaline batteries are used in series, for a total voltage of 6V, the power dissipated by the device would be equal to P = VI = 6V*0.1A = 0.6W, or about 33% less than the power used in the 9V setup. This is because the voltage now only has to be regulated from 6V down to 5V, rather than from 9V. The larger capacity of AA batteries also have a significant impact. A typical AA battery 2500𝑚𝐴ℎ solution would power the logging device for around 𝑡 = 100𝑚𝐴 = 25 ℎ𝑜𝑢𝑟𝑠 – or about 5.5 times as long as 9V solution would. Four AAA batteries in series would also provide a significant upgrade on using a 9V battery solution. This solution would give the logging device a battery life of 900𝑚𝐴ℎ approximately 𝑡 = = 9 ℎ𝑜𝑢𝑟𝑠. 100𝑚𝐴 The impressive battery life that four AA batteries in series can provide the logging device with means that it is the power supply solution of choice for this product. Rechargeable batteries would be preferable in order to minimise the long term cost and environmental impact of the product. 4.3. AirLink GL6100 Power Consumption As noted in section 2.2 on page 6, the power consumption of the AirLink GL6100 had to be tested in order to determine whether or not it would be feasible to package it as part of the mobile logging device. If the modem displayed a current draw of anywhere near the 2A maximum specified in the datasheet, a solution would have to be found where the modem forms part of some sort of charging base station. 25 The simple testing methodology used is now listed: 1. Identify which ports on the AirLink GL6100 modem are used for VCC and Ground, respectively. 2. Set an adjustable bench mounted power supply, with controllable current, to 5V. 3. Connect the power supply to the modem, and monitor current draw from it. 4. Connect the modem to the Arduino Uno microcontroller, and transmit a typical message to the Trintel SMART platform. 5. Monitor the power spikes as messages were transmitted via GSM. This process was repeated for several transmissions, in order to assure that no anomalies were found. The results were deemed consistent and conclusive, and are displayed in Table 2. The start-up current drawn by the system is within a few milliamps of the idle current draw. Table 2: Power usage of the AirLink GL6100 modem Supplied voltage Average current draw (idle) Average current draw (transmitting) Average power consumption (idle) Average power consumption (transmitting) 5V 45mA 80mA 0.225W 0.4W This means that the power consumption of the modem is in fact in line with that of the rest of the peripherals used in the project. It would not have such a drastic impact on battery life that it becomes impractical to attach it to the mobile device. This is the solution of choice because it requires minimal effort from the user. 4.4. RS232 and TTL Serial Communication RS232 and TTL serial communication is identical in terms of the protocol used; the difference is only in the voltages used to represent either a logical ‘1’ or ‘0’ – as discussed in section 2.9 on page 16. The Uno microcontroller makes use of TTL serial communication, while the AirLink GL6100 modem adheres to the RS232 standard. In order to allow for communication between the two standards, the RS232 signal has to be both inverted and regulated to ensure that the mechanical circuits on the Uno is not damaged. The TTL signals from the microcontroller also has to be inverted and amplified in order to ensure that it can be correctly interpreted by the modem. This is done with a designated integrated circuit, such as the Texas Instruments MAX232. There are many ‘clones’ on the market that perform similarly, such as the Sipex SP232ACP. These ICs are used to transform the TTL and RS232 signals so that they are compatible, and one is simply placed between the Uno and the modem to make communication possible. The Sipex SP232ACP is chosen for this project because it fits the requirements (which is to allow the microcontroller to communicate with the modem without adding bulk to the device), and it was obtainable immediately and free of charge. 26 5. Software Design This section documents and discusses all the software development that went into this project, both for the programming of the Arduino Uno microcontroller and the website that would be used for data analysis. 5.1. Microcontroller Programming Arduino provide users with development software used to create programs, called ‘sketches’, which run on the Uno microcontroller. The language is based on C++, but some hardware abstraction and specific libraries are included. Figure 13: An example Arduino sketch in the proprietary IDE The purpose of the microcontroller, and therefore the code on the Arduino Uno, for this project is to: 1. Read the data from the GPS receiver 2. Process this data into a String of a specific, recognisable format 3. Save the modified data to a microSD card 4. Send the modified data to the Trintel SMART platform cloud via the AirLink modem The design processes used to achieve each of these goals is now discussed. The Arduino microcontroller code used to perform all of these functions can be viewed in its entirety in Appendix K. 27 Adafruit provide a software library for use with their Ultimate GPS Logger Shield product, which is supposed to help users read data from the GPS receiver quickly and easily. Whilst it does allow the user to get functional GPS readings with only about an hour or so of work, the author found the code to be very rigid. The TinyGPS library, developed by Mikal Hart and investigated more fully in section 2.8, made this step a much simpler process when some customisation is desired. Please refer to Figure 14 for a simplified visual explanation of this process. Figure 14: A simple flowchart representation for reading the GPS receiver The first step was defining the baud rate for the serial connection between the Arduino microcontroller and the GPS receiver as 9600 baud. This value is given by Adafruit as the rate at which the GPS receiver transmits data. Next, a “new data” variable of type Boolean is defined, so that it can be determined whether the GPS object, as previously explained in section 2.8, has received any new data from the receiver. The data from the GPS receiver is then continuously polled for three seconds to check for new data. This time was chosen, because after some experimentation it was deemed that it was enough time to allow a significant movement to take place, but not so much as to belittle the accuracy of the routing data. After some testing was done, however, it was determined that a more energy efficient way to do this was to only poll the receiver for 1 second, and then put the device in a low-power mode for 2 seconds. This is discussed in section 6.1.3 on page 40. If the GPS receiver has new data available (which it should, as the receiver updates at a frequency of 1 Hz), the data is then passed to a post processing function. Once a new GPS sentence has been passed to the GPS object, it is ready to be processed. This is a simple step where the data is simply put in the correct format to include the correct modem command. The Arduino SD library is then used to save the data to a SD storage card. The program will assign a name for text file it is saving to by checking for any files already on the SD card, and simply iterating the number at the end of the name. This means that a new file is created every time the Arduino restarts, and simply stops files from becoming millions of lines in length. The string format for data saved to the SD card is as follows: [latitude] | [longitude] | [speed] | [time] <carriage return> The data is also sent to the modem, along with the appropriate command, in order to upload it via GSM to Trintel’s SMART platform. The commands used to communicate with the SMART platform are discussed in the following section, section 5.2. 28 Since the modem is connected to the microcontroller’s hardware UART, it is simply a matter of sending the data, in the correct format, to the serial output of the Arduino Uno. The format is similar to the format used when saving to SD card storage, minus the carriage return at the end, and inserted into an ASCII command. 5.2. Communicating with the Trintel SMART Platform In order to communicate with the AirLink GL6100 modem, the UART on the Uno had to be set up in a compatible manner. The settings used are shown in Figure 15. These mirrored the protocol used by the modem. Figure 15: The UART settings used for the Uno microcontroller Since data will never be transmitted at a rate faster than 1 Hz (as this is the maximum update rate of the chosen GPS receiver), a baud rate of 9600 is more than adequate, as shown by the calculations that follow. 𝑇𝑟𝑎𝑛𝑠𝑚𝑖𝑠𝑠𝑖𝑜𝑛 𝑏𝑖𝑡𝑠 = 1 𝑠𝑡𝑎𝑟𝑡 𝑏𝑖𝑡 + 8 𝑑𝑎𝑡𝑎 𝑏𝑖𝑡𝑠 + 1 𝑠𝑡𝑜𝑝 𝑏𝑖𝑡 = 10 𝑏𝑖𝑡𝑠 𝑇𝑟𝑎𝑛𝑠𝑓𝑒𝑟 𝑙𝑖𝑚𝑖𝑡 = 9600 = 960 𝑏𝑦𝑡𝑒𝑠 𝑝𝑒𝑟 𝑠𝑒𝑐𝑜𝑛𝑑 10 The data is converted into a concatenated String before being sent to the modem. This String is of the following format: [latitude]/[longitude]/[speed]/[time]. It is done this way because it allows all the information to be easily contained in a single variable when uploaded to the Trintel SMART platform. The different parts of the String take on the following sizes: [latitude]: 9 bytes o [longitude]: 9 bytes o Example: “18866570” (divide by 1000000 for degrees) [speed]: 4 bytes o Example: ”-33928463” (divide by 1000000 for degrees) Example: “49” (knots) [time]: 6 bytes o Example: “130956” (hhmmss) 29 This means that the data string’s total size can be calculated as follows: 9 + 9 + 4 + 6 = 28 𝑏𝑦𝑡𝑒𝑠 However, as explained in section 2.2 on page 6, the modem also requires an AWTDA command of a specific format in order to be able to transmit the data. The length of this command, when the previously discussed string is given as the data value, has a total length of 44 bytes, excluding the data string. This value could change depending on the length of the variable names chosen. This means that the total byte count is 28+44=72 bytes. Therefore, the data string can be transmitted to the modem at a rate of 1Hz with a baud rate of 9600, because it can transmit 9600 bits per second and this setup only requires 72*8=576 bits per second to be transmitted. The modem is operated via an extended selection of AT (attention) commands created by Trintel called AWTDA. This means that in order to send commands to the modem the microcontroller only has to send properly formatted ASCII text strings to the serial port. Trintel has set up the firmware on the modems so that sending data across the wireless network is a relatively simple process, as the modem is merely provided with a command and, if applicable, some data. The modem can even poll the device if such a command is sent from the Trintel platform, but for this project most of the commands are limited to data upload commands. These come in the following format: AT+AWTDA=d,"{assetID}.{path}",{number of data points},"{variable},{data type},{value}" The modem will always return a text string starting with “OK” if the command was executed successfully, or “ERROR” if not. 5.3. Web Application Overview The Trintel SMART platform allows data that is uploaded to the website to be presented in various ways. However, because of the amount of post-processing desired, such as sectioning and heat mapping, the platform is inadequate when it comes to displaying the data in a manner which is easily interpretable. It is still required in order to get the data from each logging device into the cloud, but it cannot be relied upon on its own. The processing of the data should not occur on the logging device itself, because battery life is such a primary concern and any extra processing impacts that negatively. The algorithms also need to be able to take all the data in the data store into account. The web application also requires different user levels, in order to specify the administrative rights only some users have as well as who has access to potentially sensitive data. The SMART platform does not allow the implementation of different user levels. The conclusion is that, based on the limited customisation options offered by the Trintel platform, the battery life concerns of the logging device and the requirement for different user levels, that a web application should be developed specifically for this project, in order to accommodate all the requirements, as explained in section 3.3.2 on page 18. The application has three major components, namely login, map display and data management. These components are briefly discussed in sections 5.3.1 to 5.3.3, but 30 please refer to the user manual in Appendix D for an in-depth explanation of every section of the web application along with screenshots. 5.3.1. Login Page The login page has a very simple purpose: allowing users to log in to the web application. Users will be greeted with a simple welcome message and a brief explanation of the website. They will be asked to log in by either providing the username and password for an existing account, or by creating a new one. The web application will not allow a visitor to navigate to any of the other tabs without logging into an account first. Currently there is little security benefits in doing so, but it means that there is a system in place which can be upgraded to facilitate different account permission levels, or so that it may be tracked who uploaded which data. 5.3.2. Map Display Page The map display page is where all the routing data will be displayed via a map widget. The widget is powered by OpenStreetMap and is implemented using the Leaflet.JS library, for reasons explained in section 2.6 on page 11. 5.3.3. Data Management Page The data management page is where files are uploaded manually to the web application’s data store. It is implemented so that files can simply be ‘dragged and dropped’ into a designated area, and the application will read the files and update its contents into the data store, after applying the proper post processing, such as sectioning, to it. The map is then populated using the route data in the data store. 5.4. Sectioning routes The data is to be presented in manner that can be likened to a so-called “heat map”. This means that the colour and colour intensity of the data, as displayed on the map, will represent the amount of traffic it has generated. In order to be able to present data in such a manner, it has to be divided into sections. These sections will then count traffic that crosses it, and this number will be stored with the section in order to represent it in a sensible manner. Please refer to Figure 16 on page 33 for a one page flow chart of the process, as it is now explained. In order to section the data, a temporary segment is created first. The starting point of the first segment of the data set, or file, is simply the first coordinate that is read into the database. For any other segment it is the first coordinate that is read into the database after a previous segment has been finalised. The program will then continue to read coordinates into a temporary array, chronologically from the same data set, and measure the distance from the starting point each time. This is done by using the haversine formula, as explained in section 2.7.2 on page 14 of this report. The value for R which is used is the earth’s mean radius (6371.0 km, according to NASA [75]). The end point of the temporary segment is defined when either the end of the data set is reached or if the coordinate being added to the database is more than 20 meters from the starting point of that segment, whichever occurs first. The ‘Least Squares Method’, 31 as described in section 2.7.1, is then used to determine a straight line that best represents this temporary collection of latitude and longitude coordinates. The next step is to calculate whether the best fit line of the data intersects the bounding boxes of any other predefined sections, and by how much. For more information on how bounding boxes are generated, and on how it is determined whether a line does in fact cross any bounding boxes, please refer to sections 5.5 (‘Bounding Boxes’) and 5.6 (‘Intersections’) that follow. If the straight line segment does intersect with any other sections, the ratio of the line segment within that particular section’s bounding box is calculated. This ratio is then used to update both the section’s average position and traffic count appropriately. The average position of the section is updated by weighing the intruding segment’s average position, as determined by the line of best fit, based on the segment’s ratio within in the section and that section’s traffic count. For example, if 0.65 of the segment is within the bounding box, and the section has a traffic count of 4.3, the position of the section’s start and end points will be calculated as follows: 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑛𝑒𝑤 = = Or, in general terms: 4.3 ∙ 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑜𝑙𝑑 0.65 ∙ 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑠𝑒𝑔𝑚𝑒𝑛𝑡 + 4.3 + 0.65 4.3 + 0.65 (4.3 ∙ 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑜𝑙𝑑 ) + (0.65 ∙ 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑠𝑒𝑔𝑚𝑒𝑛𝑡 ) (4.3 + 0.65) 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑛𝑒𝑤 = (𝑐𝑜𝑢𝑛𝑡 ∙ 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑜𝑙𝑑 ) + (𝑟𝑎𝑡𝑖𝑜 ∙ 𝑝𝑜𝑠𝑖𝑡𝑖𝑜𝑛𝑠𝑒𝑔𝑚𝑒𝑛𝑡 ) 𝑐𝑜𝑢𝑛𝑡 + 𝑟𝑎𝑡𝑖𝑜 (4) (5) (6) The aim of redefining the average position of every section when a person moves through it is to, with time, generate sections that truly represent the road and the user’s movement. In a similar vein, the traffic count of the section is also updated with the ratio of the segment that is within that section. The start and end points of the ratio of the segment that is within a section is noted for future reference. The process described up to this point is continued until all the section with which the segment intersects has been identified. Referring to the start and end points of the ratios within sections, it can be identified which parts of the segment is not within a section. The remainder of the section is then used to generate a new section. This also occurs when the segment does not intersect with any sections. First, a new section ID is generated. This is done by checking the database for previous sections. If no other sections exist, i.e. this is the first section generated on the entire map, the section ID ‘1’ is generated. Otherwise, the section ID is calculated by incrementing the ID of the previously generated section by 1. The bounding box for that section is generated, as described in the “Bounding Boxes” subsection that follows, and then the section is inserted into the database. Its average position will be equal to that of the line segment used to generate it. 32 Figure 16: The process of sectioning data 33 5.5. Bounding Boxes Route sections should be defined in a manner which allows the program to detect when route segments are in fact on the same path. People will not be moving on exactly the same route, even when walking on the same pathway or sidewalk, so there needs to be some room for variation. Sidewalks, in South Africa and the United States of America, are generally between 1.5 and 2.0 meters in width [76][77]. As such, it makes sense to give the bounding box a reach of 1.5 meters on either side of the line, as explained by Figure 17, in order to make sure that all routes on the same sidewalk are consolidated to a single section. Figure 17: Bounding box representation The bounding box is generated by calculating the equations that describe the short lines of the box, as visualised in Figure 17, with different values of b: 𝑦 = 𝑚𝑥 + 𝑏 (7) Where m represents the slope of the line, b represents the longitude intercept of the line, and x and y represent the latitude and longitude, respectively, of each coordinate. The slope for these short lines can easily be obtained because they are perpendicular to the section line. This means that the slope of the short lines, m1, can be derived from the slope of the section line, m0, which is already known, via the following formula: 𝑚1 = −1 𝑚0 (8) This is true for the slopes of all perpendicular lines [78][79]. This is then used, together with the start and end coordinates of the section line, in the linear equation above to determine the longitude intersections for each line, namely b1 and b2. This then provides complete definitions for both the short sides of the bounding box, given that it is known how long they should be (which it is – 1.5 meter to either side of the section line). The Pythagorean Theorem can be used to calculate the distance between two points on a coordinate grid by drawing a line between them and regarding it as the long side of a right triangle, as shown in the following figure.[80] From the preceding figure it is clear that the distance between the two coordinates is equal to the length of the long side of the right triangle, which may be calculated from Pythagoras’ Theorem as follows: 𝑐 2 = 𝑎2 + 𝑏 2 (9) ∴ 𝑑 = (𝑥2 − 𝑥1 )2 + (𝑦2 − 𝑦1 )2 ( 10 ) Where d represents the distance between the two coordinates, and 𝑥𝑖 and 𝑦𝑖 represent the latitude and longitude, respectively, of each coordinate. 2 34 The latitude and longitude coordinates for each of the four corners of the bounding box can now be calculated, since the start and end points of the section line are also on the lines that make up the short sides of the bounding box. This means that, for the preceding distance formula, the distance and the latitude and longitude for one of the coordinates is known. The slope can also be used to eliminate a variable from the distance formula, as follows: 𝑦2 − 𝑦1 𝑚1 = ( 11 ) 𝑥2 − 𝑥1 ∴ 𝑦2 = 𝑚1 (𝑥2 − 𝑥1 ) + 𝑦1 ( 12 ) Therefore, the distance equation may be simplified: 𝑑2 = (𝑥2 − 𝑥1 )2 + (𝑚1 (𝑥2 − 𝑥1 ) + 𝑦1 − 𝑦1 )2 )2 ( 13 ) 2 = (𝑥2 − 𝑥1 + (𝑚1 (𝑥2 − 𝑥1 )) = (𝑥2 − 𝑥1 )2 + 𝑚2 (𝑥2 − 𝑥1 )2 = (1 + 𝑚2 )(𝑥2 − 𝑥1 )2 𝑑2 ∴ = (𝑥2 − 𝑥1 )2 1 + 𝑚2 𝑑 ∴ 𝑥2 = 𝑥1 ± ( 14 ) √1 + 𝑚12 Here x2 represents the latitude coordinate of the corner. x1 represents the latitude of either start or end point of the section line, depending on which corner is being calculated. The second term of the final equation is either positive or negative depending on which corner is being calculated. The longitude is calculated by substituting this latitude value into the linear equation for the straight line of the short side of the bounding box that is currently applicable. Sections are displayed with and without their borders in Figure 18 as a simple visual example. Figure 18: A simple example of sections with (left) and without (right) their bounding boxes displayed 5.6. Intersections Please refer to the flowchart in Figure 16 on page 33 as a supplement to the following description. Once the straight line approximation has been made for a potential new section, the program compares its position to that of all the previously generated sections. Any 35 existing sections that are close enough to the temporary section for a possible intersection are now identified. The first step in this identification process is to search the database for only those previously generated sections that are close enough for the line to potentially intersect with the section’s bounding box. This preliminary round of elimination is there so that the line is only tested against the remaining few sections for intersections with their bounding boxes, and not against all the sections in the database. This elimination is done because the mathematics required to calculate whether two line segments intersect is relatively complex and rather computationally expensive if it has to be done for (potentially) thousands of sections. This step is simply there to keep the time needed to import a new set of routes to a minimum. The idea is expressed visually in Figure 19, after which a detailed explanation of the process follows. Figure 19: Minimum distance for possible intersections The furthest the centre of a line segment can be from the centre of a section while the possibility of that line segment intersecting the section’s bounding box remains is now calculated below. A reminder that the bounding box of a section totals 7m in width, and around 20m in length. 𝑑 = 10 + √102 + 3.52 = 20.5948 𝑚 The aforementioned calculation can be broken down as follows: ( 15 ) d is the maximum distances between the two centres, or the distance between points F and H in the preceding figure. 10 is the approximate distance between the segment’s centre and one of its end points, or the distance between points H and C, or H and G, in the preceding figure. The √102 + 3.52 term represents the distance from the centre of a section’s bounding box to one of its corners, or the distance between points F and C in the preceding figure. The 2nd term of the sum is calculated by using Pythagoras’ theorem on the right angled triangle that can be created with its longest side between points F and C. The triangle AEC, in Figure 20, explains this idea visually. 36 Figure 20: Explaining this application of Pythagoras' theorem By only looking at the sections that have centres within d metres of the segment centre, as illustrated by the circle in Figure 19, all these remaining sections have a chance of intersecting with the line segment. Not all of them do, however, and further calculations are required. The next step is to determine which of these remaining sections’ bounding boxes are in fact intersected. This is done by making use of the so-called ‘orientation method for determining intersections’ [42], as explained in section 2.7.3 on page 15. The approximated straight line is tested against each of the borders of the bounding box of each of the sections within the determined distance for possible intersections. A visual example of how an established section, with a single traffic count, would be shifted when it is partially intersected by a newly inserted section can be found in Figure 21. Figure 21: Example effect demonstrating a section (with count 1) being partially intersected. All distances are in metres. Based on the amount of boundaries intersected, the segment of the line that is within the bounding box of the particular section is now defined. In the case where two boundary lines are intersected, the points of intersection provide the start and end points of the segment. In the case where only one boundary is intersected, the closest point to the centre of the bounding box is taken as the one point of the segment, and the point of intersection as the other. The ratio of the line segment within the section bounding box is using calculated with the following formula: 𝑟𝑎𝑡𝑖𝑜 = 𝑙𝑒𝑛𝑔𝑡ℎ 𝑜𝑓 𝑠𝑒𝑔𝑚𝑒𝑛𝑡 𝑖𝑛 𝑏𝑜𝑢𝑛𝑑𝑖𝑛𝑔 𝑏𝑜𝑥 𝑡𝑜𝑡𝑎𝑙 𝑙𝑒𝑛𝑔𝑡ℎ 𝑜𝑓 𝑙𝑖𝑛𝑒 𝑠𝑒𝑔𝑚𝑒𝑛𝑡 ( 16 ) 37 5.7. Heat Mapping the Data In order to clearly differentiate between the traffic certain route sections generate, an approach similar to heat mapping is implemented. Each section is assigned a so-called heat level, based on the traffic that passed through it. There are 9 levels, defined as follows: Level 1: The section has only been passed through once. Level 2: The section has been passed through between 2 and 10 times. Level 3: The section has been passed through between 11 and 25 times. Level 4: The section has been passed through between 26 and 50 times. Level 5: The section has been passed through between 51 and 100 times. Level 6: The section has been passed through between 101 and 250 times. Level 7: The section has been passed through between 251 and 500 times. Level 8: The section has been passed through between 501 and 1000 times. Level 9: The section has been passed through more than 1000 times. The line that represents the section on the map is then modified according to the section’s heat level in terms of its weight and colour. Figure 22 is an example of this implementation, with each line having a lower heat level than the one before. There are different colour schemes available for the route data from people with different disabilities in order to be able to differentiate, for example, between route data from people with sight disabilities and people with walking disabilities. Figure 22: A visual example of the different section heat levels - from most traffic on the left to least traffic on the right 38 6. Implementation, Testing and Results 6.1. Power Usage and Battery Life This section discusses the power usage of the logging device, the expected battery life of the device and power saving steps taken to improve it. 6.1.1. Power Consumption The logging device’s power usage had to be tested, as the theoretical values cannot account for the combination of peripherals and the program run on the microcontroller. Since the battery provided a near-constant voltage of 9V, the current is what had to be measured in order to calculate the power using the formula P=V*I [57]. The methodology consisted of the following steps: 1. Both the AirLink GL6100 modem and the Sipex SP232ACP were disconnected from the microcontroller. This means that only the Arduino Uno and the Ultimate GPS Logger shield remained. 2. The Arduino Uno was switched on until it achieved a satellite fix. 3. A multimeter was set to its ammeter setting and placed in series between the positive pole of the 9V battery and the VIN pin on the Arduino Uno. 4. The current draw was measured and recorded over an extended period of time in order to avoid any anomalies. 5. The Sipex SP232ACP serial converter IC was re-attached to the Uno, and the current was again measured and recorded over an extended period of time. 6. The Sipex SP232ACP was disconnected from the Uno, and the AirLink modem was attached again. Then the current was recorded again in the same manner. 7. Lastly, the Sipex IC was reattached to the Uno whilst the modem was also connected, and the current draw was measured in the same way for the last time. Please refer to Table 3 for the results of these tests. Table 3: Power usage of the logging device Setup (with 9V battery) Arduino Uno and GPS Shield only (base setup) Base setup with Sipex IC Base setup with both Sipex IC and modem Average Current Draw 67mA Average Power Usage 0.603W 75mA 111mA – 143mA 0.675W 0.999W – 1.287W The power usage of the device is very clearly cyclical when the modem is connected. It hits a peak current, and then drops to a minimum, and then back to the peak, and so forth, at a rate of about 1Hz. This is in line with the frequency at which the new GPS data gets transmitted wirelessly. The swing between maximum and minimum current draw is only about 2mA when the modem is not connected. 39 6.1.2. Battery Life According to the datasheet, the Arduino Uno requires a minimum input voltage of 6V for the manufacturer to guarantee normal functionality. This means that, in terms of commercially available portable batteries, there are three obvious power supply solutions for this project, as discussed in section 4.2.4 on page 24. These options are now listed in Table 4, and are compared in terms of the battery life that can be expected if it is used as the solution in this project. This table is also revisited in the next subsection, after certain power saving techniques have been implemented. In order to determine the current required at 6V, the power that was tested in the preceding subsection for the full setups (between 0.999W and 1.287W) is reverted back to current using the formula I = P/V [57]. The expected battery life is then calculated by dividing the capacity, in milliamp-hours, by the current draw, in milliamps. This answer is in hours. Table 4: Battery comparison Solution 1x 9V Battery [72] 4x AA Alkaline [73] Batteries in series 4x AAA Alkaline [74] Batteries in series Voltage 9V 4 x 1.5V = 6V Current 111mA – 143mA 167mA – 215mA Capacity 450mAh 2500mAh Battery Life ~4.5 hours ~25 hours 4 x 1.5V = 6V 167mA – 215mA 1000mAh ~9 hours The preceding table makes it clear that the expected battery life can only meet the requirement of 12 hours continuous battery life, as set out in section 3.3.1 on page 17, when the setup consists of 4 1.5V alkaline AA batteries in series. Such a power supply setup does, however, provide more than double the minimum requirement in terms of battery life hours. 6.1.3. Power Saving After the power usage of the logging device was measured, steps were taken to improve the battery life of the unit. The GPS receiver frequency, which was originally set at the lowest frequency advertised by Adafruit at 1Hz, was set to an even lower update frequency of 0.333Hz. This was done by sending a command using the PMTK protocol specified by GlobalTop (the manufacturer of the actual GPS receiver chip) along with a newly generated checksum. The command looks as follows: $PMTK220,3000*3D The checksum follows the * symbol, and is calculated as the XOR of all the bytes between the * and $ symbols, written in hexadecimal. The 220 PMTK command specifies that it should adjust the period between updates to the value, in milliseconds, between the comma and the * symbol. An additional Arduino library called JeeLib [81] is used. This library was developed by JeeLabs – a weblog dedicated to what it calls “physical computing”, that is electronics that interact with the physical world through sensors [82]. The class primarily utilised is called “Sleepy”. This class has functions that allow the Arduino microcontroller to enter a low-power state for a set amount of time using the 40 Watchdog Timer. Since the GPS receiver is set to update at a frequency of once every 3 seconds, this provides a low-power delay in order to stop the microcontroller from checking the GPS receiver for new data quicker than it updates. The “loseSomeTime” function does just that, and it is used to provide a delay of about 2 seconds between GPS receiver checks. The JeeLib documentation does warn that the time delay is not always accurate, but over a testing period of 40 minutes the delays were always between 2 and 5 seconds. It is therefore accurate enough for this application. The current draw of the logging device, in a full setup (i.e. with all the peripherals connected), was measured again after this function was implemented along with the slower GPS receiver update frequency. The minimum current draw is now slightly lower at 98mA rather than 111mA, but it also stays there for longer. The current draw is at its low point, on average, for about 2 seconds out of every 3 second cycle. 2×0.098 1×0.141 + 3 )× 3 This means that the average power usage for such a setup is now ( 9= 1.011𝑊 instead of 1.143𝑊 – an improvement of 11.56%, without sacrificing functionality. 6.2. Average Section Positions The system currently used to determine the positions of sections has some clear advantages and drawbacks. The main drawback of this system is that it is heavily reliant on a high numbers of users for accuracy of data. Accuracy here refers the fact that there is no guarantee that a user is taking a sensible route – for example, someone might cross the road at a normally dangerous place because they wanted to greet someone on the other side and the road happened to be empty. Outlier data from situations like those are without much use, and in fact it may encourage incorrect assumptions. In order to combat potential issues in that vein, a system is implemented where the visibility of routes that have only a single count can be toggled easily on the map interface. This means that users can choose whether or not to view single count routes at all. As soon as a second user also takes a similar route, the likelihood of that route being a sensible one increases drastically. It was impossible to test the logging device with the high number of users that provide the ideal use case it was designed for during the development thereof, but it is expected that by averaging the section positions based on all routes that pass through it will result in accurate depictions of the routes. The major advantage of this method of route mapping is that the actual routes people use get logged, not where the map expects a route to be. For example, if many people really do cross the road at a certain place where there is no regulated crossing, it is useful to be able to display that so that someone might be able to interpret it as a place where a formal crossing is needed. Another example would be many people crossing a grass area, which could mean that it would be sensible to build a path there. 6.3. Bounding Boxes and Intersections The bounding boxes were originally designed to be 3m in width, and 10m in length, for reasons explained in section 5.5 on page 34. However, since there is a lot of 41 computational intensity involved in order to calculate whether or not two lines cross one another, the temporary sections are not assigned bounding boxes before determining whether they intersect other sections. This is because it would take a factor of 16 more processing power to check all four borders of the bounding box of the temporary section with those of the bounding boxes of all the sections which could possibly be intersected. Instead it was decided to, crudely, enlarge the bounding boxes of the sections to be 7m in width and only check whether the line of the temporary section crosses any of the established sections’ borders. This way, if a new section is in fact generated, its “actual” bounding box, with a width of 1.5m on either side of the line, cannot intersect with another section it is parallel to. This concept is explained simply in Figure 23, where the red rectangles represent the “actual” bounding boxes of the sections, and the blue rectangle represents the oversized bounding box used in order to eliminate the need for the temporary section’s bounding box. Figure 23: An explanation for the bounding box size choices It is clear that the actual bounding boxes of the sections cannot intersect if the temporary section did not intersect with the oversized bounding box originally. 6.4. Practical Data Flow There are two practical paths whereby the data can get from the logging device to the MongoDB database on the FreeMove website. The first, and preferred, data path involves the data being transmitted to the Trintel SMART platform via the modem. From there a system administrator can download the data in a semicolon separated format text file and upload it to the web application for post processing. Uploading the data is as simple as dragging and dropping the file on the appropriate area under the “Data Management” tab of the web application. The data is not very time sensitive, in the sense that this process only has to be done on a weekly or even monthly basis and takes seconds to complete, and as such this method is not as labour intensive as it might suggest. The alternative is to gather the data from the microSD storage card on the actual logging device. This method is meant merely as a backup for when the GPRS transmission fails, or if the user would like to use their own raw routing data for personal projects. The route 42 data text files can then also be uploaded to the web application, again simply by dragging and dropping it in the correct box. In order for the web application to be able to determine which coordinates have already been uploaded successfully, and which have not, each coordinate is also assigned a random number between 0 and 1000. This is done because it is possible for two people to have crossed the exact same coordinate, and as such the system cannot simply check whether a coordinate is already in the data store. However, it is exceptionally improbable that two people cross the exact same coordinate and get assigned the same random number. The random number generator is seeded by using the relatively random analogue voltage from an open pin. This means that a system administrator should always upload all the files from the SD card to the web application as soon as a logging device is returned, as this will guarantee that all data points are added to the data store. 6.5. Arduino Shield PCB Design Although the packaging of the FreeMove logging device was outside of the scope of this project, it is vital to the success of this project that the device can in fact be packaged in a way that allows in to be user-friendly to carry. This implies that the size of the device has to be minimal. Figure 24: The potential Arduino shield's PCB layout In an effort to demonstrate that the device complies with this requirement, a PCB layout was designed using the EAGLE (Easily Applicable Graphical Layout Editor) CAD (Computer Aided Design) program. The design is displayed in Figure 24. The PCB was designed in a manner that allows it to connect to an Arduino Uno as an expansion shield. This means that the device is already a single unit, and it only needs to be placed inside a sturdy case in order to protect the device from physical damage. The shield has been designed to have an overhang of 21mm, under which the battery pack may be fitted in order to reduce the logging device to a single physical unit. The AirLink GL6100 modem was taken apart in order to reverse engineer a schematic for it, 43 but the unit was too complicated for this. Instead, the unit was removed from all unnecessary packaging and measured. The resulting measurements were then used to make sure that there is appropriate space on the PCB shield in order to mount it on the shield. The wiring can then also be done in a way that bypasses the TTL to RS232 converter inside the modem, meaning that the converter between the microcontroller and the modem can be removed. If communication takes place at TTL voltage levels instead of converting it to RS232 levels by both the modem and the microcontroller, it should increase the battery life of the device as well as minimise unnecessary components that add bulk to the product. Please see Appendix J for the full schematic diagram of the design. 6.6. Panic button The Trintel SMART platform provides SMS and email notifications when an alert or event is triggered from the side of an asset. It was thought feature could be used to in order to implement some sort of ‘panic button’ on each device with relative ease. Figure 25: Process flow for potential panic button Users would simply supply a next of kin to whom the alert would be SMSed, along with the current coordinates of the user. This coordinate data would be transmitted in a format that allows smartphone users to simply click on a link which takes them to a Google Maps page that points to the location from where the stress signal is triggered. After trying to implement this feature, however, it became clear that it is currently not practically feasible. Firstly, the response time on the SMS events is poor. During testing, it would take anywhere between a few seconds and 15 minutes before an SMS was received. This is likely a fault on the behalf of the network operator, but the system needs to be reliably responsive before it can be used in such a way. Secondly, the Trintel platform only allows the position attributes of the asset to be sent. These coordinates have to be manually updated through the web platform, and cannot be changed from the logging device. These two stumbling blocks have currently halted the implementation of a panic button feature, but it could yet be implemented if they are addressed by Trintel and MTN. 44 7. Conclusion The prototype system developed during this project meets all the objectives specified at the start of it, as per Appendix B. These objectives are now listed and evaluated to confirm the success of the project. The development and implementation of a portable (battery powered) logging device to log transportation routes used by persons with disabilities. Testing has shown that the Arduino Uno based logging device provides acceptable accuracy of data, especially considering the post-processing that is applied to the routing data before it is displayed. The battery life of the device is also satisfactory, given that a solution comprising of four AA alkaline batteries, in a series setup, is used. The form factor of the current prototype is not ideal, and some improvements in this area can definitely made in future, but the packaging was outside the scope of this project. It is, however, conceivable that the entire product can be fitted into a welldesigned case of an acceptably small size. In short, this objective is met successfully by the prototype logging device developed during the project. The development and implementation of a Trintel-based user interface to collect, display and distribute route data. The Trintel SMART Platform is used to collect all the route data generated by the, potentially multiple, logging device(s). No data was ever lost while transmitting to the SMART platform during the testing phase of this project. The Trintel SMART platform has been deemed incapable of applying the post-processing techniques required to display the routing data in a manner that allows for effective interpretation of the data with relative ease. For this reason the displaying of data was redirected to a separate web application, but there it was implemented successfully – with results that are much more desirable than those achievable with the SMART platform’s built-in widgets. The Trintel platform is also used to distribute the data by allowing system administrators to download all the routing data of every logging device (or “asset”) in a semicolon separated text file. This file can then be uploaded to the FreeMove web application with minimal effort. The development and implementation of a stand-alone data visualisation tool to display route data on a map. The FreeMove web application draws lines in different colours and various weights on an accurate street map in order to show how much traffic each section generates, which means that interpreting the data is a very simple, visual process. The main objective of the project was to develop a system that allows a user to look at visualised data, and draw sensible conclusions from it about where funds should be spent for maximum gain. This objective is achieved by the FreeMove web application and, together with the mobile logging device prototype, the project as a whole has to be considered a success. It provides a platform from which, with some slight tweaking, a commercially viable product is definitely realisable. 45 8. References [1] W. Hartley, “Census: South Africans mostly a healthy nation | Health | BDlive.” [Online]. Available: http://www.bdlive.co.za/national/health/2012/10/30/censussouth-africans-mostly-a-healthy-nation. [Accessed: 28-Jul-2014]. [2] R. W. Pogge and The Ohio State University, “GPS and Relativity.” [Online]. Available: http://www.astronomy.ohio-state.edu/~pogge/Ast162/Unit5/gps.html. [Accessed: 30-Sep-2014]. [3] European Space Agency, “What is Galileo? / The future - Galileo / Navigation / Our Activities / ESA,” 2014. [Online]. Available: http://www.esa.int/Our_Activities/Navigation/The_future__Galileo/What_is_Galileo. [Accessed: 21-Oct-2014]. [4] Arainespace, “Galileo satellites experience orbital injection anomaly on Soyuz launch: Initial report,” 2014. [Online]. Available: http://www.arianespace.com/news-press-release/2014/8-23-2014.asp. [Accessed: 21-Oct-2014]. [5] K. Moskvitch, “Glonass: Has Russia’s sat-nav system come of age?,” BBC News, 2010. [Online]. Available: http://news.bbc.co.uk/2/hi/8595704.stm. [Accessed: 21Oct-2014]. [6] US Aeronautics and Space Engineering Boards and National Research Council Staff, The Global Positioning System: A Shared National Asset. 1997. [7] E. Magnuson and W. R. Doerner, “Atrocity in the skies: KAL Flight 007 shot down by the Soviets,” TIME Mag., vol. September , 1983. [8] William J. Hughes Technical Center, “Global Positioning System ( GPS ) Standard Positioning Service ( SPS ) Performance Analysis Report,” vol. 86, no. June, 2014. [9] National Marine Electronics Association, “NMEA 0183 Standard.” [Online]. Available: http://www.nmea.org/content/nmea_standards/nmea_0183_v_410.asp. [Accessed: 30-Sep-2014]. [10] “MTN-SA coverage maps - OpenSignal.” [Online]. Available: http://opensignal.com/networks/south-africa/mtn-sa-coverage. [Accessed: 21Sep-2014]. [11] A. Fendelman, “What is GSM? (Cell Phone Glossary Definition).” [Online]. Available: http://cellphones.about.com/od/phoneglossary/g/gsm.htm. [Accessed: 30-Sep-2014]. 46 [12] J. Patterson and The Ohio State University, “Interactive Arts Media I course 5140,” 2012. [Online]. Available: http://accad.osu.edu/~jpatters/740/images/Web App.png. [Accessed: 07-Oct-2014]. [13] D. Flanagan, JavaScript: The Definitive Guide, 5th ed. O’Reilly Media, Inc., 2006. [14] “node.js.” [Online]. Available: http://nodejs.org/. [Accessed: 06-Oct-2014]. [15] R. Soule and Cornell University, “Client-Side Scripting (JavaScript) [Part of CS 5142 course],” 2013. [Online]. Available: http://www.cs.cornell.edu/Courses/cs5142/2013fa/2013-1007-client-javascript1.pdf. [Accessed: 06-Oct-2014]. [16] N. Parlante and Stanford University, “CS101: Introduction to Computing Principles,” 2014. [Online]. Available: http://web.stanford.edu/class/cs101/. [Accessed: 06-Oct-2014]. [17] L. Cozzens, A. Kudler, I. Sulam, and Brown University, “JavaScript Tutorial,” 1998. [Online]. Available: http://cs.brown.edu/courses/bridge/1998/res/javascript/javascript-tutorial.html. [Accessed: 06-Oct-2014]. [18] “MongoDB.” [Online]. Available: http://www.mongodb.org/. [Accessed: 06-Oct2014]. [19] “Documentation - Meteor.” [Online]. Available: http://docs.meteor.com/. [Accessed: 15-Aug-2014]. [20] “JavaScript reference - JavaScript | MDN.” [Online]. Available: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference. [Accessed: 15-Aug-2014]. [21] A. Bhattacharjee, “NoSQL vs SQL – Which is a Better Option?,” 2014. [Online]. Available: https://www.udemy.com/blog/nosql-vs-sql-2/. [Accessed: 24-Oct-2014]. [22] P. Brown, “NoSQL Databases: An Introduction.” [Online]. Available: http://www.browniethoughts.com/2013/02/nosql-databases-introduction.html. [Accessed: 07-Oct-2014]. [23] “World’s Largest Professional Network | LinkedIn.” [Online]. Available: https://www.linkedin.com/. [Accessed: 07-Oct-2014]. [24] “Jaspersoft Business Intelligence.” [Online]. Available: https://www.jaspersoft.com/. [Accessed: 07-Oct-2014]. [25] “MongoDB – The Leading NoSQL Database.” [Online]. Available: http://www.mongodb.com/leading-nosql-database. [Accessed: 07-Oct-2014]. 47 [26] “Google Maps.” [Online]. Available: maps.google.com. [Accessed: 15-Aug-2014]. [27] “OpenStreetMap.” [Online]. Available: http://www.openstreetmap.org. [Accessed: 15-Aug-2014]. [28] “Google.” [Online]. Available: https://www.google.co.za/. [Accessed: 15-Aug-2014]. [29] “Google Maps JavaScript API v3.” [Online]. Available: https://developers.google.com/maps/documentation/javascript/basics. [Accessed: 15-Aug-2014]. [30] “‘Map Loads’ - Google Maps API — Google Developers.”[Online]. Available: https://developers.google.com/maps/faq#usage_mapload. [Accessed: 15-Aug2014]. [31] “Wikipedia, the free encyclopedia.” [Online]. Available: http://en.wikipedia.org/wiki/Main_Page. [Accessed: 15-Aug-2014]. [32] “Leaflet - a JavaScript library for mobile-friendly maps.” [Online]. Available: http://leafletjs.com/. [Accessed: 15-Aug-2014]. [33] “OpenLayers: Home.” [Online]. Available: http://openlayers.org/. [Accessed: 15Aug-2014]. [34] “OpenLayers Examples.” [Online]. Available: http://openlayers.org/dev/examples/. [Accessed: 15-Aug-2014]. [35] “OpenLayers API.” [Online]. Available: http://dev.openlayers.org/apidocs/files/OpenLayers-js.html. [Accessed: 15-Aug2014]. [36] A. Olivier and University of Stellenbosch, “The Least Squares Regression Model,” 2007. [Online]. Available: http://academic.sun.ac.za/mathed/174WG/LeastSquares.pdf. [Accessed: 17-Sep2014]. [37] S. M. Stigler, “Gauss and The Invention of Least Squares,” Ann. Stat., vol. 9, no. 3, pp. 465–474, 1981. [38] H. Abdi, “The Method of Least Squares,” pp. 1–7, 1974. [39] Movable Type Scripts, “Calculate distance and bearing between two Latitude/Longitude points using haversine formula in JavaScript.” [Online]. Available: http://www.movable-type.co.uk/scripts/latlong.html. [Accessed: 18Sep-2014]. 48 [40] Doctor Rick, “Deriving the Haversine Formula,” The Math Forum, 1999. [Online]. Available: http://mathforum.org/library/drmath/view/51879.html. [Accessed: 18Sep-2014]. [41] “Latitude & Longitude Haversine Formula.” [Online]. Available: http://www.longitudestore.com/haversine-formula.html. [Accessed: 18-Sep-2014]. [42] P. Prosser and Glasgow University, “Geometric Algorithms,” 2000. [43] M. Hart, “TinyGPS | Arduiniana.” [Online]. Available: http://arduiniana.org/libraries/tinygps/. [Accessed: 30-Sep-2014]. [44] W. Greiman, “SdFat Arduino Library.” . [45] R. H. Katz, “EECS150: UART Design,” 2000. [46] I. Poole, “RS-232 Voltage Levels | RS232 Signals | Radio-Electronics.Com.” [Online]. Available: http://www.radioelectronics.com/info/telecommunications_networks/rs232/signals-voltageslevels.php. [Accessed: 30-Sep-2014]. [47] Gdansk University of Technology, “Exercise 8 - Port RS-232.” [Online]. Available: http://www.ue.eti.pg.gda.pl/fpgalab/zadania.spartan3/zad_rs232_en.html. [Accessed: 30-Sep-2014]. [48] R. Kochhar and University of Wisconsin, “ASCII Table: 7-bit,” 2008. [Online]. Available: http://www.neurophys.wisc.edu/comp/docs/ascii/. [Accessed: 09-Oct2014]. [49] “RS Comp - Buy Arduino UNO R3.” [Online]. Available: http://za.rsonline.com/web/p/processor-microcontroller-development-kits/7154081/. [Accessed: 29-Jul-2014]. [50] “Netram Technologies - buy arduino uno.” [Online]. Available: http://netram.co.za/1009-arduino-uno-r3.html. [Accessed: 29-Jul-2014]. [51] “Hobbytronics. buy Arduino UNO.” [Online]. Available: http://www.hobbytronics.co.za/p/20/arduino-uno. [Accessed: 29-Jul-2014]. [52] “MicroRobotics - buy Arduino UNO R3.” [Online]. Available: https://www.robotics.org.za/index.php?route=product/product&path=20_67&prod uct_id=50. [Accessed: 29-Jul-2014]. [53] “Arduino Uno.” [Online]. Available: http://arduino.cc/en/Main/ArduinoBoardUno. [Accessed: 29-Jul-2014]. 49 [54] “3.3V Conversion | Arduino Tips, Tricks, and Techniques | Adafruit Learning System.” [Online]. Available: https://learn.adafruit.com/arduino-tips-tricks-andtechniques/3-3v-conversion. [Accessed: 29-Jul-2014]. [55] “LM1117/LM1117I 800mA Low-Dropout Linear Regulator (Rev. M) - lm1117-n.pdf.” [Online]. Available: http://www.ti.com/lit/ds/symlink/lm1117-n.pdf. [Accessed: 29Jul-2014]. [56] “Arduino Power Consumption - Gadget Makers’ Blog.” [Online]. Available: http://gadgetmakersblog.com/arduino-power-consumption/. [Accessed: 29-Jul2014]. [57] D. Silverman, “Energy Units and Conversions.” [Online]. Available: http://www.physics.uci.edu/~silverma/units.html. [Accessed: 29-Jul-2014]. [58] “BeagleBoard.org - black.” [Online]. Available: http://beagleboard.org/black. [Accessed: 29-Jul-2014]. [59] E. Brown, “BeagleBone hops up to 1GHz. Drops price to $45. Woof! · LinuxGizmos.com,” 2013. [Online]. Available: http://linuxgizmos.com/beagleboneblack-speeds-up-to-1ghz-drops-price-to-45-dollars/. [Accessed: 28-Jul-2014]. [60] “XE Currency Converter - Live Rates.” [Online]. Available: http://www.xe.com/currencyconverter/. [Accessed: 30-Jul-2014]. [61] “BeagleBone Black | MircoRobotics.” [Online]. Available: https://www.robotics.org.za/index.php?route=product/product&path=20_201&pro duct_id=611. [Accessed: 20-Sep-2014]. [62] “BeagleBone Black | Arch Linux ARM.” [Online]. Available: http://archlinuxarm.org/platforms/armv7/ti/beaglebone-black. [Accessed: 30Jul-2014]. [63] “POWER | FAQs | Raspberry Pi.” [Online]. Available: http://www.raspberrypi.org/help/faqs/#power. [Accessed: 20-Sep-2014]. [64] “Generic Raspberry Pi Model B | Buy Online in South Africa | TAKEALOT.com.” [Online]. Available: http://www.takealot.com/raspberry-pi-modelb/PLID28026129. [Accessed: 20-Sep-2014]. [65] “Raspberry Pi - Model B - Netram Technologies.” [Online]. Available: http://netram.co.za/1714-raspberry-pi-model-b.html. [Accessed: 20-Sep-2014]. [66] Texas Instruments, “MSP-EXP430G2.” [Online]. Available: http://www.ti.com/ww/en/launchpad/launchpads-msp430-mspexp430g2.html#tabs. 50 [67] “RS-Components: TI MSP430 Development Board.” [Online]. Available: http://za.rs-online.com/web/p/processor-microcontroller-developmentkits/7122649/. [68] “How Much Power Does MSP430 / TI Launchpad Use?,” 2011. [Online]. Available: http://www.elperfecto.com/2011/01/08/how-much-power-does-msp430-tilaunchpad-use/. [Accessed: 26-Oct-2014]. [69] A. Allan, “Which Board is Right for Me?,” MakeZine. [Online]. Available: http://makezine.com/magazine/make-36-boards/which-board-is-right-for-me/. [Accessed: 26-Oct-2014]. [70] “Overview | Adafruit Ultimate GPS Logger Shield | Adafruit Learning System.” [Online]. Available: https://learn.adafruit.com/adafruit-ultimate-gps-loggershield/overview. [Accessed: 28-Jul-2014]. [71] “Arduino Radiation Sensor Shield.” [Online]. Available: http://microcontrollershop.com/product_info.php?products_id=5035. [Accessed: 27-Oct-2014]. [72] “Energizer 522 Datasheet,” pp. 1–2. [73] “ENERGIZER E91 Datasheet,” pp. 1–2. [74] Energizer, “ENERGIZER E92 Datasheet,” pp. 1–2. [75] NASA, “Earth Fact Sheet.” [Online]. Available: http://nssdc.gsfc.nasa.gov/planetary/factsheet/earthfact.html. [Accessed: 18Sep-2014]. [76] CSIR, “Roads : Geometric design and layout planning.” [77] U.S. Department of Transportation and Federal Highway Aministration, “Chapter 4 - Sidewalk Design Guidelines and Existing Practices - Sidewalks - Publications - Bicycle & Pedestrian Program - Environment - FHWA.” [Online]. Available: http://www.fhwa.dot.gov/environment/bicycle_pedestrian/publications/sidewal ks/chap4a.cfm. [Accessed: 18-Sep-2014]. [78] “Slope: Parallel and Perpendicular Lines.” [Online]. Available: http://www.purplemath.com/modules/slope2.htm. [Accessed: 18-Sep-2014]. [79] “Slope of Parallel and Perpendicular Lines.” [Online]. Available: http://www.algebralab.org/lessons/lesson.aspx?file=geometry_coordparallelperp endicular.xml. [Accessed: 18-Sep-2014]. [80] “The Distance Formula.” [Online]. Available: http://www.purplemath.com/modules/distform.htm. [Accessed: 18-Sep-2014]. 51 [81] “JeeLib: Introduction.” [Online]. Available: http://jeelabs.net/pub/docs/jeelib/. [Accessed: 08-Oct-2014]. [82] “JeeLabs.” [Online]. Available: http://jeelabs.org/. [Accessed: 08-Oct-2014]. [83] A. Bogomolny, “The Law of Cosines (Cosine Rule).” [Online]. Available: http://www.cut-the-knot.org/pythagoras/cosine.shtml. [Accessed: 18-Sep-2014]. [84] S. Hartke and University of Nebraska–Lincoln, “Spherical Law of Cosines,” pp. 1– 4, 2011. [85] H. Whitey, Great Moments in Mathematics (before 1650). 1983, pp. 29–32. [86] D. E. Joyce and Clark University, “Measurement of angles.” [Online]. Available: http://www.clarku.edu/~djoyce/trig/angle.html. [Accessed: 18-Sep-2014]. [87] M. van ’t Hooft, “Performance: Vincenty vs Haversine vs Sferical Law of Cosines Distance Calculations,” 2013. [88] “Intel® 22 nm Technology.” [Online]. Available: http://www.intel.com/content/www/us/en/silicon-innovations/intel-22nmtechnology.html. [Accessed: 21-Sep-2014]. [89] Texas Instruments, “CMOS Power Consumption and C pd Calculation,” no. June, 1997. 52 Appendix A: Project Planning Schedule 53 Appendix B: Project Specification The project specifications, as agreed upon between the author and Mr Arno Barnard, are as follows: 1. The development and implementation of a portable (battery powered) logging device to log transportation routes used by persons with disabilities. 2. The development and implementation of a Trintel-based user interface to collect, display and distribute route data. 3. The development and implementation of a stand-alone data visualisation tool to display route data on a map. These specification can be expanded in to functional specifications, interfaces and performance, as is done below. Functional Specification The system consists of a portable route logging device, a Trintel-based web portal that captures and distributes the route data, and a web application that displays the route data. Route data is transmitted to the Trintel-based web portal via a GSM modem. The route data is downloaded from the web portal in a semicolon separated text file, and uploaded onto the web application. The web application stores all uploaded route data in a MongoDB data store. Interfaces The mobile route logging device is based on an Arduino Uno, which can be programmed via its USB connection. The AirLink GL6100 GSM modem communicates via RS232 serial. The visualised route data can be viewed on the FreeMove web application. The raw route data can be viewed on the Trintel web portal, or accessed directly from the micro-SD storage card in the mobile logging device. The mobile logging device requires a power supply which can provide 200mA current at a voltage of between +6V and +12V. Performance 1 The mobile logging device updates its position at a rate of 3Hz. The average power usage of the mobile logging device is between 1W and 1.3W. The mobile logging device has an average expected battery life of 25 hours when using a AA battery solution with four batteries in series. No data was lost in transmission between the mobile logging device and the Trintel web platform during the testing phase of the project. The dimensions of the logging device are currently as follows: o The Arduino Uno, along with the GPS and micro-SD shield, has maximum dimensions of 78mm x 53mm x 21mm. o The RS232 to TTL converting IC has maximum dimensions of 59mm x 41mm x 12mm. o The AirLink GL6100 GSM modem has maximum dimensions of 67mm x 51mm x 25mm. If the specifically designed Arduino shield is implemented, the entire logging unit should have maximum dimensions of 98mm x 53mm x 33mm. 54 55 56 Appendix C: Outcomes Compliance Outcome Problem solving: Demonstrate competence to identify, assess, formulate and solve convergent and divergent engineering problems creatively and innovatively. Application of scientific and engineering knowledge: Demonstrate competence to apply knowledge of mathematics, basic science and engineering sciences from first principles to solve engineering problems. Engineering design: Demonstrate competence to perform creative, procedural and non-procedural design and synthesis of components, systems, engineering works, products or processes. Investigations, experiments and data analysis: Demonstrate competence to design and conduct investigations and experiments. Engineering methods, skills and tools, including Information Technology: Demonstrate competence to use appropriate engineering methods, skills and tools, including those based on information technology. Professional and technical communication: Demonstrate competence to communicate effectively, both orally and in writing, with engineering audiences and the community at large. Independent learning ability: Demonstrate competence to engage in independent learning through well-developed learning skills. Where is this outcome achieved? Throughout this entire report. Sections 2.8, 4, 5, 6 and 7. Sections 4, 5 and 6. Sections 2, 6 and 7. Sections 2, 3, 4, 5, 6 and 7. Throughout this entire report, but also during my weekly meetings with my project supervisor and our regular email communication. Throughout this entire report, but specifically in section 2. 57 Appendix D: FreeMove User Manual Logging In Start the FreeMove web application by using a web browser to navigate to freemove.meteor.com. Here you will find the welcome page, as shown in Figure 26: The FreeMove welcome page. Figure 26: The FreeMove welcome page To log in, click the “sign in / up” button in the top right corner. Here you can choose to either sign into a previously created account with the correct username and password, or you can create a new account. Figure 27: Signing into a new or existing FreeMove account The web application will not allow you to navigate away from this main page unless you log into an account, new or existing. Figure 28: The error message when a user tries to navigate the web application without logging in If you logged into a new or existing account successfully, the system will display an informative message stating so. Figure 29: A successful sign in message 58 Once you have logged in successfully, you can now navigate to the other tabs of the web application. To do so, click on the various links on the navigation bar. The details of how to use each section of the web application follows. Figure 30: The FreeMove navigation bar Managing Data In order to add coordinate sets to the data store, click on the “Manage data” tab in the navigation bar. This will take you to the data upload page. In order to add more data to the data store, simply drag and drop the route coordinate files into the designated file upload box, as shown in Figure 31: The data upload box on the FreeMove web application. Figure 31: The data upload box on the FreeMove web application The files can either be downloaded from Trintel’s platform, or copied directly from the microSD card found in a logging device. In order to get the data manually from the SD card of a logging device, simply connect the storage card to a computer, select all the text files on the card, and drag and drop them into the data upload box. No modification of the data files are needed. The web application will automatically determine which coordinates have not been uploaded yet, and only add those to the online data store. In order to get the data from Trintel’s platform, you will have to be registered on their system. If you are, point your web browser to platform.trintel.co.za, and log in with your username and password. Figure 32: The login page from Trintel's platform 59 After you have logged in, click on “Asset Management”. From here, navigate to the “Data” tab of the resulting page. The “Data” tab will display all the variables currently set up for each asset viewable under your account. Figure 33: The "Data" tab on the Trintel platform (Pay no attention to the actual data – many are still simply left over from previous testing exercises!) In order to download the history of the tracking data, select the appropriate variable and click on the “Export…” button to save the text file. This file can be uploaded directly to the FreeMove web application without any modification. The web application will, as before, automatically detect whether coordinates have already been added to the data store or not, and will only add those which have not been added before. Viewing the Map To view the routing data visualized on a map, click on the “Visualize data” tab on the navigation panel. Doing so will bring up an OpenStreetMap widget, with the current data in the data store visualized on it. Route sections are categorised based on how much traffic it generates. These different categories are represented using lines of varying colours and thicknesses. The categories for route traffic is defined as follows: Level 1: The section has only been passed through once. Level 2: The section has been passed through between 2 and 10 times. Level 3: The section has been passed through between 11 and 25 times. Level 4: The section has been passed through between 26 and 50 times. Level 5: The section has been passed through between 51 and 100 times. Level 6: The section has been passed through between 101 and 250 times. Level 7: The section has been passed through between 251 and 500 times. Level 8: The section has been passed through between 501 and 1000 times. Level 9: The section has been passed through more than 1000 times. The categorisation can be seen in Figure 34. 60 Figure 34: A visual example of the different section heat levels - from most traffic on the left to least traffic on the right The visualised data on the map will automatically be updated based on the coordinates in the data store. The user can also choose to view only data for persons with specific disabilities, or to exclude routes which have only been used once in order to eliminate data anomalies and to view only relevant data. Figure 35: Selecting which data is displayed 61 Appendix E: Cost of Components Item Cost Retailer 9V Alkaline Battery (Duracell) R33.70 RS Components Adafruit Ultimate GPS Logger Shield Arduino Uno MicroSD Storage Card (1gb) Sierra AirLink GL6100 GSM modem Sipex SP232ACP R781.00 MicroRobotics.org R269.00 R40.00 Free MicroRobotics.org WootWare.co.za Sponsored by MTN and Trintel Free Sponsored by Mr Arno Barnard TOTAL R1123.70 62 Appendix F: Motivation for Adafruit GPS Shield Table 5: Motivation for Adafruit Ultimate GPS Logger Shield Criteria Channels Antenna Physical dimensions Power usage Ease of use Price Extra features Motivation The PA6H GPS receiver module boasts 66 channels, which is on par with the leading industry standard for small form factor GPS receivers. The PA6H has a ceramic patch antenna with a sensitivity of -165dBm. 16 x 16 x 4.7 mm for the PA6H module, and 70 x 54 x 7 for the entire shield. However, the shield’s form factor means that it integrates with the Arduino Uno in a well thought out manner, and as such keeps the form factor of the entire device looking professional. This also means that the product maintains a smooth shape similar to that of a pack of playing cards, whereas a smaller GPS receiver might still have caused a less desirable shape. 20mA at 5V The unit really stands out in this department. The shield is manufactured specifically for use with the Arduino Uno microcontroller, and as such it is very easy to connect using headers. Adafruit also provide extremely detailed documentation and example code in order to get the receiver up and running as quickly as possible. R781.00 in South Africa Integrated SD card slot The GPS receiver shield provides a preconfigured micro-SD card slot out of the box. This means that no time has to be spent on the hardware side to find a storage solution, which is time saved. Integrated RTC battery The shield module has a RTC battery included, which the manufacturer claims has a 7 year lifetime. This battery greatly improves the time needed for the GPS receiver to find a satellite fix, as it allows the module to keep its internal clock running even when external power is removed. As such, the module does not have to take time to calculate the time from satellites. Prototyping area The shield has a 15x12 hole prototyping area, where extra components may be added. In the case of this project, it is an ideal place to put the TTL to RS232 converter IC. Fix LED The shield provides a clearly visible LED that blinks in order to show when a satellite is obtained. This is very helpful when debugging new code. Built in data logging The shield has the option of internal data logging. It is unlikely that this feature will be used, as it can only store data at a rate of 1/16 Hz, and store it on a 64 kB flash. Soft serial and direct connect The GPS receiver can be connected to the microcontroller using soft serial, which means that it leaves the Uno’s physical UART free for other peripherals (such as the modem, in this case). The direct connect option means that the GPS receiver can be debugged directly over USB, using a terminal program. 63 Appendix G: Calculating the Distance between Coordinates In order to calculate the distance between two coordinate points there are two methods that stand out: The Spherical Law of Cosines formula The haversine formula These methods have much in common, but also have unique traits that lead to different pros and cons. Both methods are used to measure the shortest distance between two points on the outside of a sphere, following a straight line on the outside of said sphere. The Spherical Law of Cosines formula is similar to the Euclidean Law of Cosines (also referred to as the Cosine Law) [83], and it makes sense to regard it first. Considering the triangle XYZ, with side lengths a, b and c, and corner angles α, β and γ. Figure 36: Triangle XYZ [84] The Cosine Law is a generalised form of the Pythagorean Theorem [85], where the angle γ is not necessarily 90⁰. The Cosine Law is defined as follows: 𝑐 2 = 𝑎2 + 𝑏 2 − 2𝑎𝑏 cos 𝛾 ( 17 ) If 𝛾 is at a right angle: 𝑐 2 = 𝑎2 + 𝑏 2 − 2𝑎𝑏 cos 90° = 𝑎2 + 𝑏 2 − 2𝑎𝑏 ∙ 0 = 𝑎2 + 𝑏 2 This is equal to Pythagoras’ Theorem. ( 18 ) In order to convert the Cosine Law to a spherical system, place the triangle XYZ on a sphere with a radius of 1 (also known as a unit sphere). A, B and C are the angles opposite lines a, b and c at the middle point of the sphere, denoted by O. Figure 37: Unit sphere coordinates [84] The lines a, b and c now also have the same length as the angle (in radians) at A, B and C, since the formula for the length of an arc is defined as 𝐴𝑟𝑐 = 𝑟𝜃 = 1 ∙ 𝜃 [86] ( 19 ) And therefore 𝐴𝑟𝑐 = 𝜃, or b = B, as long as the sphere has a radius of 1. Further, if Z is made the North point on the sphere, then a tangent plane can be drawn to it. The last 64 step is to extend the lines from O through X and Y until they meet this tangent plane at W and U. Figure 38: Final steps for spherical cosine law [84] Next, the length of UW is calculated by applying the Cosine Law to UZW. Lastly, the Cosine Law can be applied to the triangle OWU in order to calculate C, the angle between the rays from O to W and U, respectively. This leads to the Spherical Law of Cosines theorem [84]: cos 𝐶 = cos 𝐴 ∙ cos 𝐵 + sin 𝐴 ∙ sin 𝐵 ∙ cos 𝛾 ( 20 ) 𝛾 is the angle of UZW. A special derivation of this formula is known as the Haversine Formula. It is slightly more complex in that it is not simply a one-line calculation in Javascript, but it is regarded as more accurate than the Spherical Law of Cosines when working with distances where accuracy of a few meters is required. [39][40][41] This formula can be presented as three separate calculations [39]: a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2) ( 21 ) c = 2 ⋅ atan2( √a, √(1 − a) ) d = R ⋅ c Where φ and λ represent latitude and longitude, respectively, and R is the radius of the sphere in question. The distance between the two points is given by d. There is also a performance implication by using the Haversine Formula instead of the Spherical Law of Cosines, as is noted in Figure 39. Since the processing power on the server is more than capable of handling such calculations, however, it is of little consequence for this particular implementation – the distance calculation code will only run when data is being added to the database, and as such a few milliseconds, or even seconds, performance difference may be dismissed. The data in the following chart is presented in operations per second, with a higher number being better. Three different internet browsers were tested for more conclusive results. 65 Performance of distance calculations 900000 Operations per second 800000 700000 600000 500000 400000 300000 200000 100000 0 Chrome 37.0.2062 Haversine Formula Firefox 29.0 Internet Explorer 10.0 Spherical Law of Cosines Figure 39: Performance comparison of spherical distance calculation methods [87] It can be seen that using the Spherical Law of Cosines instead of the haversine formula would result in an increase in performance of between 20% and 30%, depending on which internet browser is used, but this performance impact can be ignored in favour of higher accuracy for this project. 66 Appendix H: Power Consumption versus Processor Speed Modern processors make use of transistors that switch at very high frequencies [88]. This transistor toggling, as it is sometimes called, directly influences the power consumption of the processor. The relationship can be described by the following formula: 𝑃 = 𝑎 ∙ 𝐶 ∙ 𝑉2 ∙ 𝑓 Where P represents the power consumption, and f the frequency of the transistor toggling. This implies a linear increase in power usage as the frequency of the capacitive toggling increases, and while this is not completely true in practice, the results very closely resemble this. The following figure is from a Texas Instruments document on CMOS power consumption, and it shows the ICC current versus frequency for their AHC00 integrated circuit. Figure 40: ICC versus Frequency for the TI AHC00 [89] Figure 40 shows that the relationship between frequency and power consumption is almost linear, even in practice, for transistors. This strongly suggests that a slower processor, for all the drawbacks it has, will be beneficial from a power usage point of view. 67 Appendix I: The Orientation Method The orientation of three points in a 2-dimensional space can be defined as either clockwise, counter-clockwise, or collinear, as shown in Figure 41(a), (b) and (c). Figure 41: (a) Counter-clockwise, (b) clockwise and (c) collinear orientation of 3 points [42] Two line segments, defined by points (p1, q1) and (p2, q2) respectively, intersect if and only if one of the following two conditions are true: 1. Condition 1 a. (p1, q1, p2) and (p1, q1, q2) have different orientations, and b. (p2, q2, p1) and (p2, q2, q1) have different orientations 2. Condition 2 a. (p1, q1, p2), (p1, q1, q2), (p2, q2, p1) and (p2, q2, q1) are all collinear, and b. The x-projections of (p1, q1) and (p1, q1) intersect, and c. The y-projections of (p1, q1) and (p2, q2) intersect Condition 1 results in two lines intersecting at some angle, whilst Condition 2 is true if the lines intersect in a collinear manner. This is shown in Figures Figure 42 and Figure 43. Figure 42: Intersecting line that satisfy Condition 1 [42] Figure 43: Intersecting collinear lines that satisfy Condition 2 [42] In order to determine the orientation of three points, the slope of sections (point1, point2) and (point2, point3) are required. The slope of a line segment can be calculated as follows: 𝑠𝑙𝑜𝑝𝑒 = (𝑦1 − 𝑦0 ) (𝑥1 − 𝑥0 ) ( 22 ) 68 In the context of this project, 𝑦𝑖 and 𝑥𝑖 represent the latitude and longitude of a coordinate, respectively. If the slope of the line segment (point1, point2) is defined as 𝜎 and that of the line segment (point2, point3) is defined as 𝜏 there are three possible outcomes when comparing the slopes: 1. 𝜎 < 𝜏 , or a counter-clockwise orientation 2. 𝜎 > 𝜏 , or a clockwise orientation 3. 𝜎 = 𝜏 , or a collinear orientation These outcomes are then used to determine whether either Condition 1 or Condition 2, as previously defined, are satisfied and the lines intersect. 69 Appendix J: Schematic for PCB Design 70 Appendix K: Arduino Uno Code 1 /* 2 ACKNOWLEDGEMENTS: 3 JeeLabs, for the power saving sleepy class <http://jeelabs.net/pub/docs/jeelib/classSleepy.html> 4 Jeremy Blum, for detailed Arduino tutorials that helped A LOT <http://www.jeremyblum.com/> 5 */ 6 7 8 #include <SoftwareSerial.h> 9 #include <TinyGPS.h> 10 #include <SD.h> 11 #include <Ports.h> 12 13 TinyGPS gps; 14 15 #define RXPIN 8 16 #define TXPIN 7 17 18 ISR(WDT_vect) { Sleepy::watchdogEvent(); } 19 SoftwareSerial ss(RXPIN, TXPIN); 20 const int chipSelect = 10; 21 File logfile; 22 long randnum; 23 24 void setup(){ 25 // Start the serial at 9600 baud rate 26 Serial.begin(9600); 27 ss.begin(9600); 28 // Set the GPS receiver update rate to 1/3Hz 29 PMTK_SET_UPDATE_3SEC; 30 31 Serial.println("FreeMove GPS tracking unit"); 32 Serial.println(); 33 Serial.print("Initializing SD card..."); 34 pinMode(10, OUTPUT); 35 // Check to see if SD card is present 36 if (!SD.begin(chipSelect)) { 37 Serial.println("Card failed, or not present"); 38 // don't do anything more: 39 return; 40 } 41 Serial.println(" card initialized."); 42 43 // Generate new file. Name iterates if exists. 44 char filename[15]; 45 strcpy(filename, "GPSLOG00.TXT"); 46 for (uint8_t i = 0; i < 100; i++) { 47 filename[6] = '0' + i/10; 48 filename[7] = '0' + i%10; 49 // create if does not exist, do not open existing, write, sync after write 50 if (! SD.exists(filename)) { 51 break; 52 } 53 } 54 // Open the file on SD card for writing 55 logfile = SD.open(filename, FILE_WRITE); 56 if( ! logfile ) { 71 57 Serial.print("Couldnt create "); 58 Serial.println(filename); 59 } 60 Serial.print("Writing to "); 61 Serial.println(filename); 62 63 // Seed the random generator from unused analogue pin 0 64 randomSeed(analogRead(0)); 65 } 66 67 void loop(){ 68 delay(100); 69 Sleepy::loseSomeTime(2000); 70 bool newData = false; 71 unsigned long chars; 72 unsigned short sentences, failed; 73 74 // For one second we parse GPS data and report some key values 75 for (unsigned long start = millis(); millis() - start < 1000;) 76 { 77 while (ss.available()) 78 { 79 char c = ss.read(); 80 if (gps.encode(c)) // Did a new valid sentence come in? 81 newData = true; 82 } 83 } 84 // If new data is received from GPS receiver 85 if (newData){ 86 long lat, lon; 87 unsigned long fix_age, time, date, speed, course; 88 unsigned long chars; 89 unsigned short sentences, failed_checksum; 90 91 // retrieves +/- lat/long in 100000ths of a degree 92 gps.get_position(&lat, &lon, &fix_age); 93 94 // time in hhmmsscc, date in ddmmyy 95 gps.get_datetime(&date, &time, &fix_age); 96 97 // returns speed in 100ths of a knot 98 speed = gps.speed(); 99 100 // course in 100ths of a degree 101 course = gps.course(); 102 103 // Generate random ID number 104 randnum = random(1000); 105 106 // Send command to modem over serial 107 Serial.print("AT+AWTDA=d,\"logger.stat\",1,\"info,string,"); 108 Serial.print(lat); 109 Serial.print("|"); 110 Serial.print(lon); 111 Serial.print("|"); 112 Serial.print(speed); 113 Serial.print("|"); 114 Serial.print(time); 115 Serial.print("|"); 116 Serial.print(randnum); 117 Serial.print("\""); 72 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 } 136} Serial.println(); // Log coordinate data to text file, if SD card present if (logfile) { logfile.print(lat); logfile.print("|"); logfile.print(lon); logfile.print("|"); logfile.print(speed); logfile.print("|"); logfile.print(time); logfile.print("|"); logfile.print(randnum); logfile.println(); logfile.flush(); Serial.println("Logged to SD card."); } 73 Appendix L: FreeMove Web Application Folder Structure Figure 44: Folder structure for the web application 74 Appendix M: FreeMove Web Application Code Client: HTML data.html 1<template name="data"> 2 <div align="center" style="margin-top: 5px"> 3 <p><em>To upload more data, please drag and drop the file(s) generated by the logging unit below.</em></p> 4 </div> 5 <div align="center" style="margin-top: 5px" id="dropbox"> 6 Drop files here 7 </div> 8</template> home.html 1 <template name="home"> 2 <div align="center" style="margin-top: 20px"> 3 <h1>Welcome to FreeMove.</h1> 4 <h4>Here data is added and visualized in order to provide a platform for effective resource planning.</h4> 5 {{#if loggedIn}} 6 <p><em>Welcome, <b>{{loggedIn.username}}</b>.</em></p> 7 {{else}} 8 <p><em>Please log in to continue.</em></p> 9 {{/if}} 10 </div> 11</template> index.html 1 <head> 2 <title>FreeMove</title> 3 <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet0.7.3/leaflet.css" /> 4 <script src="http://cdn.leafletjs.com/leaflet0.7.3/leaflet.js"></script> 5 </head> 6 <body> 7 </body> 8 9 <template name="layout"> 10 <div class="container"> 11 <header> 12 {{> nav }} 13 </header> 14 {{> yield}} 15 </div> 16</template> 17 18<template name='nav'> 19 <nav class="navbar navbar-default" role="navigation"> 20 <div class="container-fluid"> 21 <div class="navbar-header"> 22 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> 23 <span class="sr-only">Toggle navigation</span> 24 <span class="icon-bar"></span> 25 <span class="icon-bar"></span> 75 26 <span class="icon-bar"></span> 27 </button> 28 {{> navBrand}} 29 </div> 30 <div class="collapse navbar-collapse" id="bs-example-navbar-collapse1"> 31 <ul class="nav navbar-nav"> 32 {{> navItems}} 33 </ul> 34 <ul class="nav navbar-nav navbar-right"> 35 {{> loginButtons }} 36 </ul> 37 </div> 38 </div> 39 </nav> 40</template> 41 42<template name="navBrand"> 43 <a class="navbar-brand" href="{{ pathFor 'home' }}">FreeMove</a> 44</template> 45 46<template name='navItems'> 47 <li class="{{ activeIfTemplateIs 'home' }}"> 48 <a href="{{ pathFor 'home'}}">Home</a> 49 </li> 50 <li class="{{ activeIfTemplateIs 'map' }}"> 51 <a href="{{pathFor 'map'}}">Visualize data</a> 52 </li> 53 <li class="{{ activeIfTemplateIs 'data' }}"> 54 <a href="{{pathFor 'data'}}">Manage data</a> 55 </li> 56</template> map.html 1<template name="map"> 2 <div id="map-info"> 3 <p><em>Adjust which layers are visible using the tool in the top right corner of the map widget.</em></p> 4 </div> 5 <div id="map-canvas"></div> 6</template> Client: JavaScript home.js 1 var first = true; 2 3 Template.data.rendered = function () { 4 // Check for the various File API support. 5 if (window.File && window.FileReader && window.FileList && window.Blob) { 6 // Great success! All the File APIs are supported. 7 toastr.info('Your browser supports the HTML5 File APIs.', 'Good stuff'); 8 } else { 9 toastr.error('Your browser does not support the HTML5 File APIs.', 'Oh no'); 10 } 11 12 // Listen for files dropped to upload 76 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 var dropZone = document.getElementById('dropbox'); dropZone.addEventListener('dragover', handleDragOver, false); dropZone.addEventListener('drop', handleFiles, false); } Template.home.rendered = function () { if (first){ var displayed_in = false; var displayed_none = false; first = false; } Deps.autorun(function () { if (Meteor.user() && !displayed_in){ toastr.clear(); toastr.success("You have signed in succesfully.", "Hello."); displayed_in = true; displayed_none = false; } else if (!displayed_none) { toastr.clear(); toastr.info("No one is currently logged in.", ""); displayed_none = true; displayed_in = false; } }); } // Read in a new file function newRead(text, set) { var lines; // Check whether the data is generated by logger // (and therefore split by new lines) or by the // Trintel portal (and therefore split using ;s) var dataType = text.indexOf(";"); if (dataType == -1) { lines = text.split("\n"); } else { lines = text.split(";"); } // Previous coordinate var prev_lat = 0.0; var prev_lng = 0.0; // Section starting point var start_lat = 0.0; var start_lng = 0.0; // Section points var sec_lats = []; var sec_lngs = []; // Current section ID var current_sec_ID = 0; // Amount of generated sections, from current file var sec_count = 0; var ccc = 0; // Read in each line of the current file _.each(lines, function(line) { var split_line = line.split("|"); // Time format: hhmmss var time = parseFloat(split_line[3]); var timeslot; // Between 06h00 and 12h00 77 74 if (time >= 6000000 && time < 12000000) { 75 timeslot = 'A'; 76 } 77 // Between 12h00 and 18h00 78 if (time >= 12000000 && time < 18000000) { 79 timeslot = 'B'; 80 } 81 // Between 18h00 and 06h00 82 else { 83 timeslot = 'C'; 84 } 85 86 // Generate lat and lng values 87 var lat = parseFloat(split_line[0]) / 1000000; 88 var lng = parseFloat(split_line[1]) / 1000000; 89 90 // Read random ID for coordinate 91 var randnum = parseFloat(split_line[4]); 92 93 // Check if coordinate has been added before 94 var checker = Coordinates.findOne({ lat: lat, lng: lng, randnum: randnum}); 95 96 ccc += 1; 97 98 // Check that latitude and longitude are numbers 99 if (!isNaN(lat) && !isNaN(lng) && !checker) { 100 //console.log("Working"); 101 // Compare distance to previous section start 102 var sec_dist = distToPrev(lat, lng, start_lat, start_lng); 103 sec_dist = Math.abs(sec_dist); 104 105 // Point not in a previously generated section 106 if (sec_dist > 20) { 107 // If not first section for file, finalise previous section first 108 if (sec_count > 0) { 109 // Calculate average section line by using least squares method 110 111 // Declare some variables 112 var lat_sum = 0; 113 var lng_sum = 0; 114 var lat_mean = 0; 115 var lng_mean = 0; 116 var lat_sqrd = 0; 117 var pair_sqrd = 0; 118 119 for (var i = 0; i < sec_lats.length; i++) { 120 // Calculate the lat and lng sums 121 lat_sum += sec_lats[i]; 122 lng_sum += sec_lngs[i]; 123 124 // Calculate the sum of each pair multiplied 125 pair_sqrd += sec_lats[i] * sec_lngs[i]; 126 127 // Calculate the sum of lats squared 128 lat_sqrd += sec_lats[i] * sec_lats[i]; 129 } 130 131 // Calculate latitude and longitude means 78 132 lat_mean = lat_sum / sec_lats.length; 133 lng_mean = lng_sum / sec_lngs.length; 134 135 // Calculate the slope, m 136 var m = (pair_sqrd - (lat_sum * lng_sum / sec_lats.length)) / (lat_sqrd - (lat_sum * lat_sum / sec_lngs.length)); 137 138 // Calculate b = y_mean - m*x_mean 139 var b = lng_mean - (m * lat_mean); 140 141 // Form new line with lng = m*lat + b 142 var s_lng = m*sec_lats[0] + b; 143 var f_lng = m*sec_lats[sec_lats.length - 1] + b; 144 145 // Create start, end and centre points 146 var start_obj = { 147 lat: sec_lats[0], 148 lng: s_lng 149 }; 150 var finish_obj = { 151 lat: sec_lats[sec_lats.length - 1], 152 lng: f_lng 153 }; 154 var segment_centre = { 155 lat: (start_obj.lat + finish_obj.lat)/2, 156 lng: (start_obj.lng + finish_obj.lng)/2 157 } 158 159 160 161 // Calculate length of new line 162 var line_length = distToPrev(start_obj.lat, start_obj.lng, finish_obj.lat, finish_obj.lng); 163 164 // See if in another section's bounds 165 var in_bounds = false; 166 var intersections = 0; 167 var secs = Sections.find().fetch(); 168 _.each(secs, function(section) { 169 // Check whether the section is within reach before doing any calculations 170 var dist_to_centre = Math.abs(distToPrev(section.bounds.centre.lat, section.bounds.centre.lng, segment_centre.lat, segment_centre.lng)); 171 if(dist_to_centre < 22) { 172 //Find the four lines that define the bounding box 173 //Source: http://mathforum.org/library/drmath/view/53254.html 174 //For each of these lines: 175 //1. Get y = m2x + b2 176 //2. Subtract from current line to find intersection x (latitude): 177 // y - y = (m1 - m2)x + (b1 - b2) 178 // 0 = (m1-m2)x + (b1-b2) 179 // x = -(b1-b2)/(m1-m2) 180 //3. Get intersection y (longitude): y = mx+b 181 //4. See if point (x,y) is on the line section 79 182 // i.e. is start.lat < intersect_lat < end.lat ? 183 //5. Set in_bounds appropriately 184 185 // Get the four latlng intersections 186 var lat_short0 = -(b - section.short_bb.b0) / (m - section.short_bb.m); 187 var lat_short1 = -(b - section.short_bb.b1) / (m - section.short_bb.m); 188 var lat_long0 = -(b - section.long_bb.b0) / (m - section.long_bb.m); 189 var lat_long1 = -(b - section.long_bb.b1) / (m - section.long_bb.m); 190 191 var lng_short0 = m * lat_short0 + b; 192 var lng_short1 = m * lat_short1 + b; 193 var lng_long0 = m * lat_long0 + b; 194 var lng_long1 = m * lat_long1 + b; 195 196 // Use the orientation method to determine if intersections occur 197 // Source for algorithm: http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf 198 var hit; 199 var inters = []; 200 201 // Check short 0 202 hit = checkIntersection(start_obj, finish_obj, section.bounds.cnr1, section.bounds.cnr2); 203 if (hit) { 204 var temp_obj = { 205 lat: lat_short0, 206 lng: lng_short0 207 }; 208 inters.push(temp_obj); 209 210 } 211 212 // Check short 1 213 hit = checkIntersection(start_obj, finish_obj, section.bounds.cnr3, section.bounds.cnr4); 214 if (hit) { 215 var temp_obj = { 216 lat: lat_short1, 217 lng: lng_short1 218 }; 219 inters.push(temp_obj); 220 } 221 222 // Check long 0 223 hit = checkIntersection(start_obj, finish_obj, section.bounds.cnr1, section.bounds.cnr3); 224 if (hit) { 225 var temp_obj = { 226 lat: lat_long0, 227 lng: lng_long0 228 }; 229 inters.push(temp_obj); 230 } 231 232 // Check long 1 80 233 hit = checkIntersection(start_obj, finish_obj, section.bounds.cnr2, section.bounds.cnr4); 234 if (hit) { 235 var temp_obj = { 236 lat: lat_long1, 237 lng: lng_long1 238 }; 239 inters.push(temp_obj); 240 } 241 242 // If a section was intersected 243 if(inters[0]) { 244 var temp_seg; 245 in_bounds = true; 246 // If the line runs through a section 247 if (inters.length > 1){ 248 temp_seg = { 249 start: { 250 lat: inters[0].lat, 251 lng: inters[0].lng 252 }, 253 finish: { 254 lat: inters[1].lat, 255 lng: inters[1].lng 256 } 257 } 258 } 259 // If the line only intersects section once 260 else { 261 262 var distFromStart = distToPrev(start_obj.lat, start_obj.lng, section.bounds.centre.lat, section.bounds.centre.lng); 263 var distFromFinish = distToPrev(finish_obj.lat, finish_obj.lng, section.bounds.centre.lat, section.bounds.centre.lng); 264 if (distFromStart < distFromFinish) { 265 266 temp_seg = { 267 start: { 268 lat: inters[0].lat, 269 lng: inters[0].lng 270 }, 271 finish: { 272 lat: start_obj.lat, 273 lng: start_obj.lng 274 } 275 } 276 277 } else { 278 81 279 temp_seg = { 280 start: { 281 lat: inters[0].lat, 282 lng: inters[0].lng 283 }, 284 finish: { 285 lat: finish_obj.lat, 286 lng: finish_obj.lng 287 } 288 } 289 290 } 291 } 292 293 // Calculate ratio of segment in section 294 var ratio = distToPrev(temp_seg.start.lat, temp_seg.start.lng, temp_seg.finish.lat, temp_seg.finish.lng) / 295 distToPrev(start_obj.lat, start_obj.lng, finish_obj.lat, finish_obj.lng); 296 297 // Adjust section average position and count according to ratio 298 var temp_section = { 299 start: section.start, 300 finish: section.finish 301 } 302 var new_pos = calcNewPos(ratio, section.count, temp_seg, temp_section); 303 Sections.update( {_id: section._id}, 304 { $set: {start: new_pos.start, finish: new_pos.finish, count: section.count+ratio}}); 305 306 // Reset the lats array 307 sec_lats = []; 308 sec_lngs = []; 309 310 } 311 } 312 }) 313 // Intersects a previous section area 314 if (in_bounds) {} 315 //Does not intersect previous section sufficiently 316 else { 317 // Calculate bounding box 318 var new_bb = generateBB(start_obj, finish_obj, m); 319 320 // Create sections object 321 var section_obj = { 322 sec_ID: current_sec_ID, 323 start: start_obj, 324 finish: finish_obj, 325 bounds: new_bb.bb_obj, 326 short_bb: new_bb.short_obj, 82 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 knots 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 long_bb: new_bb.long_obj, count: 1 }; // Update sections database Sections.insert(section_obj); // Reset the lats array sec_lats = []; sec_lngs = []; } } // Set start of section start_lat = lat; start_lng = lng; // Update section points sec_lats.push(lat); sec_lngs.push(lng); if (sec_count == 0) { // Generate section ID var section_check = Sections.findOne({}); if(section_check){ current_sec_ID = section_check.sec_ID + 1; } else { current_sec_ID = 1; } } else { current_sec_ID += 1; } // Create coordinate object var coord_obj = { timeslot: timeslot, lat: lat, lon: lng, speed: parseFloat(split_line[2]), // unit: type: set: section: randnum: "A", set, current_sec_ID, randnum } // Push coordinate obj to database Coordinates.insert(coord_obj); // Update sections counter sec_count += 1; } // Point in the previously generated section else { // Update section points sec_lats.push(lat); sec_lngs.push(lng); // Create coordinate object 83 387 var coord_obj = { 388 timeslot: timeslot, 389 lat: lat, 390 lon: lng, 391 speed: parseFloat(split_line[2]), // unit: knots 392 type: "A", 393 set: set, 394 section: current_sec_ID, 395 randnum: randnum 396 } 397 398 // Push coordinate obj to database 399 Coordinates.insert(coord_obj); 400 } 401 } 402 }); 403} 404 405// Calculates the new avergae position of a section 406function calcNewPos(ratio, count, segment, section) { 407 var new_start = { 408 lat: ((segment.start.lat*ratio)+(section.start.lat*count))/(ratio+count), 409 lng: ((segment.start.lng*ratio)+(section.start.lng*count))/(ratio+count) 410 } 411 412 var new_finish = { 413 lat: ((segment.finish.lat*ratio)+(section.finish.lat*count))/(ratio+count), 414 lng: ((segment.finish.lng*ratio)+(section.finish.lng*count))/(ratio+count) 415 } 416 417 var new_pos = { 418 start: new_start, 419 finish: new_finish 420 } 421 return new_pos; 422} 423 424// Checks whether lines, defined by 2x start and end points, intersect 425// Uses getOrientation 426// Returns boolean result 427function checkIntersection(p1, p2, p3, p4){ 428 var dir1 = getOrientation(p1, p2, p3); 429 var dir2 = getOrientation(p1, p2, p4); 430 var dir3 = getOrientation(p3, p4, p1); 431 var dir4 = getOrientation(p3, p4, p2); 432 433 if (dir1 != dir2 && dir3 != dir4){ 434 return true; 435 } else { 436 return false; 437 } 438} 439 440// Calculate the orientation of line segment defined by 3 points 441// Return: 442// 0 - points are colinear 84 443// 1 - counterclockwise 444// 2 - clockwise 445function getOrientation (p1, p2, p3) { 446 var val = (p2.lng - p1.lng) * (p3.lat - p2.lat) 447 (p2.lat - p1.lat) * (p3.lng - p2.lng); 448 if (val == 0) { 449 return 0; 450 } else if (val > 0){ 451 return 1; 452 } else { 453 return 2; 454 } 455} 456 457// Generate the bounding box for a given line 458function generateBB(start_obj, finish_obj, m) { 459 // Calculate bounding box 460 // Perpendicular line: y = (-1/m)x + b 461 /* (lat1,lng1) |-----------------------| (lat3,lng3) 462 | | 463 |-----------------------| 464 | | 465 (lat2,lng2) |-----------------------| (lat4, lng4) 466 */ 467 // Formula: x1 = x0 + D/sqrt(1+m1^2), with m1 = -1/m 468 469 // Calculate the four corners 470 var m1 = -1/m; // Slope for normal line 471 var b0 = start_obj.lng - (start_obj.lat * m1); // Y-intercept for normal line 472 var b1 = finish_obj.lng - (finish_obj.lat * m1); // Y-intercept for normal line 473 var d = 0.000035 // Approximately 1.5m on either side of line 474 // Corner 1 475 var lat1 = start_obj.lat + ( d / Math.sqrt( 1+(m1 * m1) ) ); 476 var lng1 = (m1 * lat1) + b0; 477 var cnr1 = { 478 lat: lat1, 479 lng: lng1 480 } 481 // Corner 2 482 var lat2 = start_obj.lat - ( d / Math.sqrt( 1+(m1 * m1) ) ); 483 var lng2 = (m1 * lat2) + b0; 484 var cnr2 = { 485 lat: lat2, 486 lng: lng2 487 } 488 // Corner 3 489 var lat3 = finish_obj.lat + ( d / Math.sqrt( 1+(m1 * m1) ) ); 490 var lng3 = (m1 * lat3) + b1; 491 var cnr3 = { 492 lat: lat3, 493 lng: lng3 494 } 495 // Corner 4 496 var lat4 = finish_obj.lat - ( d / Math.sqrt( 1+(m1 * m1) ) ); 497 var lng4 = (m1 * lat4) + b1; 498 var cnr4 = { 499 lat: lat4, 500 lng: lng4 501 } 85 502 503 // Centre point 504 var clat = (lat1 + lat2 + lat3 + lat4) / 4; 505 var clng = (lng1 + lng2 + lng3 + lng4) / 4; 506 var centre = { 507 lat: clat, 508 lng: clng 509 } 510 511 // Generate the bounding box object 512 var bb_obj = { 513 cnr1: cnr1, 514 cnr2: cnr2, 515 cnr3: cnr3, 516 cnr4: cnr4, 517 centre: centre 518 } 519 520 // Store line attributes for later use 521 var short_obj = { 522 m: m1, 523 b0 : b0, 524 b1 : b1 525 } 526 var long_b0 = cnr1.lng - (m*cnr1.lat); // b = y-mx 527 var long_b1 = cnr2.lng - (m*cnr2.lat); // b = y-mx 528 var long_obj = { 529 m: m, 530 b0 : long_b0, 531 b1 : long_b1 532 } 533 534 //return bb_obj, short_obj, long_obj; 535 return { 536 bb_obj: bb_obj, 537 short_obj: short_obj, 538 long_obj: long_obj 539 }; 540} 541 542// Converts GPS data points to decimal coordinates 543// Decimal value = Degrees + (Minutes/60) + (Seconds/3600) 544function convertToDecimal(val, latlng, dir) { 545 var dec_result = 0; 546 if (latlng == "lat"){ 547 dec_result += parseFloat(val.substring(0,2)); 548 dec_result += parseFloat(val.substring(2)) / 60; 549 if (dir == "S"){ 550 dec_result *= -1.0; 551 } 552 } 553 else if (latlng == "lng"){ 554 dec_result += parseFloat(val.substring(0,3)); 555 dec_result += parseFloat(val.substring(3)) / 60; 556 if (dir == "W"){ 557 dec_result *= -1.0; 558 } 559 } 560 return dec_result; 561} 562 86 563// Calculates the distance between the previous coordinate and the new one 564// for the purpose of a "Trackpoint Distance Threshold" filter 565function distToPrev(lat1, lng1, lat2, lng2) { 566 // Using the Haversine formula 567 // a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2) 568 // c = 2 ⋅ atan2( √a, √(1−a) ) 569 // d = R ⋅ c 570 // Credits: http://www.movable-type.co.uk/scripts/latlong.html 571 var R = 6371000; // metres 572 var radlat1 = degToRad(lat1); 573 var radlat2 = degToRad(lat2); 574 var deltaLat = degToRad(lat2 - lat1); 575 var deltaLng = degToRad(lng2 - lng1); 576 577 var a = (Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2)) 578 + ( (Math.cos(radlat1) * Math.cos(radlat2)) 579 * (Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2)) ); 580 var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 581 var d = R * c; 582 583 return d; 584} 585 586// Converts degrees to radians 587function degToRad(degrees) { 588 return (degrees * Math.PI / 180); 589} 590 591// Handles file upload 592function handleFiles(e) { 593 e.stopPropagation(); 594 e.preventDefault(); 595 596 var files = e.dataTransfer.files; 597 598 var output = []; 599 var set = 0; 600 601 for (var i = 0, f; f = files[i]; i++) { 602 var reader = new FileReader(); 603 reader.onload = function(e) { 604 var text = reader.result; 605 newRead(text, set); 606 set += 1; 607 } 608 609 reader.readAsText(f); 610 } 611 612 toastr.info("Coordinates succesfully added to the database.", "Done") 613} 614 615function handleDragOver(e) { 616 e.stopPropagation(); 617 e.preventDefault(); 618 e.dataTransfer.dropEffect = 'copy'; // Explicitly show this is a copy. 619 } 620 87 621// Set sign up field to only ask for username 622Accounts.ui.config({ 623 passwordSignupFields: 'USERNAME_ONLY' 624}); map.js 1 //Only run function once "map" template has finished rendering 2 //in order to avoid errors 3 Template.map.rendered = function() { 4 // Draw each section 5 //Initialise the map according to OSM_maps.js in lib 6 osm_maps.initialise(); 7 8 //Run the following when the Sections Meteor collection changes 9 //i.e. new coordinates inserted or old ones removed 10 Deps.autorun(function() { 11 var secs = Sections.find().fetch(); 12 var latlngs = []; 13 //Check that collection is not empty 14 if (secs) { 15 // Temporarily set the type to "A" 16 var t = "A"; 17 var heat = 0; 18 //For each section, add the line to the map 19 _.each(secs, function(section) { 20 // console.log(section); 21 latlngs = []; 22 23 if (typeof section.start !== 'undefined' && 24 typeof section.finish !== 'undefined') { 25 // Add section start and end to coordinate data 26 latlngs.push(new L.LatLng(section.start.lat, section.start.lng)); 27 latlngs.push(new L.LatLng(section.finish.lat, section.finish.lng)); 28 29 // Set user type 30 var type = "A"; 31 32 // Generate heat rankings 33 var heat = 0; 34 if (section.count > 1000) { 35 heat = 9; 36 } else if (section.count > 500) { 37 heat = 8; 38 } else if (section.count > 250) { 39 heat = 7; 40 } else if (section.count > 100) { 41 heat = 6; 42 } else if (section.count > 50) { 43 heat = 5; 44 } else if (section.count > 25) { 45 heat = 4; 46 } else if (section.count > 10) { 47 heat = 3; 48 } else if (section.count > 1) { 49 heat = 2; 50 } else { 51 heat = 1; 88 52 53 54 55 56 57 58 59 60 61 62 63 type = "C"; } // Generate a line from the section data osm_maps.addLine(latlngs, type, heat); } }); } }); nav.js 1// Helper for navigation bar 2Template.navItems.helpers({ 3 activeIfTemplateIs: function (template) { 4 var currentRoute = Router.current(); 5 return currentRoute && 6 template === currentRoute.lookupTemplate() ? 'active' : ''; 7 } 8 }); Client: CSS styles.css #map-canvas { width: 100%; height: 600px; } #map-info { word-spacing:2pt; font-size:12px; text-align:center; font-family:arial black, sans-serif; } #dropbox { width: 350px; height: 60px; border: 4px dashed #B0B0B0; margin-left: auto; margin-right: auto; font-weight:bold; color:#B0B0B0; letter-spacing:1pt; word-spacing:2pt; font-size:20px; text-align:center; font-family:arial black, sans-serif; line-height:1; } Lib: JavaScript OSM_maps.js 1 2 osm_maps = { map: null, 89 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 A: null, B: null, C: null, //Add the line to the appropriate map layer, based on type addLine : function (latlngs, type, heat) { var c; switch (heat) { case 1: c = 'Aqua'; break; case 2: c = 'DeepSkyBlue'; break; case 3: c = 'Teal'; break; case 4: c = 'Blue'; break; case 5: c = 'MediumBlue'; break; case 6: c = 'DarkBlue'; break; case 7: c = 'Navy'; break; case 8: c = 'MidnightBlue'; break; case 9: c = 'Black'; break; } switch (type) { case 'A': var polyline = L.polyline(latlngs, { color: c, weight: heat }); this.A.addLayer(polyline); break; case 'B': var polyline = L.polyline(latlngs, { color: 'red', weight: 2 }); this.B.addLayer(polyline); break; case 'C': var polyline = L.polyline(latlngs, { color: 'yellow', weight: 2 }); this.C.addLayer(polyline); break; } }, 90 64 65 // Adds a polygon to the map 66 addPolygon : function(latlngs) { 67 var polygon = L.polygon(latlngs).addTo(this.map); 68 }, 69 70 // Adds a marker to the map 71 addMarker : function(latlng, t) { 72 //var marker = L.marker(latlng).addTo(this.map); 73 if (t == "A"){ 74 var circle = L.circle(latlng, 0.1, { 75 color: 'red', 76 fillColor: '#f03', 77 fillOpacity: 0.5 78 }).addTo(this.map); 79 } else { 80 var circle = L.circle(latlng, 0.1, { 81 color: 'red', 82 fillColor: '#f03', 83 fillOpacity: 0.7 84 }).addTo(this.map); 85 } 86 }, 87 88 //Initialise the map, centered on the student part of Stellenbosch, and add the appropriate 89 //layers 90 initialise : function () { 91 console.log("Initialising the map..."); 92 var cloudmadeUrl = 'http://{s}.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.jpg'; 93 var subDomains = ['otile1','otile2','otile3','otile4']; 94 var cloudmadeAttrib = 'Data, imagery and map information provided by <a href="http://open.mapquest.co.uk" target="_blank">MapQuest</a>, <a href="http://www.openstreetmap.org/" target="_blank">OpenStreetMap</a> and contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/" target="_blank">CC-BY-SA</a>'; 95 var cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18, attribution: cloudmadeAttrib, subdomains: subDomains}); 96 97 var dagbreek = new L.LatLng(-33.932607, 18.868643); 98 99 var A = L.layerGroup(); //Wheelchair user 100 this.A = A; 101 var B = L.layerGroup(); //Sight disabled 102 this.B = B; 103 var C = L.layerGroup(); //Singular traffic section 104 this.C = C; 105 106 this.map = new L.Map('map-canvas', {center: dagbreek, zoom: 14, layers : [cloudmade, this.A, this.B, this.C]}); 107 108 //Add map controller 109 //Reference: http://leafletjs.com/examples/layers-control.html 110 var baseMaps = { 111 "Open Street Maps": cloudmade 112 }; 113 var overlayMaps = { 114 "Wheelchair users" : this.A, 115 "Sight disabled" : this.B, 116 "Routes only used once" : this.C 91 117 118 119 120} }; L.control.layers(baseMaps, overlayMaps).addTo(this.map); } router.js 1 Router.configure({ 2 layoutTemplate: 'layout' //can be any template name 3 }); 4 5 Router.map(function () { 6 this.route('home', { 7 path: '/', 8 waitOn: function () {return Meteor.subscribe('all_coords')}, 9 data: function () { 10 return { 11 loggedIn: Meteor.user() 12 }; 13 } 14 }); 15 16 this.route('map', { 17 onBeforeAction: function() { 18 if(!Meteor.loggingIn() && !Meteor.user()) { 19 toastr.error('You need to log in to see this.', 'Oh no!') 20 this.redirect('home'); 21 } 22 }, 23 waitOn: function () {return Meteor.subscribe('all_coords')}, 24 data: function () { 25 var coords = Coordinates.find({}).fetch(); 26 return { 27 coords : coords 28 }; 29 } 30 }); 31 32 this.route('data', { 33 onBeforeAction: function() { 34 if(!Meteor.loggingIn() && !Meteor.user()) { 35 toastr.error('You need to log in to see this.', 'Oh no!') 36 this.redirect('home'); 37 } 38 }, 39 waitOn: function () {return Meteor.subscribe('all_coords')} 40 }) 41 42}) schema.js 1// _id, type, lat, lon, time, set 2Coordinates = new Meteor.Collection("coordinates"); 3// _id, sec_ID, start (lat, lng), finish (lat, lng), centre(lat, lng), 4// bounds (cnr1-4(lat, lng)), short_bb, long_bb, lat_min, lat_max, 5// lng_min, lng_max, count 6Sections = new Meteor.Collection("sections"); 7// Temporary storage for all the intersections 8Intersecs = new Meteor.Collection("intersecs"); 92 Server: JavaScript dummy.js 1 var dummy_coords = [ 2 {type: 'A', lat: -33.932536, lon: 18.868616, set: 1}, 3 {type: 'A', lat: -33.932604, lon: 18.867879, set: 1}, 4 {type: 'A', lat: -33.931161, lon: 18.867707, set: 1}, 5 {type: 'A', lat: -33.932336, lon: 18.858781, set: 1} 6 ]; 7 8 Meteor.methods({ 9 //Adds the above defined data to the collection 10 loadDummyData: function () { 11 dummy_coords.forEach(function (dummy_coord) { 12 Coordinates.insert(dummy_coord); 13 console.log("Added the dummy coordinates."); 14 }); 15 }, 16 //Clears the database 17 DBclear: function () { 18 Coordinates.remove({}); 19 Sections.remove({}); 20 Intersecs.remove({}); 21 console.log("Cleared the database."); 22 }, 23 // Returns the coordinates in the data store 24 COORDshow: function () { 25 console.log(Coordinates.find({}).fetch()); 26 }, 27 // Returns the sections in the data store 28 SECshow: function () { 29 console.log(Sections.find({}).fetch()); 30 } 31}); server.js 1Meteor.publish('all_coords', function () { 2 return Coordinates.find({}); 3}); 93
© Copyright 2024