1 #include "V2VService.hpp" 3 std::shared_ptr<cluon::OD4Session> od4;
4 std::string followerIp;
5 std::queue <float> delayQueue;
7 int main(
int argc,
char **argv) {
9 auto commandlineArguments = cluon::getCommandlineArguments(argc, argv);
10 if (0 == commandlineArguments.count(
"cid") || 0 == commandlineArguments.count(
"freq") ||
11 0 == commandlineArguments.count(
"ip") || 0 == commandlineArguments.count(
"id")) {
12 std::cerr << argv[0] <<
" sends and receives follower or leader status as defined in the V2V Protocol (DIT168)." 14 std::cerr <<
"Usage: " << argv[0]
15 <<
" --cid=<OD4Session Session> --freq=<frequency> --ip=<localIP> --id=<DIT168Group>" 17 std::cerr <<
"Example: " << argv[0]
18 <<
" --cid=111 --freq=125 --ip=127.0.0.1 --id=9 --partnerIp=1.1.1.1 --parnterId=8" << std::endl;
21 const uint16_t CID = (uint16_t) std::stoi(commandlineArguments[
"cid"]);
22 const uint16_t FREQ = (uint16_t) std::stoi(commandlineArguments[
"freq"]);
23 const uint16_t QUEUE_MAX = (uint16_t) std::stoi(commandlineArguments[
"queueMax"]);
24 const std::string IP = commandlineArguments[
"ip"];
25 const std::string ID = commandlineArguments[
"id"];
26 const std::string PARTNER_IP = commandlineArguments[
"partnerIp"];
27 const std::string PARTNER_ID = commandlineArguments[
"partnerId"];
28 const std::string SPEED_AFTER = commandlineArguments[
"offsetSpeedAfter"];
29 const std::string LEFT = commandlineArguments[
"left"];
30 const std::string RIGHT = commandlineArguments[
"right"];
32 std::shared_ptr<V2VService> v2vService = std::make_shared<V2VService>(IP, ID, PARTNER_IP, PARTNER_ID,
33 SPEED_AFTER, LEFT, RIGHT, QUEUE_MAX);
35 float pedalPos = 0, steeringAngle = 0, distanceReading = 0;
40 std::make_shared<cluon::OD4Session>(CID,
41 [&v2vService, &pedalPos, &steeringAngle, &button, &PARTNER_IP](cluon::data::Envelope &&envelope) noexcept {
42 if (envelope.dataType() == 1041) {
43 opendlv::proxy::PedalPositionReading ppr =
44 cluon::extractMessage<opendlv::proxy::PedalPositionReading>(std::move(envelope));
45 pedalPos = ppr.position();
47 else if (envelope.dataType() == 1043) {
48 opendlv::proxy::ButtonPressed buttonPressed =
49 cluon::extractMessage<opendlv::proxy::ButtonPressed>(std::move(envelope));
50 button = buttonPressed.buttonNumber();
53 v2vService->followRequest();
56 v2vService->followResponse();
59 v2vService->stopFollow(PARTNER_IP);
62 v2vService->announcePresence();
65 std::cout <<
"You shouldn't be here" << std::endl;
69 else if (envelope.dataType() == 1045) {
70 opendlv::proxy::GroundSteeringReading gsr =
71 cluon::extractMessage<opendlv::proxy::GroundSteeringReading>(std::move(envelope));
72 steeringAngle = gsr.groundSteering();
76 auto atFrequency{[&v2vService, &pedalPos, &steeringAngle]() ->
bool {
77 v2vService->followerStatus();
78 v2vService->leaderStatus(pedalPos, steeringAngle, 0);
81 od4->timeTrigger(FREQ, atFrequency);
89 std::string speed_after, std::string left, std::string right, uint16_t queue_max) {
92 _PARTNER_IP = partnerIp;
93 _PARTNER_ID = partnerId;
94 _SPEED_AFTER = speed_after;
97 _QUEUE_MAX = queue_max;
104 std::make_shared<cluon::OD4Session>(BROADCAST_CHANNEL,
105 [
this](cluon::data::Envelope &&envelope) noexcept {
106 std::cout <<
"[OD4] ";
107 switch (envelope.dataType()) {
108 case ANNOUNCE_PRESENCE: {
109 AnnouncePresence ap = cluon::extractMessage<AnnouncePresence>(std::move(envelope));
110 std::cout <<
"received 'AnnouncePresence' from '" 111 << ap.vehicleIp() <<
"', GroupID '" 112 << ap.groupId() <<
"'!" << std::endl;
113 if (ap.vehicleIp() == _PARTNER_IP && ap.groupId() == _PARTNER_ID) {
114 isPresentPartner =
true;
116 presentCars[ap.groupId()] = ap.vehicleIp();
120 default: std::cout <<
"[BROADCAST CHANNEL] Not announce presence." << std::endl;
130 std::make_shared<cluon::UDPReceiver>(
"0.0.0.0", DEFAULT_PORT,
131 [
this](std::string &&data, std::string &&sender, std::chrono::system_clock::time_point &&ts) noexcept {
132 std::cout <<
"[UDP] ";
133 std::pair<int16_t, std::string> msg = extract(data);
136 case FOLLOW_REQUEST: {
137 FollowRequest
followRequest = decode<FollowRequest>(msg.second);
139 <<
"' from '" << sender <<
"'!" << std::endl;
143 unsigned long len = sender.find(
':');
144 followerIp = sender.substr(0, len);
145 toFollower = std::make_shared<cluon::UDPSender>(followerIp, DEFAULT_PORT);
150 case FOLLOW_RESPONSE: {
151 FollowResponse
followResponse = decode<FollowResponse>(msg.second);
153 <<
"' from '" << sender <<
"'!" << std::endl;
158 StopFollow
stopFollow = decode<StopFollow>(msg.second);
159 std::cout <<
"received '" <<
stopFollow.LongName()
160 <<
"' from '" << sender <<
"'!" << std::endl;
163 unsigned long len = sender.find(
':');
164 if (sender.substr(0, len) == followerIp) {
166 std::cout <<
"Car was leader, no longer is\n";
170 else if (sender.substr(0, len) == leaderIp) {
172 std::cout <<
"Car was follower, no longer is\n";
178 case FOLLOWER_STATUS: {
179 FollowerStatus
followerStatus = decode<FollowerStatus>(msg.second);
181 <<
"' from '" << sender <<
"'!" << std::endl;
185 case LEADER_STATUS: {
186 opendlv::proxy::PedalPositionReading msgPedal;
187 opendlv::proxy::GroundSteeringReading msgSteering;
188 float calibratedAngle = 0.0f;
190 LeaderStatus
leaderStatus = decode<LeaderStatus>(msg.second);
192 <<
"' from '" << sender <<
"'!" << std::endl;
193 std::cout <<
"LeaderStatus Values, pedalPos: " <<
leaderStatus.speed() <<
" steeringAngle: " 196 float floatSpeedAfter = std::stof(_SPEED_AFTER);
201 msgPedal.position(
leaderStatus.speed() + floatSpeedAfter);
205 float floatLeft = std::stof(_LEFT);
206 float floatRight = std::stof(_RIGHT);
209 calibratedAngle =
leaderStatus.steeringAngle() + m_OFFSET;
212 std::cout <<
"Left Value: " << (
leaderStatus.steeringAngle() + floatLeft)
214 calibratedAngle = (
leaderStatus.steeringAngle() + floatLeft);
217 std::cout <<
"Right Value: " << (
leaderStatus.steeringAngle() + floatRight)
219 calibratedAngle =
leaderStatus.steeringAngle() + floatRight;
222 if (
leaderStatus.speed() != 0 && delayQueue.size() < _QUEUE_MAX) {
223 delayQueue.push(calibratedAngle);
225 else if (
leaderStatus.speed() != 0 && delayQueue.size() >= _QUEUE_MAX) {
226 delayQueue.push(calibratedAngle);
228 float delayedSteeringAngle = delayQueue.front();
229 msgSteering.groundSteering(delayedSteeringAngle);
230 od4->send(msgSteering);
236 default: std::cout <<
"¯\\_(ツ)_/¯" << std::endl;
248 std::cout <<
"Announce presence returned! Already following of a car" << std::endl;
265 if (!isPresentPartner || isFollower) {
266 std::cout <<
"Follow request returned! isFollower: " << isFollower <<
" isPresentPartner: " << isPresentPartner
270 toLeader = std::make_shared<cluon::UDPSender>(_PARTNER_IP, DEFAULT_PORT);
282 if (isFollower || isLeader) {
283 std::cout <<
"Follow response returned! isFollower: " << isFollower <<
" isLeader: " << isLeader << std::endl;
302 stopFollow.temporaryValue(
"Stop follow test");
304 std::cout <<
"Inside stop follow, vehicleIp == _PARTNER_IP: " << (vehicleIp == _PARTNER_IP) <<
" isFollower: " 305 << isFollower <<
" isLeader: " << isLeader << std::endl;
307 if (vehicleIp == _PARTNER_IP && isFollower) {
309 std::cout <<
"Car was follower\n";
314 if (vehicleIp == _PARTNER_IP && isLeader) {
316 std::cout <<
"Car was leader\n";
332 if (!isFollower)
return;
347 if (!isLeader)
return;
351 std::cout <<
"Sending to david: " << (steeringAngle - m_OFFSET) << std::endl;
363 uint32_t V2VService::getTime() {
365 gettimeofday(&now,
nullptr);
366 return (uint32_t ) now.tv_usec / 1000;
375 std::pair<int16_t, std::string> V2VService::extract(std::string data) {
376 if (data.length() < 10)
return std::pair<int16_t, std::string>(-1,
"");
378 std::stringstream ssId(data.substr(0, 4));
379 std::stringstream ssLen(data.substr(4, 10));
380 ssId >> std::hex >> id;
381 ssLen >> std::hex >> len;
382 return std::pair<int16_t, std::string> (
383 data.length() -10 == len ? id : -1,
384 data.substr(10, data.length() -10)
396 std::string V2VService::encode(T msg) {
397 cluon::ToProtoVisitor v;
399 std::stringstream buff;
400 buff << std::hex << std::setfill(
'0')
401 << std::setw(4) << msg.ID()
402 << std::setw(6) << v.encodedData().length()
415 T V2VService::decode(std::string data) {
416 std::stringstream buff(data);
417 cluon::FromProtoVisitor v;
void stopFollow(std::string vehicleIp)
V2VService(std::string ip, std::string id, std::string partnerIp, std::string partnerId, std::string speed_after, std::string left, std::string right, uint16_t queue_max)
void leaderStatus(float speed, float steeringAngle, uint8_t distanceTraveled)