6
6
7
7
import numpy as np
8
8
9
+ # export PYTHONPATH=~/src/ft_300s_driver/bazel-bin/lcmtypes/ft_300s/:${PYTHONPATH}
10
+ try :
11
+ from ft_reading_t import ft_reading_t
12
+ except ImportError :
13
+ logging .warning ("Failed to import `ft_reading_t`. Won't be able to log FT data." )
14
+
9
15
from iiwa_setup .controllers import (
10
16
InverseDynamicsControllerWithGravityCompensationCancellation ,
11
17
)
12
18
from iiwa_setup .iiwa import IiwaHardwareStationDiagram
19
+ from iiwa_setup .sensors import FTSensorDataReceiver
13
20
from manipulation .station import LoadScenario
14
21
from pydrake .all import (
15
22
ApplySimulatorConfig ,
18
25
ConstantVectorSource ,
19
26
Demultiplexer ,
20
27
DiagramBuilder ,
28
+ DrakeLcm ,
29
+ LcmInterfaceSystem ,
30
+ LcmSubscriberSystem ,
21
31
MeshcatVisualizer ,
22
32
PiecewisePolynomial ,
23
33
Simulator ,
@@ -107,6 +117,11 @@ def main():
107
117
default = 1e-3 ,
108
118
help = "The period at which to log data." ,
109
119
)
120
+ parser .add_argument (
121
+ "--log_ft_data" ,
122
+ action = "store_true" ,
123
+ help = "Whether to log the FT sensor data." ,
124
+ )
110
125
parser .add_argument (
111
126
"--html_path" ,
112
127
type = Path ,
@@ -132,6 +147,7 @@ def main():
132
147
duration_to_remove_at_start = args .duration_to_remove_at_start
133
148
noise_scale = args .noise_scale
134
149
logging_period = args .logging_period
150
+ log_ft_data = args .log_ft_data
135
151
html_path = args .html_path
136
152
137
153
assert not (use_hardware and noise_scale > 0.0 )
@@ -251,6 +267,29 @@ def main():
251
267
wsg_const_pos_source .get_output_port (), station .GetInputPort ("wsg.position" )
252
268
)
253
269
270
+ if log_ft_data :
271
+ lcm = DrakeLcm ()
272
+ lcm_system = builder .AddNamedSystem (
273
+ "lcm_interface_system" , LcmInterfaceSystem (lcm )
274
+ )
275
+ ft_sensor_subscriber : LcmSubscriberSystem = builder .AddNamedSystem (
276
+ "ft_sensor_subscriber" ,
277
+ LcmSubscriberSystem .Make (
278
+ channel = "FT300S_SENSOR_DATA" ,
279
+ lcm_type = ft_reading_t ,
280
+ lcm = lcm_system ,
281
+ use_cpp_serializer = False ,
282
+ wait_for_message_on_initialization_timeout = 10 ,
283
+ ),
284
+ )
285
+ ft_sensor_data_receiver : FTSensorDataReceiver = builder .AddNamedSystem (
286
+ "ft_sensor_data_receiver" , FTSensorDataReceiver ()
287
+ )
288
+ builder .Connect (
289
+ ft_sensor_subscriber .get_output_port (),
290
+ ft_sensor_data_receiver .get_input_port (),
291
+ )
292
+
254
293
# Add data loggers
255
294
desired_state_demux = builder .AddNamedSystem (
256
295
"desired_state_demux" , Demultiplexer (output_ports_sizes = [7 , 7 ])
@@ -287,6 +326,12 @@ def main():
287
326
"measured_torque_logger" ,
288
327
VectorLogSink (num_positions , publish_period = logging_period ),
289
328
)
329
+ if log_ft_data :
330
+ # The FT 300-S sensor publishes at 100Hz.
331
+ ft_logger : VectorLogSink = builder .AddNamedSystem (
332
+ "ft_logger" ,
333
+ VectorLogSink (input_size = 6 , publish_period = np .min ([1e-2 , logging_period ])),
334
+ )
290
335
builder .Connect (
291
336
desired_state_demux .get_output_port (0 ),
292
337
commanded_position_logger .get_input_port (),
@@ -315,6 +360,11 @@ def main():
315
360
station .GetOutputPort ("iiwa.torque_measured" ),
316
361
measured_torque_logger .get_input_port (),
317
362
)
363
+ if log_ft_data :
364
+ builder .Connect (
365
+ ft_sensor_data_receiver .GetOutputPort ("ft_measured" ),
366
+ ft_logger .get_input_port (),
367
+ )
318
368
319
369
visualizer = MeshcatVisualizer .AddToBuilder (
320
370
builder , station .GetOutputPort ("query_object" ), station .internal_meshcat
@@ -377,6 +427,10 @@ def main():
377
427
simulator .get_context ()
378
428
).sample_times ()
379
429
430
+ if log_ft_data :
431
+ ft_data = ft_logger .FindLog (simulator .get_context ()).data ().T
432
+ ft_sample_times_s = ft_logger .FindLog (simulator .get_context ()).sample_times ()
433
+
380
434
if only_log_excitation_traj_data :
381
435
# Only keep data during excitation trajectory execution
382
436
data_start_time = (
@@ -412,6 +466,14 @@ def main():
412
466
# Shift sample times to start at 0
413
467
sample_times_s -= sample_times_s [0 ]
414
468
469
+ if log_ft_data :
470
+ ft_start_idx = np .argmax (ft_sample_times_s >= data_start_time )
471
+ ft_end_idx = np .argmax (ft_sample_times_s >= excitation_traj_end_time )
472
+ ft_data = ft_data [ft_start_idx :ft_end_idx ]
473
+ ft_sample_times_s = ft_sample_times_s [ft_start_idx :ft_end_idx ]
474
+ # Shift sample times to start at 0
475
+ ft_sample_times_s -= ft_sample_times_s [0 ]
476
+
415
477
# Remove duplicated samples
416
478
_ , unique_indices = np .unique (sample_times_s , return_index = True )
417
479
commanded_position_data = commanded_position_data [unique_indices ]
@@ -422,6 +484,10 @@ def main():
422
484
commanded_torque_data = commanded_torque_data [unique_indices ]
423
485
measured_torque_data = measured_torque_data [unique_indices ]
424
486
sample_times_s = sample_times_s [unique_indices ]
487
+ if log_ft_data :
488
+ _ , ft_unique_indices = np .unique (ft_sample_times_s , return_index = True )
489
+ ft_data = ft_data [ft_unique_indices ]
490
+ ft_sample_times_s = ft_sample_times_s [ft_unique_indices ]
425
491
426
492
# Add noise
427
493
if noise_scale > 0.0 :
@@ -446,6 +512,8 @@ def main():
446
512
joint_accelerations = np .zeros_like (measured_position_data ) * np .nan ,
447
513
joint_torques = measured_torque_data ,
448
514
sample_times_s = sample_times_s ,
515
+ ft_sensor_measurements = ft_data if log_ft_data else None ,
516
+ ft_sensor_sample_times_s = ft_sample_times_s if log_ft_data else None ,
449
517
)
450
518
joint_data .save_to_disk (save_data_path )
451
519
0 commit comments