长安的花

当学问走过漫漫古道
凿刻入千窟,心也从愚昧中苏醒

0%

Udacity 6.PID 代码解析

Udacity 代码解析

定义

1
2
3
4
5
constexpr double pi() { return M_PI; }

double deg2rad(double x) { return x * pi() / 180; }

double rad2deg(double x) { return x * 180 / pi(); }

定义一个Pi,定义两个角度转弧度和弧度转角度的函数

constexpr声明为constexpr类型的变量,编译器会验证该变量的值是否是一个常量表达式。

获取地图数据

1
2
3
4
5
6
7
8
9
10
11
std::string 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 "";
} else if (b1 != std::string::npos && b2 != std::string::npos) {
return s.substr(b1, b2 - b1 + 1);
}
return "";
}

主函数

1
2
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
int main() {
uWS::Hub h;

// Set PID gains 设置三个增益
double k_p = 0.1;
double k_i = 0.0001;
double k_d = 1.0;

// Initialize PID controller
PID pid;
pid.Init(k_p, k_i, k_d);// 初始化

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 j = json::parse(s);
std::string event = j[0].get<std::string>();
if (event == "telemetry") {
// j[1] is the data JSON object
// 从模拟器里获取信息
// cte 是误差
// speed 速度
// angle 转向角
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;

pid.UpdateError(cte);//使用pid的函数更新误差

steer_value = pid.TotalError();//获取总误差,总误差指的是需要偏转的角度

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

json msgJson;
msgJson["steering_angle"] = steer_value;
msgJson["throttle"] = 0.4;
auto msg = "42[\"steer\"," + msgJson.dump() + "]";
std::cout << msg << std::endl;
ws.send(msg.data(), msg.length(), uWS::OpCode::TEXT);
}
} else {
// Manual driving
std::string msg = "42[\"manual\",{}]";
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();
std::cout << "Disconnected" << std::endl;
});

int port = 4567;
if (h.listen(port)) {
std::cout << "Listening to port " << port << std::endl;
} else {
std::cerr << "Failed to listen to port" << std::endl;
return -1;
}
h.run();
}

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道