RobTranslation.RobTranslationProxy Class Reference

Proxy class for a DocumentObjectGroupPython RobTranslation instance. More...

Public Member Functions

def __init__ (self, fp)
 Initialization method for RobTranslationProxy. More...
 
def onChanged (self, fp, prop)
 Method called after DocumentObjectGroupPython RobTranslation was changed. More...
 
def execute (self, fp)
 Method called when recomputing a DocumentObjectGroupPython. More...
 
def onDocumentRestored (self, fp)
 Method called when document is restored to make sure everything is as it was. More...
 
def setProperties (self, fp)
 Method to set properties during initialization or document restoration. More...
 
def change_joint_sequence (self, joint_sequence)
 Method used to change a RobTranslation's joint variable sequence. More...
 
def is_translation_property (self, prop)
 Method to check that a property describes a translation. More...
 
def is_ValidTranslation (self, timestamps=[], ds=[], translation=None)
 Method to check if a translation is valid. More...
 
def find_timestamp_indices_and_weights (self, fp)
 Method to find weighted timestamps indices corresponding to a given time. More...
 
def __getstate__ (self)
 Necessary method to avoid errors when trying to save unserializable objects. More...
 
def __setstate__ (self, state)
 Necessary method to avoid errors when trying to restore unserializable objects. More...
 

Public Attributes

 updated
 
 fp
 A DocumentObjectGroupPython associated with the proxy. More...
 

Static Public Attributes

bool updated = False
 A bool - True if a property was changed by a class and not user. More...
 

Detailed Description

Proxy class for a DocumentObjectGroupPython RobTranslation instance.

A RobTranslationProxy instance adds properties to a DocumentObjectGroupPython RobTranslation instance and responds to their changes. It provides a RobotPanel to be able to see an object in a displacement range.

To connect a Proxy object to a DocumentObjectGroupPython RobTranslation do:

a = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroupPython",
"RobTranslation")
RobTranslationProxy(a)

Definition at line 71 of file RobTranslation.py.

Constructor & Destructor Documentation

◆ __init__()

def RobTranslation.RobTranslationProxy.__init__ (   self,
  fp 
)

Initialization method for RobTranslationProxy.

A class instance is created and made a Proxy for a generic DocumentObjectGroupPython RobTranslation object. During initialization number of properties are specified and preset.

Parameters
fpA DocumentObjectGroupPython RobTranslation object to be extended.

Definition at line 91 of file RobTranslation.py.

91  def __init__(self, fp):
92  # Add (and preset) properties
93  self.setProperties(fp)
94  fp.Proxy = self
95 

Member Function Documentation

◆ __getstate__()

def RobTranslation.RobTranslationProxy.__getstate__ (   self)

Necessary method to avoid errors when trying to save unserializable objects.

This method is used by JSON to serialize unserializable objects during autosave. Without this an Error would rise when JSON would try to do that itself.

We need this for unserializable fp attribute, but we don't serialize it, because it's enough to reset it when object is restored.

Returns
None, because we don't serialize anything.

Definition at line 546 of file RobTranslation.py.

546  def __getstate__(self):
547  return None
548 

◆ __setstate__()

def RobTranslation.RobTranslationProxy.__setstate__ (   self,
  state 
)

Necessary method to avoid errors when trying to restore unserializable objects.

This method is used during a document restoration. We need this for unserializable fp attribute, but we do not restore it, because it's enough to reset them from saved parameters.

Returns
None, because we don't restore anything.

Definition at line 559 of file RobTranslation.py.

559  def __setstate__(self, state):
560  return None
561 
562 

◆ change_joint_sequence()

def RobTranslation.RobTranslationProxy.change_joint_sequence (   self,
  joint_sequence 
)

Method used to change a RobTranslation's joint variable sequence.

A joint_sequence dictionary containing a translation is tested for validity and then assigned to a RobTranslation DocumentObjectGroupPython.

Parameters
fpA DocumentObjectGroupPython RobTranslation object.
joint_sequenceA dictionary describing a RobTranslation.

Definition at line 411 of file RobTranslation.py.

411  def change_joint_sequence(self, joint_sequence):
412  # Check that RobTranslation has a correct format and load it
413  if self.is_ValidTranslation(translation=joint_sequence):
414  self.fp.Timestamps = joint_sequence["Timestamps"]
415  self.fp.dSequence = joint_sequence["dSequence"]
416  else:
417  FreeCAD.Console.PrintError("Invalid joint sequence!")
418 

◆ execute()

def RobTranslation.RobTranslationProxy.execute (   self,
  fp 
)

Method called when recomputing a DocumentObjectGroupPython.

New placement is computed, if a RobotPanel is active or it is not active, but rotation is valid. The current pose in a parent coordinate frame is computed using DH parameters. At last ObjectPlacement and Placement are updated accordingly.

Parameters
fpA DocumentObjectGroupPython RobTranslation object.

Definition at line 161 of file RobTranslation.py.

161  def execute(self, fp):
162  # Check that joint is not controlled by a RobotPanel
163  if not fp.RobotPanelActive:
164  # Check that current translation has valid format
165  if not fp.ValidTranslation:
166  FreeCAD.Console.PrintWarning(fp.Name +
167  ".execute(): Translation " +
168  "is not in a valid format.\n")
169  return
170 
171  # Update d according to current time and translation
172  indices, weights = self.find_timestamp_indices_and_weights(fp)
173 
174  fp.d = fp.dOffset + (weights[0]*fp.dSequence[indices[0]]
175  + weights[1]*fp.dSequence[indices[1]])
176 
177  # DH transformation
178  T_theta = FreeCAD.Placement(FreeCAD.Vector(0, 0, 0),
179  FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1),
180  fp.theta))
181  T_d = FreeCAD.Placement(FreeCAD.Vector(0, 0, fp.d),
182  FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 0))
183  T_a = FreeCAD.Placement(FreeCAD.Vector(fp.a, 0, 0),
184  FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0), 0))
185  T_alpha = FreeCAD.Placement(FreeCAD.Vector(0, 0, 0),
186  FreeCAD.Rotation(FreeCAD.Vector(1, 0, 0),
187  fp.alpha))
188 
189  fp.ObjectPlacement = T_theta.multiply(T_d.multiply(
190  T_a.multiply(T_alpha)))
191 
192  # Placement update
193  fp.Placement = fp.ParentFramePlacement.multiply(fp.ObjectPlacement)
194 

◆ find_timestamp_indices_and_weights()

def RobTranslation.RobTranslationProxy.find_timestamp_indices_and_weights (   self,
  fp 
)

Method to find weighted timestamps indices corresponding to a given time.

If a time is smaller than the first timestamp, the returned indices are [0,0] with weights [1,0] as that's the closest value. Similarly, if the time is greater than the last timestamp, the returned indices are [-1,-1] pointing to the last element of a timestamps list with weights [1,0]. If the time value is between the first and last timestamp, the indices belong to the closest higher and lower time. At the same time, if interpolation is off, the weights are 0 and 1, where one is given to the index closest to the time. Otherwise, the weights, whose sum equals to 1, are computed to show inverse relative distance i.e. an index with a greater weight is the closer.

Parameters
fpA DocumentObjectGroupPython RobTranslation object.
Returns
indices A list of two integers between -1 and and length of Timestamps.
weights A list of two floats between 0 and 1 showing relative closeness.

Definition at line 503 of file RobTranslation.py.

503  def find_timestamp_indices_and_weights(self, fp):
504  # Retrieve indices corresponding to current time
505  # If the time is before the first Timestamp use the first Timestamp
506  if fp.Time <= fp.Timestamps[0]:
507  indices = [0, 0]
508  weights = [1, 0]
509 
510  # If the time is after the last Timpestamp use the last Timestamp
511  elif fp.Time >= fp.Timestamps[-1]:
512  indices = [-1, -1]
513  weights = [1, 0]
514 
515  # If time is in the range of Timesteps
516  else:
517  # Find the index of the closest higher value
518  indices = [bisect(fp.Timestamps, fp.Time)]
519  # Add the previous index
520  indices.insert(0, indices[0]-1)
521  weights = [fp.Timestamps[indices[1]] - fp.Time,
522  fp.Time - fp.Timestamps[indices[0]]]
523  if not fp.Interpolate:
524  if weights[0] > weights[1]:
525  weights = [1, 0]
526  else:
527  weights = [0, 1]
528  else:
529  weights = [weights[0]/sum(weights), weights[1]/sum(weights)]
530 
531  return indices, weights
532 

◆ is_translation_property()

def RobTranslation.RobTranslationProxy.is_translation_property (   self,
  prop 
)

Method to check that a property describes a translation.

It's checked whether prop is Timestamps or dSequence.

Parameters
propA str name of a changed property.
Returns
True if prop describes a translation and False otherwise.

Definition at line 430 of file RobTranslation.py.

430  def is_translation_property(self, prop):
431  return prop in ["Timestamps", "dSequence"]
432 

◆ is_ValidTranslation()

def RobTranslation.RobTranslationProxy.is_ValidTranslation (   self,
  timestamps = [],
  ds = [],
  translation = None 
)

Method to check if a translation is valid.

This method needs either a translation dictionary argument or all the other lists of floats. A valid translation needs to have all the necessary lists. All the lists must have same length. A timestamps list must consist of a sequence of strictly increasing floats. A displacement cannot exceed joint limits.

Parameters
timestampsA list of floats marking timestamps.
dsA list of floats signifying translation diplacements along Z axis.
translationA dict containing all lists above.
Returns
True if translation is valid and False otherwise.

Definition at line 450 of file RobTranslation.py.

450  def is_ValidTranslation(self, timestamps=[], ds=[], translation=None):
451  # Check all keys are included and record lengths of their lists
452  if translation is not None and isinstance(translation, dict):
453  for key in ["Timestamps", "dSequence"]:
454  if key not in translation.keys():
455  FreeCAD.Console.PrintWarning("Translation misses key " +
456  key + ".\n")
457  return False
458  timestamps = translation["Timestamps"]
459  ds = translation["dSequence"]
460 
461  # Check that all lists have the same length
462  if len(timestamps) == 0 or \
463  (len(timestamps) != 0 and len(timestamps) != len(ds)):
464  FreeCAD.Console.PrintWarning("Translation has lists with "
465  + "inconsistent or zero "
466  + "lengths.\n")
467  return False
468 
469  # Check timestamps correspond to list of increasing values
470  if any([timestamps[i] >= timestamps[i+1]
471  for i in range(len(timestamps)-1)]):
472  FreeCAD.Console.PrintWarning("Translation 'Timestamps' is not "
473  + "list of increasing values.\n")
474  return False
475 
476  if not all([self.fp.dMinimum <= d <= self.fp.dMaximum for d in ds]):
477  FreeCAD.Console.PrintWarning("Translation 'dSequence' elements"
478  + " are out of d range.\n")
479  return False
480 
481  return True
482 

◆ onChanged()

def RobTranslation.RobTranslationProxy.onChanged (   self,
  fp,
  prop 
)

Method called after DocumentObjectGroupPython RobTranslation was changed.

A translation is checked for its validity. If the Placement property is changed, then ParentFramePlacement property of a RobTranslation children is set to equal the new Placement. If the ParentFramePlacement is changed, then the Placement property is changed.

Parameters
fpA DocumentObjectGroupPython RobTranslation object.
propA str name of a changed property.

Definition at line 108 of file RobTranslation.py.

108  def onChanged(self, fp, prop):
109  # Ignore updates to ranges
110  if self.updated:
111  self.updated = False
112  return
113 
114  # Control allowed theta range limits
115  elif prop == "dMinimum" and hasattr(fp, "dMaximum"):
116  self.updated = True
117  fp.dMaximum = (fp.dMaximum, fp.dMinimum, float("inf"), 1)
118  elif prop == "dMaximum" and hasattr(fp, "dMinimum"):
119  self.updated = True
120  fp.dMinimum = (fp.dMinimum, -float("inf"), fp.dMaximum, 1)
121 
122  # Check that a translation has valid format
123  elif self.is_translation_property(prop) and \
124  hasattr(fp, "dMaximum") and \
125  hasattr(fp, "dMinimum") and \
126  hasattr(self, "fp"):
127  trans_valid = self.is_ValidTranslation(fp.Timestamps, fp.dSequence)
128  if trans_valid != fp.ValidTranslation:
129  fp.ValidTranslation = trans_valid
130 
131  elif prop == "Placement":
132  # Propagate the Placement updates down the chain
133  if hasattr(fp, "Group") and len(fp.Group) != 0:
134  for child in fp.Group:
135  child.ParentFramePlacement = fp.Placement
136  child.purgeTouched()
137 
138  # Display animated objects in a pose specified by the rotation
139  # and current time
140  if hasattr(fp, "AnimatedObjects") and len(fp.AnimatedObjects) != 0:
141  for o in fp.AnimatedObjects:
142  o.Placement = fp.Placement
143  o.purgeTouched()
144 
145  elif prop == "ParentFramePlacement":
146  # If parent frame changed, recompute placement
147  fp.Placement = fp.ParentFramePlacement.multiply(
148  fp.ObjectPlacement)
149 

◆ onDocumentRestored()

def RobTranslation.RobTranslationProxy.onDocumentRestored (   self,
  fp 
)

Method called when document is restored to make sure everything is as it was.

Reinitialization it creates properties and sets them to default, if they were not restored automatically. Properties of connected ViewObject are also recreated and reset if necessary.

Parameters
fpA restored DocumentObjectGroupPython RobTranslation object.

Definition at line 205 of file RobTranslation.py.

205  def onDocumentRestored(self, fp):
206  fp.ViewObject.Proxy.setProperties(fp.ViewObject)
207  self.setProperties(fp)
208 

◆ setProperties()

def RobTranslation.RobTranslationProxy.setProperties (   self,
  fp 
)

Method to set properties during initialization or document restoration.

The properties are set if they are not already present and an AnimateDocumentObserver is recreated.

Parameters
fpA restored or barebone RobTranslation object.

Definition at line 219 of file RobTranslation.py.

219  def setProperties(self, fp):
220  # Add (and preset) properties
221  # Animation properties
222  if not hasattr(fp, "ValidTranslation"):
223  fp.addProperty("App::PropertyBool", "ValidTranslation", "General",
224  "This property records if rotation was changed."
225  ).ValidTranslation = False
226  if not hasattr(fp, "RobotPanelActive"):
227  fp.addProperty("App::PropertyBool", "RobotPanelActive", "General",
228  "This property records if robot panel is active."
229  ).RobotPanelActive = False
230  if not hasattr(fp, "AnimatedObjects"):
231  fp.addProperty("App::PropertyLinkListGlobal", "AnimatedObjects",
232  "General", "Objects that will be animated.")
233  if not hasattr(fp, "Interpolate"):
234  fp.addProperty("App::PropertyBool", "Interpolate", "General",
235  "Interpolate RobTranslation between timestamps."
236  ).Interpolate = True
237  if not hasattr(fp, "AllowServer"):
238  fp.addProperty("App::PropertyBool", "AllowServer", "General",
239  "Should this object allow a Server object to "
240  + "change it.").AllowServer = True
241  if not hasattr(fp, "AllowControl"):
242  fp.addProperty("App::PropertyBool", "AllowControl", "General",
243  "Should this object allow a Control object "
244  + " to change it."
245  ).AllowControl = True
246  if not hasattr(fp, "Time"):
247  fp.addProperty("App::PropertyFloat", "Time", "General",
248  "Animation time in seconds.").Time = 0
249  if not hasattr(fp, "ParentFramePlacement"):
250  fp.addProperty("App::PropertyPlacement", "ParentFramePlacement",
251  "General", "Current placement of a Parent Frame.")
252  if not hasattr(fp, "ObjectPlacement"):
253  fp.addProperty("App::PropertyPlacement", "ObjectPlacement",
254  "General",
255  "Current Object placement in a Parent Frame.")
256 
257  # DH parameters
258  if not hasattr(fp, "d"):
259  fp.addProperty("App::PropertyFloat", "d", "d-hParameters",
260  "Displacement along Z axis.").d = 0
261  if not hasattr(fp, "dMaximum"):
262  fp.addProperty("App::PropertyFloatConstraint", "dMaximum",
263  "d-hParameters", "Upper limit of displacement"
264  + " along Z axis."
265  ).dMaximum = (1000, 0, float("inf"), 1)
266  elif hasattr(fp, "dMinimum"):
267  fp.dMaximum = (fp.dMaximum, fp.dMinimum, float("inf"), 1)
268  if not hasattr(fp, "dMinimum"):
269  fp.addProperty("App::PropertyFloatConstraint", "dMinimum",
270  "d-hParameters", "Lower limit of displacement"
271  + " alon Z axis."
272  ).dMinimum = (0, -float("inf"), 1000, 1)
273  elif hasattr(fp, "dMaximum"):
274  fp.dMinimum = (fp.dMinimum, -float("inf"), fp.dMaximum, 1)
275  if not hasattr(fp, "dOffset"):
276  fp.addProperty("App::PropertyFloat", "dOffset",
277  "d-hParameters", "Offset of displacement"
278  + " along Z axis.").dOffset = 0
279  if not hasattr(fp, "a"):
280  fp.addProperty("App::PropertyFloat", "a", "d-hParameters",
281  "Displacement along X axis.").a = 0
282  if not hasattr(fp, "alpha"):
283  fp.addProperty("App::PropertyFloat", "alpha", "d-hParameters",
284  "Rotation angle about X axis in degrees.").alpha = 0
285  if not hasattr(fp, "theta"):
286  fp.addProperty("App::PropertyFloat", "theta", "d-hParameters",
287  "Rotation angle about X axis in degrees.").theta = 0
288 
289  # Frame properties
290  if not hasattr(fp, "ShowFrame"):
291  fp.addProperty("App::PropertyBool", "ShowFrame", "Frame",
292  "Show a frame for current pose."
293  ).ShowFrame = True
294  if not hasattr(fp, "FrameTransparency"):
295  fp.addProperty("App::PropertyPercent", "FrameTransparency",
296  "Frame", "Transparency of the frame in percents."
297  ).FrameTransparency = 0
298  if not hasattr(fp, "ShowFrameArrowheads"):
299  fp.addProperty("App::PropertyBool", "ShowFrameArrowheads", "Frame",
300  "Show arrowheads for frame axis arrow's."
301  ).ShowFrameArrowheads = True
302  if not hasattr(fp, "FrameArrowheadLength"):
303  fp.addProperty("App::PropertyFloatConstraint",
304  "FrameArrowheadLength", "Frame",
305  "Frame axis arrow's arrowhead length.\n"
306  + "Range is < 1.0 | 1e6 >."
307  ).FrameArrowheadLength = (10, 1.0, 1e6, 1)
308  else:
309  fp.FrameArrowheadLength = (fp.FrameArrowheadLength, 1.0, 1e6, 1)
310  if not hasattr(fp, "FrameArrowheadRadius"):
311  fp.addProperty("App::PropertyFloatConstraint",
312  "FrameArrowheadRadius", "Frame",
313  "Frame axis arrow's arrowhead bottom radius.\n"
314  + "Range is < 0.5 | 1e6 >."
315  ).FrameArrowheadRadius = (5, 0.5, 1e6, 0.5)
316  else:
317  fp.FrameArrowheadRadius = (fp.FrameArrowheadRadius, 0.5, 1e6, 0.5)
318  if not hasattr(fp, "ShaftLength"):
319  fp.addProperty("App::PropertyFloatConstraint", "ShaftLength",
320  "Frame", "Frame axis arrow's shaft length.\n"
321  + "Range is < 1.0 | 1e6 >."
322  ).ShaftLength = (20, 1.0, 1e6, 1)
323  else:
324  fp.ShaftLength = (fp.ShaftLength, 1.0, 1e6, 1)
325  if not hasattr(fp, "ShaftWidth"):
326  fp.addProperty("App::PropertyFloatConstraint", "ShaftWidth",
327  "Frame", "Frame axis arrow's shaft width.\n"
328  + "Range is < 1.0 | 64 >."
329  ).ShaftWidth = (4, 1.0, 64, 1)
330  else:
331  fp.ShaftWidth = (fp.ShaftWidth, 1.0, 64, 1)
332  if not hasattr(fp, "ShowFrameLabels"):
333  fp.addProperty("App::PropertyBool", "ShowFrameLabels",
334  "Frame", "Show label for frame axes."
335  ).ShowFrameLabels = True
336 
337  # Label properties
338  if not hasattr(fp, "FontSize"):
339  fp.addProperty("App::PropertyIntegerConstraint", "FontSize",
340  "Labels", "Label font size.\n"
341  + "Range is < 1 | 100 >."
342  ).FontSize = (10, 1, 100, 1)
343  else:
344  fp.FontSize = (fp.FontSize, 1, 100, 1)
345  if not hasattr(fp, "DistanceToAxis"):
346  fp.addProperty("App::PropertyFloatConstraint", "DistanceToAxis",
347  "Labels", "Distance from label to its axis.\n"
348  + "Range is < 0.5 | 1e6 >."
349  ).DistanceToAxis = (5, 0.5, 1e6, 0.5)
350  else:
351  fp.DistanceToAxis = (fp.DistanceToAxis, 0.5, 1e6, 0.5)
352  if not hasattr(fp, "Subscription"):
353  fp.addProperty("App::PropertyString", "Subscription", "Labels",
354  "Subscription added to an axis name."
355  ).Subscription = ""
356  if not hasattr(fp, "Superscription"):
357  fp.addProperty("App::PropertyString", "Superscription", "Labels",
358  "Superscription added to an axis name."
359  ).Superscription = ""
360  if not hasattr(fp, "FontFamily"):
361  fp.addProperty("App::PropertyEnumeration", "FontFamily",
362  "Labels", "Label font family."
363  ).FontFamily = ["SERIF", "SANS", "TYPEWRITER"]
364  if not hasattr(fp, "FontStyle"):
365  fp.addProperty("App::PropertyEnumeration", "FontStyle",
366  "Labels", "Label font style."
367  ).FontStyle = ["NONE", "BOLD", "ITALIC",
368  "BOLD ITALIC"]
369 
370  # Placement properties
371  if not hasattr(fp, "Placement"):
372  fp.addProperty("App::PropertyPlacement", "Placement", "Base",
373  "Current placement for animated objects in "
374  + "world frame.")
375 
376  # Rotation properties
377  if not hasattr(fp, "Timestamps"):
378  fp.addProperty("App::PropertyFloatList", "Timestamps",
379  "Translation", "Timestamps at which we define\n"
380  + "translation.")
381  if not hasattr(fp, "dSequence"):
382  fp.addProperty("App::PropertyFloatList", "dSequence",
383  "Translation", "Displacements along Z axis.")
384 
385  # Add feature python
386  self.fp = fp
387 
388  # Make some properties read-only
389  fp.setEditorMode("ObjectPlacement", 1)
390  fp.setEditorMode("ParentFramePlacement", 1)
391  fp.setEditorMode("d", 1)
392 
393  # Hide some properties
394  fp.setEditorMode("Placement", 2)
395  fp.setEditorMode("ValidTranslation", 2)
396  fp.setEditorMode("RobotPanelActive", 2)
397 
398  import AnimateDocumentObserver
400 
def addObserver()
Adds an AnimateDocumentObserver between FreeCAD's document observers safely.

Member Data Documentation

◆ fp

RobTranslation.RobTranslationProxy.fp

A DocumentObjectGroupPython associated with the proxy.

Definition at line 386 of file RobTranslation.py.

◆ updated

RobTranslation.RobTranslationProxy.updated = False
static

A bool - True if a property was changed by a class and not user.

Definition at line 79 of file RobTranslation.py.


The documentation for this class was generated from the following file: