Skip to content

Commit fb72298

Browse files
committed
Merge remote-tracking branch 'origin/master' into devel
2 parents 5d70f30 + d8430b3 commit fb72298

File tree

3 files changed

+71
-63
lines changed

3 files changed

+71
-63
lines changed

Diff for: launch/lss_demo.launch

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
linear_vels: [1.]
6060
angular_vels: [0.]
6161
total_sim_time: 5.
62+
max_stale_msg_delay: 0.5
6263
</rosparam>
6364
</node>
6465

Diff for: nodes/diff_physics

+68-62
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/bin/env python
22

3+
import os
34
import torch
45
import numpy as np
56
import rospy
@@ -21,11 +22,13 @@ class DiffPhysics:
2122
hm_topic='/height_map',
2223
hm_frame='base_link',
2324
linear_vels=[1.],
24-
angular_vels=[0.]):
25+
angular_vels=[0.],
26+
max_stale_msg_delay=0.5):
2527
self.cfg = cfg
2628
self.hm_frame = hm_frame
2729
self.linear_vels = linear_vels
2830
self.angular_vels = angular_vels
31+
self.max_stale_msg_delay = max_stale_msg_delay
2932

3033
# paths publisher
3134
self.paths_pub = rospy.Publisher('/sampled_paths', MarkerArray, queue_size=1)
@@ -39,12 +42,12 @@ class DiffPhysics:
3942
assert isinstance(msg, PointCloud2)
4043
# if message is stale do not process it
4144
dt = rospy.Time.now() - msg.header.stamp
42-
if dt > rospy.Duration(2.):
43-
rospy.logdebug(f'Stale height map message received ({dt.to_sec():.1f} [sec]), skipping')
45+
if dt.to_sec() > self.max_stale_msg_delay:
46+
rospy.logwarn(f'Stale height map message received ({dt.to_sec():.1f} > {self.max_stale_msg_delay} [sec]), skipping')
4447
return
4548

4649
height = numpify(msg)['z']
47-
h = w = int(self.cfg.d_max / self.cfg.grid_res)
50+
h = w = int(2 * self.cfg.d_max / self.cfg.grid_res)
4851
height = height.reshape((h, w))
4952
height = np.asarray(height, dtype=np.float64)
5053
height = height.T
@@ -62,13 +65,11 @@ class DiffPhysics:
6265
assert 'linear_v' in controls.keys()
6366
assert 'angular_w' in controls.keys()
6467

65-
h, w = np.asarray(height.shape) * self.cfg.grid_res
6668
state = State(xyz=torch.tensor([0, 0., 0.], device=self.cfg.device).view(3, 1),
67-
rot=torch.eye(3, device=self.cfg.device),
68-
vel=torch.tensor([0., 0., 0.], device=self.cfg.device).view(3, 1),
69-
omega=torch.tensor([0., 0., 0.], device=self.cfg.device).view(3, 1),
70-
device=self.cfg.device)
71-
state[0][0] = -h / 2. # move robot to the edge of the height map
69+
rot=torch.eye(3, device=self.cfg.device),
70+
vel=torch.tensor([0., 0., 0.], device=self.cfg.device).view(3, 1),
71+
omega=torch.tensor([0., 0., 0.], device=self.cfg.device).view(3, 1),
72+
device=self.cfg.device)
7273

7374
""" Create robot-terrain interaction models """
7475
system = RigidBodySoftTerrain(height=height,
@@ -104,8 +105,7 @@ class DiffPhysics:
104105
angular_w.append(state[3])
105106
forces.append(state[4])
106107

107-
# height map origin is at the edge of the map
108-
xyz = torch.stack(xyz) + torch.tensor([h / 2., 0., 0.], device=self.cfg.device).view(3, 1)
108+
xyz = torch.stack(xyz)
109109
Rs = torch.stack(Rs)
110110
linear_v = torch.stack(linear_v)
111111
angular_w = torch.stack(angular_w)
@@ -133,6 +133,10 @@ class DiffPhysics:
133133
if linear_vels is None:
134134
linear_vels = [1.]
135135
assert isinstance(height, np.ndarray)
136+
assert height.shape[0] == height.shape[1]
137+
assert isinstance(linear_vels, list)
138+
assert isinstance(angular_vels, list)
139+
assert len(linear_vels) == len(angular_vels)
136140

137141
tt = torch.linspace(0., self.cfg.total_sim_time, self.cfg.n_samples)
138142
# paths marker array
@@ -141,51 +145,50 @@ class DiffPhysics:
141145
lower_cost_poses = None
142146
max_path_cost = torch.tensor(-np.inf, device=self.cfg.device)
143147
min_path_cost = torch.tensor(np.inf, device=self.cfg.device)
144-
for v in linear_vels:
145-
for w in angular_vels:
146-
# controls
147-
controls = {
148-
'stamps': tt,
149-
'linear_v': v * torch.ones(self.cfg.n_samples),
150-
'angular_w': w * torch.ones(self.cfg.n_samples)
151-
}
152-
153-
# predict states
154-
t0 = time()
155-
states = self.sim(height, controls)
156-
t1 = time()
157-
rospy.logdebug('Path of %d samples simulation took %.3f' % (self.cfg.n_samples, t1 - t0))
158-
159-
# create path message (Marker)
160-
xyz = states[0].cpu().numpy()[::100]
161-
Rs = states[1].cpu().numpy()[::100]
162-
Ts = np.zeros((len(xyz), 4, 4))
163-
Ts[:, :3, :3] = Rs
164-
Ts[:, :3, 3:4] = xyz
165-
Ts[:, 3, 3] = 1.
166-
167-
# compute path cost
168-
path_cost = self.path_cost(states)
169-
# rospy.logdebug('Path cost: %.3f' % path_cost.item())
170-
if path_cost > max_path_cost:
171-
max_path_cost = path_cost.clone()
172-
if path_cost < min_path_cost:
173-
min_path_cost = path_cost.clone()
174-
lower_cost_poses = Ts
175-
# normalize path cost
176-
path_cost = (path_cost - min_path_cost) / (max_path_cost - min_path_cost) if max_path_cost > min_path_cost else path_cost
177-
# rospy.logdebug('Path cost normalized: %.3f' % path_cost.item())
178-
179-
# map path cost to color (lower cost -> greener, higher cost -> redder)
180-
color = np.array([0., 1., 0.]) + (np.array([1., 0., 0.]) - np.array([0., 1., 0.])) * path_cost.item()
181-
marker_msg = to_marker(Ts, color=color)
182-
marker_msg.header.stamp = rospy.Time.now()
183-
marker_msg.header.frame_id = self.hm_frame
184-
marker_msg.ns = 'paths'
185-
marker_msg.id = path_id
186-
path_id += 1
187-
marker_array.markers.append(marker_msg)
188-
rospy.logdebug('Path to marker array conversion took %.3f' % (time() - t1))
148+
for v, w in zip(linear_vels, angular_vels):
149+
# controls
150+
controls = {
151+
'stamps': tt,
152+
'linear_v': v * torch.ones(self.cfg.n_samples),
153+
'angular_w': w * torch.ones(self.cfg.n_samples)
154+
}
155+
156+
# predict states
157+
t0 = time()
158+
states = self.sim(height, controls)
159+
t1 = time()
160+
rospy.logdebug('Path of %d samples simulation took %.3f' % (self.cfg.n_samples, t1 - t0))
161+
162+
# create path message (Marker)
163+
xyz = states[0].cpu().numpy()[::50]
164+
Rs = states[1].cpu().numpy()[::50]
165+
Ts = np.zeros((len(xyz), 4, 4))
166+
Ts[:, :3, :3] = Rs
167+
Ts[:, :3, 3:4] = xyz
168+
Ts[:, 3, 3] = 1.
169+
170+
# compute path cost
171+
path_cost = self.path_cost(states)
172+
# rospy.logdebug('Path cost: %.3f' % path_cost.item())
173+
if path_cost > max_path_cost:
174+
max_path_cost = path_cost.clone()
175+
if path_cost < min_path_cost:
176+
min_path_cost = path_cost.clone()
177+
lower_cost_poses = Ts
178+
# normalize path cost
179+
path_cost = (path_cost - min_path_cost) / (max_path_cost - min_path_cost) if max_path_cost > min_path_cost else path_cost
180+
# rospy.logdebug('Path cost normalized: %.3f' % path_cost.item())
181+
182+
# map path cost to color (lower cost -> greener, higher cost -> redder)
183+
color = np.array([0., 1., 0.]) + (np.array([1., 0., 0.]) - np.array([0., 1., 0.])) * path_cost.item()
184+
marker_msg = to_marker(Ts, color=color)
185+
marker_msg.header.stamp = rospy.Time.now()
186+
marker_msg.header.frame_id = self.hm_frame
187+
marker_msg.ns = 'paths'
188+
marker_msg.id = path_id
189+
path_id += 1
190+
marker_array.markers.append(marker_msg)
191+
rospy.logdebug('Path to marker array conversion took %.3f' % (time() - t1))
189192

190193
# publish all sampled paths
191194
self.paths_pub.publish(marker_array)
@@ -199,12 +202,12 @@ class DiffPhysics:
199202

200203
def main():
201204
rospy.init_node('diff_physics', anonymous=True, log_level=rospy.DEBUG)
205+
pkg_path = rospkg.RosPack().get_path('monoforce')
202206

203207
cfg = Config()
204-
cfg.grid_res = 0.1
205-
cfg.device = 'cuda'
206-
cfg.d_max = 12.8
207-
cfg.d_min = 1.
208+
config_path = rospy.get_param('~config_path', os.path.join(pkg_path, 'config/cfg.yaml'))
209+
assert os.path.isfile(config_path), 'Config file %s does not exist' % config_path
210+
cfg.from_yaml(config_path)
208211
cfg.total_sim_time = rospy.get_param('~total_sim_time', 5.)
209212
cfg.n_samples = 100 * int(cfg.total_sim_time)
210213

@@ -213,9 +216,12 @@ def main():
213216
# control parameters
214217
linear_vels = rospy.get_param('~linear_vels', [1.])
215218
angular_vels = rospy.get_param('~angular_vels', [0.])
219+
# max time to wait for a message before it is considered stale
220+
max_stale_msg_delay = rospy.get_param('~max_stale_msg_delay', 0.5)
216221
try:
217222
node = DiffPhysics(cfg=cfg, hm_topic=hm_topic, hm_frame=hm_frame,
218-
linear_vels=linear_vels, angular_vels=angular_vels)
223+
linear_vels=linear_vels, angular_vels=angular_vels,
224+
max_stale_msg_delay=max_stale_msg_delay)
219225
rospy.spin()
220226
except rospy.ROSInterruptException:
221227
pass

Diff for: scripts/robot_control

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ torch.set_default_dtype(torch.float64)
1818
cfg = Config()
1919
cfg.grid_res = 0.1
2020
cfg.device = 'cpu'
21-
cfg.d_max = 12.8
21+
cfg.d_max = 6.4
2222
cfg.d_min = 1.
2323
cfg.max_vel = np.inf
2424
cfg.max_omega = np.inf
@@ -222,6 +222,7 @@ def p_control_diffdrive():
222222

223223
# states_true, tt_true, height = get_test_data()
224224
states_true, tt_true, height = get_data()
225+
height = np.asarray(height, dtype=np.float64)
225226
xyz_true, rot_true, vel_true, omega_true, forces_true = states_true
226227
n_true_states = len(xyz_true)
227228
# height = np.zeros_like(height) + xyz_true[:, 2].numpy().min()

0 commit comments

Comments
 (0)