Using the C++ client library
Description: How to use the C++ client library to talk to the warehouseTutorial Level: BEGINNER
Contents
The mongo_ros package provides a C++ ROS client library to the DB. For now, we just have an example of use. Note that this requires the db server to be running, as described in the previous tutorial.
https://kforge.ros.org/warehousewg/warehouse-hg/raw-file/tip/mongo_ros/test/test_mongo_ros.cpp
1 #include "test_mongo_helpers.h"
2 #include <mongo_ros/message_collection.h>
3 #include <mongo_ros/exceptions.h>
4 #include <ros/ros.h>
5 #include <boost/foreach.hpp>
6 #include <gtest/gtest.h>
7
8 namespace mr=mongo_ros;
9 namespace gm=geometry_msgs;
10 using std::vector;
11 using std::string;
12
13 typedef mr::MessageWithMetadata<gm::Pose> PoseWithMetadata;
14 typedef PoseWithMetadata::ConstPtr PoseMetaPtr;
15
16 // Helper function that creates metadata for a message.
17 // Here we'll use the x and y position, as well as a 'name'
18 // field that isn't part of the original message.
19 mr::Metadata makeMetadata (const gm::Pose& p, const string& v)
20 {
21 return mr::Metadata("x", p.position.x, "y", p.position.y, "name", v);
22 }
23
24 TEST(MongoRos, MongoRos)
25 {
26 // Symbols used in queries to denote binary predicates for < and >
27 // Note that equality is the default, so we don't need a symbol for it
28 using mr::LT;
29 using mr::GT;
30
31 // Clear existing data if any
32 mr::dropDatabase("my_db");
33
34 // Set up db
35 mr::MessageCollection<gm::Pose> coll("my_db", "poses");
36
37 // Arrange to index on metadata fields 'x' and 'name'
38 coll.ensureIndex("name");
39 coll.ensureIndex("x");
40
41 // Add some poses and metadata
42 const gm::Pose p1 = makePose(24, 42, 0);
43 const gm::Pose p2 = makePose(10, 532, 3);
44 const gm::Pose p3 = makePose(53, 22, 5);
45 const gm::Pose p4 = makePose(22, -5, 33);
46 coll.insert(p1, makeMetadata(p1, "bar"));
47 coll.insert(p2, makeMetadata(p2, "baz"));
48 coll.insert(p3, makeMetadata(p3, "qux"));
49 coll.insert(p1, makeMetadata(p1, "oof"));
50 coll.insert(p4, makeMetadata(p4, "ooof"));
51 EXPECT_EQ(5u, coll.count());
52
53 // Simple query: find the pose with name 'qux' and return just its metadata
54 // Since we're doing an equality check, we don't explicitly specify a predicate
55 vector<PoseMetaPtr> res = coll.pullAllResults(mr::Query("name", "qux"), true);
56 EXPECT_EQ(1u, res.size());
57 EXPECT_EQ("qux", res[0]->lookupString("name"));
58 EXPECT_DOUBLE_EQ(53, res[0]->lookupDouble("x"));
59
60 // Set up query: position.x < 40 and position.y > 0. Reverse order
61 // by the "name" metadata field. Also, here we pull the message itself, not
62 // just the metadata. Finally, we can't use the simplified construction
63 // syntax here because it's too long
64 mr::Query q = mr::Query().append("x", mr::LT, 40).append("y", mr::GT, 0);
65 vector<PoseMetaPtr> poses = coll.pullAllResults(q, false, "name", false);
66
67 // Verify poses.
68 EXPECT_EQ(3u, poses.size());
69 EXPECT_EQ(p1, *poses[0]);
70 EXPECT_EQ(p2, *poses[1]);
71 EXPECT_EQ(p1, *poses[2]);
72
73 EXPECT_EQ("oof", poses[0]->lookupString("name"));
74 EXPECT_EQ("baz", poses[1]->lookupString("name"));
75 EXPECT_EQ("bar", poses[2]->lookupString("name"));
76
77 // Set up query to delete some poses.
78 mr::Query q2 ("y", mr::LT, 30);
79
80 EXPECT_EQ(5u, coll.count());
81 EXPECT_EQ(2u, coll.removeMessages(q2));
82 EXPECT_EQ(3u, coll.count());
83
84 // Test findOne
85 mr::Query q4("name", "bar");
86 EXPECT_EQ(p1, *coll.findOne(q4, false));
87 EXPECT_DOUBLE_EQ(24, coll.findOne(q4, true)->lookupDouble("x"));
88
89 mr::Query q5("name", "barbar");
90 EXPECT_THROW(coll.findOne(q5, true), mr::NoMatchingMessageException);
91 EXPECT_THROW(coll.findOne(q5, false), mr::NoMatchingMessageException);
92
93 // Test update
94 coll.modifyMetadata(q4, mr::Metadata("name", "barbar"));
95 EXPECT_EQ(3u, coll.count());
96 EXPECT_THROW(coll.findOne(q4, false), mr::NoMatchingMessageException);
97 ROS_INFO("here");
98 EXPECT_EQ(p1, *coll.findOne(q5, false));
99
100 // Check stored metadata
101 boost::shared_ptr<mongo::DBClientConnection> conn =
102 mr::makeDbConnection(ros::NodeHandle());
103 EXPECT_EQ("geometry_msgs/Pose", mr::messageType(*conn, "my_db", "poses"));
104 }
105
106
107 int main (int argc, char** argv)
108 {
109 ros::init(argc, argv, "client_test");
110 ros::NodeHandle nh;
111 testing::InitGoogleTest(&argc, argv);
112 return RUN_ALL_TESTS();
113 }
114






