11from __future__ import absolute_import
22
3- from .std_msgs import ROSmsg
4- from .std_msgs import Header
5- from .std_msgs import Time
6-
73from compas .geometry import Frame
84
5+ import compas_fab .robots
6+
7+ from .std_msgs import Header
8+ from .std_msgs import ROSmsg
9+
910
1011class Point (ROSmsg ):
11- """http://docs.ros.org/kinetic/ api/geometry_msgs/html/msg/Point.html
12+ """http://docs.ros.org/api/geometry_msgs/html/msg/Point.html
1213 """
14+
1315 def __init__ (self , x , y , z ):
1416 self .x = x
1517 self .y = y
@@ -20,10 +22,12 @@ def from_msg(cls, msg):
2022 x , y , z = msg ['x' ], msg ['y' ], msg ['z' ]
2123 return cls (x , y , z )
2224
25+
2326class Quaternion (ROSmsg ):
24- """http://docs.ros.org/kinetic/ api/geometry_msgs/html/msg/Quaternion.html
27+ """http://docs.ros.org/api/geometry_msgs/html/msg/Quaternion.html
2528 """
26- def __init__ (self , x = 0. ,y = 0. , z = 0. , w = 1. ):
29+
30+ def __init__ (self , x = 0. , y = 0. , z = 0. , w = 1. ):
2731 self .x = x
2832 self .y = y
2933 self .z = z
@@ -34,12 +38,14 @@ def from_frame(cls, frame):
3438 qw , qx , qy , qz = frame .quaternion
3539 return cls (qx , qy , qz , qw )
3640
41+
3742class Pose (ROSmsg ):
38- """http://docs.ros.org/kinetic/ api/geometry_msgs/html/msg/Pose.html
43+ """http://docs.ros.org/api/geometry_msgs/html/msg/Pose.html
3944 """
45+
4046 def __init__ (self , position = None , orientation = None ):
41- self .position = position if position else Point (0 ,0 , 0 )
42- self .orientation = orientation if orientation else Quaternion (0 ,0 , 0 , 1 )
47+ self .position = position if position else Point (0 , 0 , 0 )
48+ self .orientation = orientation if orientation else Quaternion (0 , 0 , 0 , 1 )
4349
4450 @classmethod
4551 def from_frame (cls , frame ):
@@ -59,37 +65,155 @@ def from_msg(cls, msg):
5965 orientation = Quaternion .from_msg (msg ['orientation' ])
6066 return cls (position , orientation )
6167
68+
6269class PoseStamped (ROSmsg ):
63- """http://docs.ros.org/melodic/ api/geometry_msgs/html/msg/PoseStamped.html
70+ """http://docs.ros.org/api/geometry_msgs/html/msg/PoseStamped.html
6471 """
65- def __init__ (self , header = Header (), pose = Pose ()):
66- self .header = header
67- self .pose = pose
72+
73+ def __init__ (self , header = None , pose = None ):
74+ self .header = header or Header ()
75+ self .pose = pose or Pose ()
6876
6977 @classmethod
7078 def from_msg (cls , msg ):
7179 header = Header .from_msg (msg ['header' ])
7280 pose = Pose .from_msg (msg ['pose' ])
7381 return cls (header , pose )
7482
83+
7584class Vector3 (ROSmsg ):
7685 """http://docs.ros.org/api/geometry_msgs/html/msg/Vector3.html
7786 """
87+
7888 def __init__ (self , x = 0. , y = 0. , z = 0. ):
7989 self .x = x
8090 self .y = y
8191 self .z = z
8292
93+ @classmethod
94+ def from_msg (cls , msg ):
95+ x , y , z = msg ['x' ], msg ['y' ], msg ['z' ]
96+ return cls (x , y , z )
97+
98+
8399class Transform (ROSmsg ):
84100 """http://docs.ros.org/api/geometry_msgs/html/msg/Transform.html
85101 """
86- def __init__ (self , translation = Vector3 (), rotation = Quaternion ()):
87- self .translation = translation
88- self .rotation = rotation
102+
103+ def __init__ (self , translation = None , rotation = None ):
104+ self .translation = translation or Vector3 ()
105+ self .rotation = rotation or Quaternion ()
106+
89107
90108class Twist (ROSmsg ):
91109 """http://docs.ros.org/api/geometry_msgs/html/msg/Twist.html
92110 """
93- def __init__ (self , linear = Vector3 (), angular = Vector3 ()):
94- self .linear = linear
95- self .angular = angular
111+
112+ def __init__ (self , linear = None , angular = None ):
113+ self .linear = linear or Vector3 ()
114+ self .angular = angular or Vector3 ()
115+
116+
117+ class Wrench (ROSmsg ):
118+ """http://docs.ros.org/api/geometry_msgs/html/msg/Wrench.html
119+
120+ This represents force in free space, separated into its linear and angular parts.
121+
122+ Examples
123+ --------
124+ >>> wrench = compas_fab.robots.Wrench([0, 0, -98], [0, 0, 0])
125+ >>> ros_wrench = Wrench.from_wrench(wrench)
126+ >>> ros_wrench.msg
127+ {'force': {'x': 0.0, 'y': 0.0, 'z': -98.0}, 'torque': {'x': 0.0, 'y': 0.0, 'z': 0.0}}
128+ >>> ros_wrench.wrench
129+ Wrench(Vector(0.000, 0.000, -98.000), Vector(0.000, 0.000, 0.000))
130+ """
131+
132+ def __init__ (self , force = None , torque = None ):
133+ self .force = force or Vector3 ()
134+ self .torque = torque or Vector3 ()
135+
136+ @classmethod
137+ def from_msg (cls , msg ):
138+ force = Vector3 .from_msg (msg ['force' ])
139+ torque = Vector3 .from_msg (msg ['torque' ])
140+ return cls (force , torque )
141+
142+ @classmethod
143+ def from_wrench (cls , wrench ):
144+ force = wrench .force
145+ torque = wrench .torque
146+ return cls (Vector3 (* list (force )), Vector3 (* list (torque )))
147+
148+ @property
149+ def wrench (self ):
150+ force = [self .force .x , self .force .y , self .force .z ]
151+ torque = [self .torque .x , self .torque .y , self .torque .z ]
152+ return compas_fab .robots .Wrench (force , torque )
153+
154+
155+ class WrenchStamped (ROSmsg ):
156+ """http://docs.ros.org/api/geometry_msgs/html/msg/WrenchStamped.html
157+
158+ A wrench with reference coordinate frame and timestamp.
159+ """
160+
161+ def __init__ (self , header = None , wrench = None ):
162+ self .header = header or Header ()
163+ self .wrench = wrench or Wrench ()
164+
165+ @classmethod
166+ def from_msg (cls , msg ):
167+ header = Header .from_msg (msg ['header' ])
168+ wrench = Wrench .from_msg (msg ['wrench' ])
169+ return cls (header , wrench )
170+
171+
172+ class Inertia (ROSmsg ):
173+ """http://docs.ros.org/api/geometry_msgs/html/msg/Inertia.html
174+
175+ Examples
176+ --------
177+ >>> inertia = compas_fab.robots.Inertia([[0] * 3] * 3, 1., [0.1, 3.1, 4.4])
178+ >>> ros_inertia = Inertia.from_inertia(inertia)
179+ >>> ros_inertia.msg
180+ {'m': 1.0, 'com': {'x': 0.1, 'y': 3.1, 'z': 4.4}, 'ixx': 0.0, 'ixy': 0.0, 'ixz': 0.0, 'iyy': 0.0, 'iyz': 0.0, 'izz': 0.0}
181+ >>> ros_inertia.inertia
182+ Inertia([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], 1.0, Point(0.100, 3.100, 4.400))
183+ """
184+
185+ def __init__ (self , m = 0.0 , com = None , ixx = 0. , ixy = 0. , ixz = 0. , iyy = 0. , iyz = 0. , izz = 0. ):
186+ self .m = float (m ) # Mass [kg]
187+ self .com = com or Vector3 () # Center of mass [m]
188+ self .ixx = float (ixx )
189+ self .ixy = float (ixy )
190+ self .ixz = float (ixz )
191+ self .iyy = float (iyy )
192+ self .iyz = float (iyz )
193+ self .izz = float (izz )
194+
195+ @classmethod
196+ def from_msg (cls , msg ):
197+ com = Vector3 .from_msg (msg ['com' ])
198+ return cls (msg ['m' ], com , msg ['ixx' ], msg ['ixy' ], msg ['ixz' ], msg ['iyy' ], msg ['iyz' ], msg ['izz' ])
199+
200+ @classmethod
201+ def from_inertia (cls , inertia ):
202+ m = inertia .mass
203+ com = Vector3 (* list (inertia .center_of_mass ))
204+ ixx , ixy , ixz = inertia .inertia_tensor [0 ]
205+ ixy , iyy , iyz = inertia .inertia_tensor [1 ]
206+ izz = inertia .inertia_tensor [2 ][2 ]
207+ return cls (m , com , ixx , ixy , ixz , iyy , iyz , izz )
208+
209+ @property
210+ def inertia (self ):
211+ inertia_tensor = [[self .ixx , self .ixy , self .ixz ],
212+ [self .ixy , self .iyy , self .iyz ],
213+ [self .ixz , self .iyz , self .izz ]]
214+ return compas_fab .robots .Inertia (inertia_tensor , self .m , [self .com .x , self .com .y , self .com .z ])
215+
216+
217+ if __name__ == "__main__" :
218+ import doctest
219+ doctest .testmod ()
0 commit comments