RcsPySim
A robot control and simulation library
ObservationModel.h
Go to the documentation of this file.
1 /*******************************************************************************
2  Copyright (c) 2020, Fabio Muratore, Honda Research Institute Europe GmbH, and
3  Technical University of Darmstadt.
4  All rights reserved.
5 
6  Redistribution and use in source and binary forms, with or without
7  modification, are permitted provided that the following conditions are met:
8  1. Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  2. Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  3. Neither the name of Fabio Muratore, Honda Research Institute Europe GmbH,
14  or Technical University of Darmstadt, nor the names of its contributors may
15  be used to endorse or promote products derived from this software without
16  specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL FABIO MURATORE, HONDA RESEARCH INSTITUTE EUROPE GMBH,
22  OR TECHNICAL UNIVERSITY OF DARMSTADT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  POSSIBILITY OF SUCH DAMAGE.
29 *******************************************************************************/
30 
31 #ifndef _OBSERVATIONMODEL_H_
32 #define _OBSERVATIONMODEL_H_
33 
34 #include "../util/BoxSpaceProvider.h"
35 
36 #include <Rcs_MatNd.h>
37 #include <Rcs_graph.h>
38 
39 namespace Rcs
40 {
41 
42 /**
43  * The ObservationModel encapsulates the computation of the state vector from the current graph state.
44  */
46 {
47 public:
48 
49  virtual ~ObservationModel();
50 
51  /**
52  * Create a MatNd for the observation vector, fill it using computeObservation and return it.
53  * The caller must take ownership of the returned matrix.
54  * @param[in] currentAction action in current step. May be NULL if not available.
55  * @param[in] dt time step since the last observation has been taken
56  * @return a new observation vector
57  */
58  MatNd* computeObservation(const MatNd* currentAction, double dt) const;
59 
60  /**
61  * Fill the given matrix with observation data.
62  * @param[out] observation observation output vector
63  * @param[in] currentAction action in current step. May be NULL if not available.
64  * @param[in] dt time step since the last observation has been taken
65  */
66  void computeObservation(MatNd* observation, const MatNd* currentAction, double dt) const;
67 
68  /**
69  * The number of state variables.
70  */
71  virtual unsigned int getStateDim() const = 0;
72 
73  /**
74  * The number of velocity variables.
75  * The default implementation assumes that for each state there is a velocity.
76  */
77  virtual unsigned int getVelocityDim() const;
78 
79  /**
80  * Implement to fill the observation vector with the observed values.
81  * @param[out] state state observation vector to fill, has getStateDim() elements.
82  * @param[out] velocity velocity observation vector to fill, has getVelocityDim() elements.
83  * @param[in] currentAction action in current step. May be NULL if not available.
84  * @param[in] dt time step since the last observation has been taken
85  */
86  virtual void computeObservation(double* state, double* velocity, const MatNd* currentAction, double dt) const = 0;
87 
88  /**
89  * Provides the minimum and maximum observable values.
90  * Since the velocity is symmetric, only the maximum needs to be provided.
91  * The default implementation uses -inf and inf.
92  * @param[out] minState minimum state vector to fill, has getStateDim() elements.
93  * @param[out] maxState maximum state vector to fill, has getStateDim() elements.
94  * @param[out] maxVelocity maximum velocity vector to fill, has getVelocityDim() elements.
95  */
96  virtual void getLimits(double* minState, double* maxState, double* maxVelocity) const;
97 
98  /**
99  * Reset any internal state. This is called to begin a new episode.
100  * It should also reset values depending on modifiable physics parameters.
101  * This is an optional operation, so the default implementation does nothing.
102  */
103  virtual void reset();
104 
105  /**
106  * Provides names for each state entry.
107  * @return a vector of name strings. Must be of length getStateDim() or empty for a nameless space.
108  */
109  virtual std::vector<std::string> getStateNames() const;
110 
111  /**
112  * Provides names for each velocity entry.
113  * The default implementation derives the names from getStateNames(), appending a 'd' to each name.
114  *
115  * @return a vector of name strings. Must be of length getVelocityDim() or empty for a nameless space.
116  */
117  virtual std::vector<std::string> getVelocityNames() const;
118 
119  // These functions should not be overridden in subclasses!
120  /**
121  * Provides the minimum and maximum observable values.
122  * Delegates to getLimits.
123  */
124  virtual void getMinMax(double* min, double* max) const final;
125 
126  /**
127  * The number of observed variables is twice the number of state variables.
128  * Delegates to getStateDim.
129  */
130  virtual unsigned int getDim() const final;
131 
132  /**
133  * The velocity names are the state names postfixed with 'd'.
134  * Delegates to getStateNames.
135  */
136  virtual std::vector<std::string> getNames() const final;
137 
138  /**
139  * Find a nested observation model of a specified type.
140  * If multiple observation models match, the first found in depth-first search order is returned.
141  * @tparam OM observation model type to find
142  * @return nested observation model or NULL if not found.
143  */
144  template<typename OM>
145  OM* findModel()
146  {
147  auto dc = dynamic_cast<OM*>(this);
148  if (dc) {
149  return dc;
150  }
151  for (auto nested : getNested()) {
152  dc = nested->findModel<OM>();
153  if (dc) {
154  return dc;
155  }
156  }
157  return NULL;
158  }
159 
160  //! result of findOffsets
161  struct Offsets
162  {
163  int pos;
164  int vel;
165 
166  operator bool() const
167  {
168  return pos >= 0;
169  }
170  };
171 
172  /**
173  * Find a nested observation model of a specified type.
174  * If multiple observation models match, the first found in depth-first search order is returned.
175  * NOTE: the positions and velovities are done separately. In order to correct for masked state observations use
176  * `observationModel->getStateDim() + thisOM.vel + i` to get the index.
177  * @tparam OM observation model type to find
178  * @return nested observation model or NULL if not found.
179  */
180  template<typename OM>
182  {
183  Offsets local = {0, 0};
184  auto dc = dynamic_cast<OM*>(this);
185  if (dc) {
186  return local;
187  }
188  for (auto nested : getNested()) {
189  auto no = nested->findOffsets<OM>();
190  if (no) {
191  return {local.pos + no.pos, local.vel + no.vel};
192  }
193 
194  local.pos += nested->getStateDim();
195  local.vel += nested->getVelocityDim();
196  }
197  return {-1, -1};
198  }
199 
200  /**
201  * List directly nested observation models.
202  * The default implementation returns an empty list, since there are no nested models.
203  */
204  virtual std::vector<ObservationModel*> getNested() const;
205 };
206 
207 } /* namespace Rcs */
208 
209 #endif /* _OBSERVATIONMODEL_H_ */
virtual ~ObservationModel()
virtual std::vector< std::string > getStateNames() const
virtual std::vector< ObservationModel * > getNested() const
virtual std::vector< std::string > getVelocityNames() const
virtual void getMinMax(double *min, double *max) const final
MatNd * computeObservation(const MatNd *currentAction, double dt) const
virtual unsigned int getVelocityDim() const
virtual unsigned int getStateDim() const =0
virtual void getLimits(double *minState, double *maxState, double *maxVelocity) const
virtual std::vector< std::string > getNames() const final
virtual unsigned int getDim() const final