Skip to content

Commit

Permalink
lcm: Add lcm_messages target
Browse files Browse the repository at this point in the history
  • Loading branch information
EricCousineau-TRI committed May 14, 2020
1 parent 99aa834 commit 7fc6472
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 6 deletions.
22 changes: 22 additions & 0 deletions lcm/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,28 @@ drake_cc_package_library(
":drake_lcm",
":interface",
":lcm_log",
":lcm_messages",
":mock",
":real",
],
)

drake_cc_library(
name = "lcm_messages",
srcs = ["lcm_messages.cc"],
hdrs = ["lcm_messages.h"],
deps = [
"//common:essential",
"//common:nice_type_name",
],
)

drake_cc_library(
name = "interface",
srcs = ["drake_lcm_interface.cc"],
hdrs = ["drake_lcm_interface.h"],
deps = [
":lcm_messages",
"//common:essential",
],
)
Expand Down Expand Up @@ -85,6 +97,16 @@ drake_cc_library(

# === test/ ===

drake_cc_googletest(
name = "lcm_messages_test",
deps = [
":lcm_messages",
":lcmt_drake_signal_utils",
"//common/test_utilities",
"//lcmtypes:drake_signal",
],
)

drake_cc_googletest(
name = "drake_lcm_interface_test",
deps = [
Expand Down
9 changes: 3 additions & 6 deletions lcm/drake_lcm_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "drake/common/drake_copyable.h"
#include "drake/common/drake_throw.h"
#include "drake/lcm/lcm_messages.h"

namespace drake {
namespace lcm {
Expand Down Expand Up @@ -181,12 +182,8 @@ template <typename Message>
void Publish(DrakeLcmInterface* lcm, const std::string& channel,
const Message& message, std::optional<double> time_sec = {}) {
DRAKE_THROW_UNLESS(lcm != nullptr);
const int num_bytes = message.getEncodedSize();
DRAKE_THROW_UNLESS(num_bytes >= 0);
const size_t size_bytes = static_cast<size_t>(num_bytes);
std::vector<uint8_t> bytes(size_bytes);
message.encode(bytes.data(), 0, num_bytes);
lcm->Publish(channel, bytes.data(), num_bytes, time_sec);
const std::vector<uint8_t> bytes = EncodeLcmMessage(message);
lcm->Publish(channel, bytes.data(), bytes.size(), time_sec);
}

/**
Expand Down
1 change: 1 addition & 0 deletions lcm/lcm_messages.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include "drake/lcm/lcm_messages.h"
49 changes: 49 additions & 0 deletions lcm/lcm_messages.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include <cstdint>
#include <vector>

#include "drake/common/drake_throw.h"
#include "drake/common/nice_type_name.h"

namespace drake {
namespace lcm {

/**
Encodes an LCM message to a series of bytes.
*/
template <typename Message>
std::vector<uint8_t> EncodeLcmMessage(const Message& message) {
const int num_bytes = message.getEncodedSize();
DRAKE_THROW_UNLESS(num_bytes >= 0);
const size_t size_bytes = static_cast<size_t>(num_bytes);
std::vector<uint8_t> bytes(size_bytes);
message.encode(bytes.data(), 0, num_bytes);
return bytes;
}

/**
Decodes an LCM message from a series of bytes.
@throws std::runtime_error if decoding fails.
*/
template <typename Message>
Message DecodeLcmMessage(const std::vector<uint8_t>& bytes) {
Message message{};
const size_t size_decoded = message.decode(bytes.data(), 0, bytes.size());
if (size_decoded != bytes.size()) {
throw std::runtime_error(
"Error decoding message of type '" + NiceTypeName::Get(message) + "'");
}
return message;
}

/**
Compares two LCM messages of the same type to see if they are equal.
*/
template <typename Message>
bool AreLcmMessagesEqual(const Message& a, const Message& b) {
return EncodeLcmMessage(a) == EncodeLcmMessage(b);
}

} // namespace lcm
} // namespace drake
48 changes: 48 additions & 0 deletions lcm/test/lcm_messages_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "drake/lcm/lcm_messages.h"

#include <gtest/gtest.h>

#include "drake/common/test_utilities/expect_throws_message.h"
#include "drake/lcm/lcmt_drake_signal_utils.h"
#include "drake/lcmt_drake_signal.hpp"

namespace drake {
namespace lcm {
namespace {

lcmt_drake_signal ModelMessage() {
lcmt_drake_signal message{};
message.timestamp = 2;
return message;
}

GTEST_TEST(LcmMessagesTest, EncodeDecodeLcmMessage) {
lcmt_drake_signal message{};
EXPECT_FALSE(
CompareLcmtDrakeSignalMessages(message, ModelMessage()));
const std::vector<uint8_t> bytes = EncodeLcmMessage(ModelMessage());
EXPECT_GT(bytes.size(), 0);
message = DecodeLcmMessage<lcmt_drake_signal>(bytes);
EXPECT_TRUE(
CompareLcmtDrakeSignalMessages(message, ModelMessage()));
}

GTEST_TEST(LcmMessagesTest, DecodeLcmMessageError) {
const std::vector<uint8_t> bytes = EncodeLcmMessage(ModelMessage());
std::vector<uint8_t> corrupt_bytes = bytes;
corrupt_bytes.at(0) = 0;
DRAKE_EXPECT_THROWS_MESSAGE(
DecodeLcmMessage<lcmt_drake_signal>(corrupt_bytes),
std::runtime_error,
"Error decoding message of type 'drake::lcmt_drake_signal'");
}

GTEST_TEST(LcmMessagesTest, AreLcmMessagesEqual) {
lcmt_drake_signal message{};
EXPECT_FALSE(AreLcmMessagesEqual(message, ModelMessage()));
EXPECT_TRUE(AreLcmMessagesEqual(ModelMessage(), ModelMessage()));
}

} // namespace
} // namespace lcm
} // namespace drake

0 comments on commit 7fc6472

Please sign in to comment.