forked from RobotLocomotion/drake
-
Notifications
You must be signed in to change notification settings - Fork 0
/
drake_mock_lcm.h
129 lines (109 loc) · 4.37 KB
/
drake_mock_lcm.h
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#pragma once
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "drake/common/drake_copyable.h"
#include "drake/common/drake_optional.h"
#include "drake/lcm/drake_lcm_interface.h"
namespace drake {
namespace lcm {
/**
* A *mock* LCM instance. This does not actually publish or subscribe to LCM
* messages. It contains additional methods for accessing the most recent
* message that was "published," and faking a callback.
*/
class DrakeMockLcm : public DrakeLcmInterface {
public:
DRAKE_NO_COPY_NO_MOVE_NO_ASSIGN(DrakeMockLcm);
/**
* A constructor that creates a DrakeMockLcm with loopback disabled, i.e., a
* call to Publish() will not result in subscriber callback functions being
* executed. To enable loopback behavior, call EnableLoopBack().
*/
DrakeMockLcm();
/**
* Enables loopback behavior. With loopback enabled, a call to Publish() will
* result in subscriber callback functions being called. Without loopback
* enabled, the only way to induce a call to a subscriber's callback function
* is through InduceSubscriberCallback().
*/
void EnableLoopBack() { enable_loop_back_ = true; }
void Publish(const std::string&, const void*, int, optional<double>) override;
/**
* Obtains the most recently "published" message on a particular channel.
* This method automatically decodes the message into an LCM message whose
* type is specified by the template type.
* @throws std::runtime_error if no LCM message was published on the provided
* channel or if the message failed to be decoded by the provided LCM message
* type.
*
* @tparam T The LCM message type.
*
* @param[in] channel the LCM channel for which the last published message is
* returned.
*
* @return the decoded most recently transmitted LCM message on the provided
* channel.
*/
template<typename T>
T DecodeLastPublishedMessageAs(const std::string& channel) const {
const std::vector<uint8_t>& message_bytes =
get_last_published_message(channel);
T transmitted_message{};
const int num_bytes = transmitted_message.decode(message_bytes.data(), 0,
message_bytes.size());
if (num_bytes != static_cast<int>(message_bytes.size())) {
throw std::runtime_error("DrakeMockLcm::DecodeLastPublishedMessageAs(): "
"ERROR: Failed to decode the LCM message. Number of bytes decoded: " +
std::to_string(num_bytes) + ". Number of message bytes that should "
"have been decoded: " + std::to_string(message_bytes.size()) + ".");
}
return transmitted_message;
}
/**
* Obtains the most recently "published" message on a particular channel. A
* std::runtime_error will be thrown if no message was published on the
* provide channel.
*
* @param[in] channel The channel on which the LCM message was published.
*
* @return A reference to a vector containing the serialized bytes of the
* LCM message that was previously published on channel @p channel.
*
* @pre A message was previously published on channel @p channel.
*/
const std::vector<uint8_t>& get_last_published_message(
const std::string& channel) const;
/**
* Returns the time of the most recent publication on a particular channel.
* Returns nullopt iff a message has never been published on this channel or
* the most recent Publish call had no time_sec.
*/
optional<double> get_last_publication_time(const std::string& channel) const;
void Subscribe(const std::string&, HandlerFunction) override;
/**
* Fakes a callback. The callback is executed by the same thread as the one
* calling this method.
*
* @param[in] channel The channel on which to publish the message.
*
* @param[in] data A buffer containing the serialized bytes of the message to
* publish.
*
* @param[in] data_size The length of @data in bytes.
*/
void InduceSubscriberCallback(const std::string& channel, const void* data,
int data_size);
private:
bool enable_loop_back_{false};
struct LastPublishedMessage {
std::vector<uint8_t> data{};
optional<double> time_sec{};
};
std::map<std::string, LastPublishedMessage> last_published_messages_;
// Maps the channel name to the subscriber.
std::multimap<std::string, HandlerFunction> subscriptions_;
};
} // namespace lcm
} // namespace drake