Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows version #3

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 16 additions & 17 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
project(PID)

cmake_minimum_required (VERSION 3.5)

add_definitions(-std=c++11)

set(CXX_FLAGS "-Wall")
set(CXX_FLAGS "-W1")
set(CMAKE_CXX_FLAGS, "${CXX_FLAGS}")
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")

set(sources src/PID.cpp src/main.cpp src/uWS/Extensions.cpp src/uWS/Group.cpp src/uWS/WebSocketImpl.cpp src/uWS/Networking.cpp src/uWS/Hub.cpp src/uWS/Node.cpp src/uWS/WebSocket.cpp src/uWS/HTTPSocket.cpp src/uWS/Socket.cpp src/uWS/uUV.cpp)
set_source_files_properties(${sources} PROPERTIES COMPILE_FLAGS "-D_USE_MATH_DEFINES")

set(sources src/PID.cpp src/main.cpp)

else(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(sources src/PID.cpp src/main.cpp)
endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")

if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")

include_directories(/usr/local/include)
include_directories(/usr/local/opt/openssl/include)
link_directories(/usr/local/lib)
link_directories(/usr/local/opt/openssl/lib)
link_directories(/usr/local/Cellar/libuv/1.11.0/lib)

include_directories(/usr/local/include)
include_directories(/usr/local/opt/openssl/include)
link_directories(/usr/local/lib)
link_directories(/usr/local/opt/openssl/lib)
link_directories(/usr/local/Cellar/libuv/1.11.0/lib)
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")


add_executable(pid ${sources})

target_link_libraries(pid z ssl uv uWS)
if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
target_link_libraries(pid z ssl uv uWS)
endif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
44 changes: 44 additions & 0 deletions CMakeSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug",
"generator": "Visual Studio 15 2017",
"configurationType": "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",

"variables": [
{
"name": "DCMAKE_TOOLCHAIN_FILE",
"value": "C:/vcpkg/scripts/buildsystems/vcpkg.cmake"
}
]
},
{
"name": "x86-Release",
"generator": "Visual Studio 15 2017",
"configurationType" : "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal"
},
{
"name": "x64-Debug",
"generator": "Visual Studio 15 2017 Win64",
"configurationType" : "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal"
},
{
"name": "x64-Release",
"generator": "Visual Studio 15 2017 Win64",
"configurationType" : "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal"
}
]
}
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,17 @@ Self-Driving Car Engineer Nanodegree Program
1. Clone this repo.
2. Make a build directory: `mkdir build && cd build`
3. Compile: `cmake .. && make`
4. Run it: `./pid`.
4. Run it: `./pid`.

## Windows Install Instructions

1. Install, in your root `c:/` directory, vcpkg https://github.com/Microsoft/vcpkg (15 - 30 minutes)
2. Be sure while installing vcpkg to carefully follow all instructions! This is NOT an easy install process.
3. Install python 2.7 (dependency for libuv)
4. cd to directory with vcpkg .exe and `./vcpkg install uWebsockets` (20 min, mostly automatic)
5. Open CMakeSetting.json, check if `C:/vcpkg/scripts/buildsystems/vcpkg.cmake` is the correct directory to your vcpkg and `DCMAKE_TOOLCHAIN_FILE` matches the output from vcpkg integrate.
6. Open in VS17 community edition, build pid.exe in x86 debug.


## Editor Settings

Expand Down
1 change: 1 addition & 0 deletions src/PID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ void PID::UpdateError(double cte) {
}

double PID::TotalError() {
return 1;
}

58 changes: 28 additions & 30 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#include <uWS/uWS.h>
#define _USE_MATH_DEFINES

#include "uWS/uWS.h"
#include <iostream>
#include "json.hpp"
#include "PID.h"
#include <math.h>


using namespace std;

// for convenience
using json = nlohmann::json;

Expand All @@ -12,52 +17,59 @@ constexpr double pi() { return M_PI; }
double deg2rad(double x) { return x * pi() / 180; }
double rad2deg(double x) { return x * 180 / pi(); }



// Checks if the SocketIO event has JSON data.
// If there is data the JSON object in string format will be returned,
// else the empty string "" will be returned.
std::string hasData(std::string s) {
std::stringstream hasData(std::string s) {
auto found_null = s.find("null");
auto b1 = s.find_first_of("[");
auto b2 = s.find_last_of("]");
if (found_null != std::string::npos) {
return "";
return std::stringstream();
}
else if (b1 != std::string::npos && b2 != std::string::npos) {
return s.substr(b1, b2 - b1 + 1);
std::stringstream tmp = std::stringstream();
tmp.str(s.substr(b1, b2 - b1 + 1));
return tmp;
}
return "";
return std::stringstream();
}


int main()
{

uWS::Hub h;

PID pid;
// TODO: Initialize the pid variable.


h.onMessage([&pid](uWS::WebSocket<uWS::SERVER> ws, char *data, size_t length, uWS::OpCode opCode) {
// "42" at the start of the message means there's a websocket message event.
// The 4 signifies a websocket message
// The 2 signifies a websocket event
if (length && length > 2 && data[0] == '4' && data[1] == '2')
{
auto s = hasData(std::string(data).substr(0, length));
if (s != "") {
auto s = hasData(std::string(data));
if (s.str() != "") {
auto j = json::parse(s);
std::string event = j[0].get<std::string>();
if (event == "telemetry") {
// j[1] is the data JSON object
double cte = std::stod(j[1]["cte"].get<std::string>());
double speed = std::stod(j[1]["speed"].get<std::string>());
double angle = std::stod(j[1]["steering_angle"].get<std::string>());
double steer_value;
/*
* TODO: Calcuate steering value here, remember the steering value is
* [-1, 1].
* NOTE: Feel free to play around with the throttle and speed. Maybe use
* another PID controller to control the speed!
*/



// DEBUG
std::cout << "CTE: " << cte << " Steering Value: " << steer_value << std::endl;

Expand All @@ -66,42 +78,28 @@ int main()
msgJson["throttle"] = 0.3;
auto msg = "42[\"steer\"," + msgJson.dump() + "]";
std::cout << msg << std::endl;
ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);
(ws).send(msg.data(), msg.length(), uWS::OpCode::TEXT);
}
} else {
}
else {
// Manual driving
std::string msg = "42[\"manual\",{}]";
ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);
(ws).send(msg.data(), msg.length(), uWS::OpCode::TEXT);
}
}
});

// We don't need this since we're not using HTTP but if it's removed the program
// doesn't compile :-(
h.onHttpRequest([](uWS::HttpResponse *res, uWS::HttpRequest req, char *data, size_t, size_t) {
const std::string s = "<h1>Hello world!</h1>";
if (req.getUrl().valueLength == 1)
{
res->end(s.data(), s.length());
}
else
{
// i guess this should be done more gracefully?
res->end(nullptr, 0);
}
});

h.onConnection([&h](uWS::WebSocket<uWS::SERVER> ws, uWS::HttpRequest req) {
std::cout << "Connected!!!" << std::endl;
});

h.onDisconnection([&h](uWS::WebSocket<uWS::SERVER> ws, int code, char *message, size_t length) {
ws.close();
(ws).close();
std::cout << "Disconnected" << std::endl;
});

int port = 4567;
if (h.listen(port))
if (h.listen("0.0.0.0", port))
{
std::cout << "Listening to port " << port << std::endl;
}
Expand All @@ -111,4 +109,4 @@ int main()
return -1;
}
h.run();
}
}
131 changes: 131 additions & 0 deletions src/uWS/Extensions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#include "Extensions.h"

namespace uWS {

enum ExtensionTokens {
TOK_PERMESSAGE_DEFLATE = 1838,
TOK_SERVER_NO_CONTEXT_TAKEOVER = 2807,
TOK_CLIENT_NO_CONTEXT_TAKEOVER = 2783,
TOK_SERVER_MAX_WINDOW_BITS = 2372,
TOK_CLIENT_MAX_WINDOW_BITS = 2348
};

class ExtensionsParser {
private:
int *lastInteger = nullptr;

public:
bool perMessageDeflate = false;
bool serverNoContextTakeover = false;
bool clientNoContextTakeover = false;
int serverMaxWindowBits = 0;
int clientMaxWindowBits = 0;

int getToken(const char *&in, const char *stop);
ExtensionsParser(const char *data, size_t length);
};

int ExtensionsParser::getToken(const char *&in, const char *stop) {
while (!isalnum(*in) && in != stop) {
in++;
}

int hashedToken = 0;
while (isalnum(*in) || *in == '-' || *in == '_') {
if (isdigit(*in)) {
hashedToken = hashedToken * 10 - (*in - '0');
} else {
hashedToken += *in;
}
in++;
}
return hashedToken;
}

ExtensionsParser::ExtensionsParser(const char *data, size_t length) {
const char *stop = data + length;
int token = 1;
for (; token && token != TOK_PERMESSAGE_DEFLATE; token = getToken(data, stop));

perMessageDeflate = (token == TOK_PERMESSAGE_DEFLATE);
while ((token = getToken(data, stop))) {
switch (token) {
case TOK_PERMESSAGE_DEFLATE:
return;
case TOK_SERVER_NO_CONTEXT_TAKEOVER:
serverNoContextTakeover = true;
break;
case TOK_CLIENT_NO_CONTEXT_TAKEOVER:
clientNoContextTakeover = true;
break;
case TOK_SERVER_MAX_WINDOW_BITS:
serverMaxWindowBits = 1;
lastInteger = &serverMaxWindowBits;
break;
case TOK_CLIENT_MAX_WINDOW_BITS:
clientMaxWindowBits = 1;
lastInteger = &clientMaxWindowBits;
break;
default:
if (token < 0 && lastInteger) {
*lastInteger = -token;
}
break;
}
}
}

template <bool isServer>
ExtensionsNegotiator<isServer>::ExtensionsNegotiator(int wantedOptions) {
options = wantedOptions;
}

template <bool isServer>
std::string ExtensionsNegotiator<isServer>::generateOffer() {
std::string extensionsOffer;
if (options & Options::PERMESSAGE_DEFLATE) {
extensionsOffer += "permessage-deflate";

if (options & Options::CLIENT_NO_CONTEXT_TAKEOVER) {
extensionsOffer += "; client_no_context_takeover";
}

if (options & Options::SERVER_NO_CONTEXT_TAKEOVER) {
extensionsOffer += "; server_no_context_takeover";
}
}

return extensionsOffer;
}

template <bool isServer>
void ExtensionsNegotiator<isServer>::readOffer(std::string offer) {
if (isServer) {
ExtensionsParser extensionsParser(offer.data(), offer.length());
if ((options & PERMESSAGE_DEFLATE) && extensionsParser.perMessageDeflate) {
if (extensionsParser.clientNoContextTakeover || (options & CLIENT_NO_CONTEXT_TAKEOVER)) {
options |= CLIENT_NO_CONTEXT_TAKEOVER;
}

if (extensionsParser.serverNoContextTakeover) {
options |= SERVER_NO_CONTEXT_TAKEOVER;
} else {
options &= ~SERVER_NO_CONTEXT_TAKEOVER;
}
} else {
options &= ~PERMESSAGE_DEFLATE;
}
} else {
// todo!
}
}

template <bool isServer>
int ExtensionsNegotiator<isServer>::getNegotiatedOptions() {
return options;
}

template class ExtensionsNegotiator<true>;
template class ExtensionsNegotiator<false>;

}
Loading