From 911e1cbf8fdc7f15c6ec8f8360b0f5252c470944 Mon Sep 17 00:00:00 2001 From: Joseph Mirabel <jmirabel@laas.fr> Date: Fri, 30 Mar 2018 11:35:25 +0200 Subject: [PATCH] Add convience python class to draw angular and linear velocities. --- src/CMakeLists.txt | 9 +- src/gepetto/corbaserver/tools.py | 136 +++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 src/gepetto/corbaserver/tools.py diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6a28e26..6759083 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -106,16 +106,9 @@ INSTALL( INSTALL( FILES ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/__init__.py - DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver - ) -INSTALL( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/client.py - DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver - ) -INSTALL( - FILES ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/exporttoblender.py + ${CMAKE_CURRENT_SOURCE_DIR}/gepetto/corbaserver/tools.py DESTINATION ${PYTHON_SITELIB}/gepetto/corbaserver ) INSTALL( diff --git a/src/gepetto/corbaserver/tools.py b/src/gepetto/corbaserver/tools.py new file mode 100644 index 0000000..826110c --- /dev/null +++ b/src/gepetto/corbaserver/tools.py @@ -0,0 +1,136 @@ +from gepetto.color import Color + +import numpy as np +from math import pi, sqrt, cos, sin + +def _pointsTorus(R, r, nR, nr): + pts = [] + twopi = 2 * pi + for j in range(nR): + for i in range(nr + 1): + s = i % nr + phi = s* twopi /nr + for k in (1, 0): + t = (j + k) % nR + + theta = t* twopi /nR + y = (R+r*cos(phi))*cos(theta); + z = -(R+r*cos(phi))*sin(theta); + x = r * sin(phi); + pts.append ((x, y, z)) + return pts + +def _pointsCone(r, L, nr, R): + pts = [] + twopi = 2 * pi + for j in range(nr+1): + t = j % nr + theta = t* twopi /nr + pts.append ((0., R, L)) + pts.append ((r*cos(theta), R + r*sin(theta), 0.)) + return pts + +def _pointsCircularArrow (R, r, nR, nr): + ptsCone = _pointsCone (1.5*r, 3*r, nr, R) + ptsTorus = _pointsTorus (R, r, nR, nr) + return ptsCone + ptsTorus, len(ptsCone) + +# Compute a transformation which rotates (1, 0, 0) to v +# Return (norm_v, T) +# When norm_v == 0, T is None +def _tranformFromXvector (v): + norm_v = np.linalg.norm(v) + if norm_v == 0: + # self.plugin.gui.gui.resizeArrow (n, self.radius, norm_v) + return 0, None + # x = (1, 0, 0) + u = v / norm_v + if u[0] < -1 + 1e-6: # Nearly opposite vectors + m = np.array ( ( (1, 0, 0), u ) ) + U, S, V = np.linalg.svd (m) + c = max (u[0], -1) + w2 = (1 + c) / 2 + s = sqrt(1 - w2) + t = (0,0,0, V[0,2]/s, V[1,2]/s, V[2,2]/s, w2) + else: + s = sqrt(2 * (1 + u[0])) + # axis = (0, -u[2]/s, u[1]/s) # x ^ u + t = (0,0,0, 0, -u[2]/s, u[1]/s, s/2) + return norm_v, t + +class Angular: + ## \param majorRadius, majorN radius and discretisation of the circle that is + ## the center of the torus + ## \param minorRadius, minorN radius and discretisation of the circle that is + ## a section of the torus + def __init__ (self, nodeName, color = Color.red, majorRadius = 0.1, minorRadius = 0.005, majorN = 100, minorN = 20): + self.name = nodeName + self.R = majorRadius + self.r = minorRadius + self.nR = majorN + self.nr = minorN + self.color = color + + def create (self, gui): + pts, self.minC = _pointsCircularArrow (self.R, self.r, self.nR, self.nr) + gui.addCurve (self.name, pts, self.color) + gui.setCurveMode (self.name, "quad_strip") + self.maxC = len(pts) + def remove (self, gui): + gui.deleteNode (self.name, False) + + ## \param factor the norm of the vector is divided by this value + def set(self, gui, v, factor = pi): + norm, pos = _tranformFromXvector (v) + count = min (self.minC + int (norm * (self.maxC-self.minC) / factor), self.maxC) + gui.setCurvePointsSubset (self.name, 0, count) + if pos is not None: gui.applyConfiguration (self.name, pos) + +class Linear: + ## \param majorRadius, majorN radius and discretisation of the circle that is + ## the center of the torus + ## \param minorRadius, minorN radius and discretisation of the circle that is + ## a section of the torus + def __init__ (self, nodeName, color = Color.red, radius = 0.005): + self.name = nodeName + self.R = radius + self.color = color + + def create (self, gui): + gui.addArrow (self.name, self.R, 1, self.color) + def remove (self, gui): + gui.deleteNode (self.name, False) + + ## \param factor the norm of the vector is divided by this value + def set(self, gui, v, factor = 1.): + norm, pos = _tranformFromXvector (v) + gui.resizeArrow (self.name, self.R, norm / factor) + if pos is not None: gui.applyConfiguration (self.name, pos) + + +## Represents a 6D vector using an arrow with the 3 first +## values and a circular arrow with the 3 last values. +## It is useful to plot velocities of a body, forces and torques... +class Vector6: + suffixLin = "linear" + suffixAng = "angular" + + ## \param groupName name of an **existing** group + def __init__ (self, groupName, angFactor = pi, linFactor = 1.): + self.name = groupName + self.linear = Linear (self.name + '/' + VelGetter.suffixLin) + self.angular = Angular (self.name + '/' + VelGetter.suffixAng) + self.angF = angFactor + self.linF = linFactor + + def create (self, gui): + self.linear .create(gui) + self.angular.create(gui) + + def remove (self, gui): + self.linear .remove(gui) + self.angular.remove(gui) + + def set (self, gui, v): + self.linear .set (gui, v[0:3], self.linF) + self.angular.set (gui, v[3:6], self.angF) -- GitLab