AriacScorer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2016 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
18 #include <string>
19 
20 #include <gazebo/math/Pose.hh>
21 #include <gazebo/math/Vector3.hh>
22 #include <gazebo/math/Quaternion.hh>
23 
24 #include "osrf_gear/AriacScorer.h"
25 
28 {
29 }
30 
33 {
34 }
35 
38 {
39  return this->gameScore;
40 }
41 
44 {
45  return *this->goalScore;
46 }
47 
49 void AriacScorer::Update(double timeStep)
50 {
51  if (this->isPartTravelling)
52  {
53  this->gameScore.partTravelTime += timeStep;
54  }
55 
56  boost::mutex::scoped_lock kitTraysLock(this->kitTraysMutex);
57 
58  if (this->newGoalReceived)
59  {
60  this->AssignGoal(this->newGoal);
61  }
62 
63  // During the competition, this environment variable will be set.
64  auto v = std::getenv("ARIAC_COMPETITION");
65  if (!v)
66  {
67  // Check score of trays in progress.
68  if (this->newGoalReceived || this->newTrayInfoReceived)
69  {
70  this->ScoreCurrentState();
71  }
72  }
73 
74  this->newGoalReceived = false;
75  this->newTrayInfoReceived = false;
76 }
77 
80 {
81  return this->goalScore->isComplete();
82 }
83 
86 {
87  for (const auto & item : this->kitTrays)
88  {
89  auto trayID = item.first;
90  auto tray = item.second;
91  if (tray.currentKit.kitType != "")
92  {
93  auto trayScore = ScoreTray(tray);
94  ROS_INFO_STREAM("Score from tray '" << trayID <<
95  "' with kit type '" << tray.currentKit.kitType << "': " << trayScore.total());
96  }
97  else
98  {
99  for (const auto & item : this->currentGoal.kits)
100  {
101  auto kit = item.second;
102  auto goalKitType = kit.kitType;
103  tray.currentKit.kitType = goalKitType;
104  auto trayScore = ScoreTray(tray);
105  ROS_INFO_STREAM("Score from tray '" << trayID
106  << "' if it were to have kit type '" << goalKitType << "': "
107  << trayScore.total());
108  }
109  }
110  }
111 }
112 
115 {
116  auto it = this->kitTrays.find(trayID);
117  if (it == this->kitTrays.end())
118  {
119  ROS_DEBUG_STREAM("No known tray with ID: " << trayID);
120  return false;
121  }
122  kitTray = it->second;
123  return true;
124 }
125 
128 {
129  auto trayScore = ScoreTray(tray);
130  ROS_DEBUG_STREAM("Score from tray '" << tray.trayID << "': " << trayScore.total());
131  this->goalScore->trayScores[tray.trayID] = trayScore;
132  return trayScore;
133 }
134 
137 {
138  ariac::Kit kit = tray.currentKit;
139  ariac::KitType_t kitType = tray.currentKit.kitType;
140  ariac::TrayScore score;
141  if (this->currentGoal.kits.find(kitType) == this->currentGoal.kits.end())
142  {
143  ROS_DEBUG_STREAM("No known kit type: " << kitType);
144  return score;
145  }
146  ariac::Kit assignedKit = this->currentGoal.kits[kitType];
147  auto numAssignedObjects = assignedKit.objects.size();
148  ROS_DEBUG_STREAM("Comparing the " << numAssignedObjects <<
149  " assigned objects with the current " <<
150  kit.objects.size() << " objects");
151 
152  // Count the number of each type of assigned object
153  std::map<std::string, unsigned int> assignedObjectTypeCount, currentObjectTypeCount;
154  for (const auto & obj : assignedKit.objects)
155  {
156  if (assignedObjectTypeCount.find(obj.type) == assignedObjectTypeCount.end())
157  {
158  assignedObjectTypeCount[obj.type] = 0;
159  }
160  assignedObjectTypeCount[obj.type] += 1;
161  }
162 
163  ROS_DEBUG_STREAM("Checking object counts");
164 
165  bool assignedObjectsMissing = false;
166  for (auto & value : assignedObjectTypeCount)
167  {
168  auto assignedObjectType = value.first;
169  auto assignedObjectCount = value.second;
170  auto currentObjectCount =
171  std::count_if(kit.objects.begin(), kit.objects.end(),
172  [assignedObjectType](ariac::KitObject k) {return k.type == assignedObjectType;});
173  ROS_DEBUG_STREAM("Found " << currentObjectCount <<
174  " objects of type '" << assignedObjectType << "'");
175  score.partPresence +=
176  std::min(long(assignedObjectCount), currentObjectCount) * scoringParameters.objectPresence;
177  if (currentObjectCount < assignedObjectCount)
178  {
179  assignedObjectsMissing = true;
180  }
181  }
182  if (!assignedObjectsMissing)
183  {
184  ROS_DEBUG_STREAM("All objects on tray");
185  score.allPartsBonus += scoringParameters.allObjectsBonusFactor * numAssignedObjects;
186  }
187 
188  ROS_DEBUG_STREAM("Checking object poses");
189  // Keep track of which assigned objects have already been 'matched' to one on the tray.
190  // This is to prevent multiple objects being close to a single target pose both scoring points.
191  std::vector<ariac::KitObject> remainingAssignedObjects(assignedKit.objects);
192 
193  for (const auto & currentObject : kit.objects)
194  {
195  for (auto it = remainingAssignedObjects.begin(); it != remainingAssignedObjects.end(); ++it)
196  {
197  // Only check poses of parts of the same type
198  auto assignedObject = *it;
199  if (assignedObject.type != currentObject.type)
200  continue;
201 
202  // Check the position of the object (ignoring orientation)
203  ROS_DEBUG_STREAM("Comparing pose '" << currentObject.pose <<
204  "' with the assigned pose '" << assignedObject.pose << "'");
205  gazebo::math::Vector3 posnDiff = assignedObject.pose.CoordPositionSub(currentObject.pose);
206  posnDiff.z = 0;
207  if (posnDiff.GetLength() > scoringParameters.distanceThresh)
208  continue;
209  ROS_DEBUG_STREAM("Object of type '" << currentObject.type <<
210  "' in the correct position");
212 
213  // Check the orientation of the object.
214  gazebo::math::Quaternion objOrientation = currentObject.pose.rot;
215  gazebo::math::Quaternion goalOrientation = assignedObject.pose.rot;
216 
217  // Filter objects that aren't in the appropriate orientation (loosely).
218  // If the quaternions represent the same orientation, q1 = +-q2 => q1.dot(q2) = +-1
219  double orientationDiff = objOrientation.Dot(goalOrientation);
220  // TODO: this value can probably be derived using relationships between
221  // euler angles and quaternions.
222  double quaternionDiffThresh = 0.05;
223  if (std::abs(orientationDiff) < (1.0 - quaternionDiffThresh))
224  continue;
225 
226  // Now filter the poses based on a threshold set in radians (more user-friendly).
227  double yawDiff = objOrientation.GetYaw() - goalOrientation.GetYaw();
228  if (std::abs(yawDiff) > scoringParameters.orientationThresh)
229  continue;
230 
231  ROS_DEBUG_STREAM("Object of type '" << currentObject.type <<
232  "' in the correct orientation");
234 
235  // Once a match is found, don't permit it to be matched again
236  remainingAssignedObjects.erase(it);
237  break;
238  }
239  }
240 
241  // Check if all assigned objects have been matched to one on the tray
242  if (remainingAssignedObjects.empty())
243  {
244  score.isComplete = true;
245  }
246 
247  return score;
248 }
249 
251 void AriacScorer::OnTrayInfoReceived(const osrf_gear::KitTray::ConstPtr & trayMsg)
252 {
253  boost::mutex::scoped_lock kitTraysLock(this->kitTraysMutex);
254 
255  // Get the ID of the tray that the message is from.
256  std::string trayID = trayMsg->tray.data;
257 
258  if (this->kitTrays.find(trayID) == this->kitTrays.end())
259  {
260  // This is the first time we've heard from this tray: initialize it.
261  this->kitTrays[trayID] = ariac::KitTray(trayID);
262  }
263 
264  // Update the state of the tray.
265  // TODO: this should be moved outside of the callback
266  // Do this even if the tray isn't part of the current goal because maybe it
267  // will be part of future goals.
268  this->newTrayInfoReceived = true;
269  ariac::Kit kitState;
270  FillKitFromMsg(trayMsg->kit, kitState);
271  this->kitTrays[trayID].UpdateKitState(kitState);
272 }
273 
275 void AriacScorer::OnGoalReceived(const osrf_gear::Goal::ConstPtr & goalMsg)
276 {
277  ROS_DEBUG("Received a goal");
278  this->newGoalReceived = true;
279 
280  ariac::Goal goal;
281  goal.goalID = goalMsg->goal_id.data;
282  for (const auto & kitMsg : goalMsg->kits)
283  {
284  ariac::KitType_t kitType = kitMsg.kit_type.data;
285  ariac::Kit assignedKit;
286  FillKitFromMsg(kitMsg, assignedKit);
287  goal.kits[kitType] = assignedKit;
288  }
289  this->newGoal = goal;
290 }
291 
294 {
295  ariac::GoalID_t goalID = goal.goalID;
296  if (this->gameScore.goalScores.find(goalID) == this->gameScore.goalScores.end())
297  {
298  // This is a previously unseen goal: start scoring from scratch
299  this->gameScore.goalScores[goalID] = ariac::GoalScore();
300  this->gameScore.goalScores[goalID].goalID = goalID;
301  }
302  this->goalScore = &this->gameScore.goalScores[goalID];
303 
304  this->currentGoal = goal;
305 }
306 
309 {
310  auto goalScore = *this->goalScore;
311  goalScore.timeTaken = timeTaken;
312  this->currentGoal.kits.clear();
313  return goalScore;
314 }
315 
317 void AriacScorer::FillKitFromMsg(const osrf_gear::Kit &kitMsg, ariac::Kit &kit)
318 {
319  kit.objects.clear();
320  for (const auto & objMsg : kitMsg.objects)
321  {
322  ariac::KitObject obj;
323  obj.type = ariac::DetermineModelType(objMsg.type);
324  geometry_msgs::Point p = objMsg.pose.position;
325  geometry_msgs::Quaternion o = objMsg.pose.orientation;
326  gazebo::math::Vector3 objPosition(p.x, p.y, p.z);
327  gazebo::math::Quaternion objOrientation(o.w, o.x, o.y, o.z);
328  obj.pose = gazebo::math::Pose(objPosition, objOrientation);
329  kit.objects.push_back(obj);
330  }
331 }
332 
334 void AriacScorer::OnGripperStateReceived(const osrf_gear::VacuumGripperState &stateMsg)
335 {
336  this->isPartTravelling = stateMsg.enabled && stateMsg.attached;
337 }
std::vector< KitObject > objects
A kit is composed of multiple objects.
Definition: ARIAC.hh:287
Class to store information about a goal.
Definition: ARIAC.hh:291
void AssignGoal(const ariac::Goal &goal)
Assign a goal to process.
double allPartsBonus
Definition: ARIAC.hh:56
std::string TrayID_t
Definition: ARIAC.hh:32
bool isPartTravelling
Whether or not there is a travelling part in the gripper.
Definition: AriacScorer.h:112
void ScoreCurrentState()
Calculate the score for the trays given the objects in them.
Definition: AriacScorer.cpp:85
bool newGoalReceived
Flag for signalling new goal to process.
Definition: AriacScorer.h:109
std::map< TrayID_t, TrayScore > trayScores
Mapping between tray IDs and scores.
Definition: ARIAC.hh:90
std::map< ariac::TrayID_t, ariac::KitTray > kitTrays
The trays to monitor the score of.
Definition: AriacScorer.h:97
void Update(double timeStep=0.0)
Update the scorer.
Definition: AriacScorer.cpp:49
std::string type
Object type.
Definition: ARIAC.hh:258
void OnGripperStateReceived(const osrf_gear::VacuumGripperState &stateMsg)
Callback for receiving gripper state message.
static void FillKitFromMsg(const osrf_gear::Kit &kitMsg, ariac::Kit &kit)
Helper function for filling a Kit from a kit ROS message.
ariac::GoalScore UnassignCurrentGoal(double timeTaken=0.0)
Stop processing the current goal.
Kit currentKit
The current state of the kit on the tray.
Definition: AriacKitTray.h:45
double partTravelTime
Definition: ARIAC.hh:150
ariac::Goal newGoal
Goal receivd from goal messages.
Definition: AriacScorer.h:115
The score of a tray.
Definition: ARIAC.hh:36
bool newTrayInfoReceived
Flag for signalling new tray info to process.
Definition: AriacScorer.h:106
ariac::GoalScore * goalScore
Pointer to the score of the current goal.
Definition: AriacScorer.h:121
std::string GoalID_t
Definition: ARIAC.hh:33
math::Pose pose
Pose in which the object should be placed.
Definition: ARIAC.hh:261
void OnTrayInfoReceived(const osrf_gear::KitTray::ConstPtr &trayMsg)
Callback for receiving tray state message.
std::string trayID
The ID of the tray.
Definition: AriacKitTray.h:42
Class to store information about each object contained in a kit.
Definition: ARIAC.hh:241
ariac::ScoringParameters scoringParameters
Parameters to use for calculating scores.
Definition: AriacScorer.h:118
bool IsCurrentGoalComplete()
Get the score of the current goal.
Definition: AriacScorer.cpp:79
std::map< KitType_t, Kit > kits
A goal is composed of multiple kits of different types.
Definition: ARIAC.hh:332
bool isComplete() const
Calculate if the goal is complete.
Definition: ARIAC.hh:101
The score of a competition run.
Definition: ARIAC.hh:128
ariac::GameScore gameScore
The score of the run.
Definition: AriacScorer.h:124
double timeTaken
Time in seconds spend on the goal.
Definition: ARIAC.hh:96
void OnGoalReceived(const osrf_gear::Goal::ConstPtr &goalMsg)
Callback for receiving goal message.
ariac::TrayScore SubmitTray(const ariac::KitTray &tray)
Submit tray for scoring and store the result in the goal score.
std::map< GoalID_t, GoalScore > goalScores
Definition: ARIAC.hh:156
virtual ~AriacScorer()
Destructor.
Definition: AriacScorer.cpp:32
#define ROS_DEBUG_STREAM(args)
bool isComplete
Definition: ARIAC.hh:58
GoalID_t goalID
The ID of this goal.
Definition: ARIAC.hh:322
ariac::GoalScore GetCurrentGoalScore()
Get the score of the current goal.
Definition: AriacScorer.cpp:43
std::string KitType_t
Definition: ARIAC.hh:31
double allObjectsBonusFactor
Definition: ARIAC.hh:208
#define ROS_INFO_STREAM(args)
bool GetTrayById(const ariac::TrayID_t &trayID, ariac::KitTray &kitTray)
Get the kit tray with the specified ID.
TrayID_t DetermineModelType(const std::string &modelName)
Determine the type of a gazebo model from its name.
Definition: ARIAC.hh:222
The score of a goal.
Definition: ARIAC.hh:68
double partPresence
Definition: ARIAC.hh:55
Class to store information about a kit.
Definition: ARIAC.hh:266
ariac::TrayScore ScoreTray(const ariac::KitTray &tray)
Calculate the score for a tray given the type of kit being built.
double partPose
Definition: ARIAC.hh:57
boost::mutex kitTraysMutex
Mutex for protecting the kit trays being monitored.
Definition: AriacScorer.h:100
AriacScorer()
Constructor.
Definition: AriacScorer.cpp:27
KitType_t kitType
The type of the kit.
Definition: ARIAC.hh:284
ariac::Goal currentGoal
Current goal being monitored.
Definition: AriacScorer.h:103
ariac::GameScore GetGameScore()
Get the current score.
Definition: AriacScorer.cpp:37
Class to store information about a kit tray.
Definition: AriacKitTray.h:25
#define ROS_DEBUG(...)


osrf_gear
Author(s):
autogenerated on Wed Sep 7 2016 03:48:12