11"""Scripts to generate samples using the clearpath_generator_common."""
22import argparse
33import os
4+ import signal
45import shutil
6+ import subprocess
7+ import sys
58
69from ament_index_python .packages import get_package_share_directory
710from clearpath_generator_common .bash .generator import BashGenerator
@@ -25,6 +28,50 @@ def __init__(self, message, errors):
2528 self .errors = errors
2629
2730
31+ def run_ros2_executable (* , path , argv , prefix = None ):
32+ """Execute a ROS2 executable."""
33+ cmd = [path ] + argv
34+
35+ # on Windows Python scripts are invokable through the interpreter
36+ if os .name == 'nt' and path .endswith ('.py' ):
37+ cmd .insert (0 , sys .executable )
38+
39+ if prefix is not None :
40+ cmd = prefix + cmd
41+
42+ process = subprocess .Popen (cmd , stderr = subprocess .PIPE , stdout = subprocess .PIPE )
43+
44+ # add signal handler for the parent process, so that we can finalize the child process
45+ def signal_handler (sig , frame ):
46+ print ('[ros2run]' , 'Received signal: ' , signal .strsignal (sig ))
47+ if process .poll () is None :
48+ # If child process is running, forward the signal to it
49+ process .send_signal (sig )
50+ signal .signal (signal .SIGINT , signal_handler )
51+ signal .signal (signal .SIGTERM , signal_handler )
52+
53+ stdout = ''
54+ stderr = ''
55+
56+ while process .returncode is None :
57+ try :
58+ out , err = process .communicate ()
59+ stdout += out .decode ('utf-8' )
60+ stderr += err .decode ('utf-8' )
61+ except KeyboardInterrupt :
62+ # the subprocess will also receive the signal and should shut down
63+ # therefore we continue here until the process has finished
64+ pass
65+ if process .returncode != 0 :
66+ if - process .returncode in signal .valid_signals () and os .name == 'posix' :
67+ # a negative value -N indicates that the child was terminated by signal N.
68+ print ('[ros2run]' , signal .strsignal (- process .returncode ))
69+ else :
70+ # print general failure message instead.
71+ print ('[ros2run]' , 'Process exited with failure %d' % (process .returncode ))
72+ return (process .returncode , stdout , stderr )
73+
74+
2875def generate_bash (setup_path ) -> None :
2976 """Generate bash environment file."""
3077 bg = BashGenerator (setup_path )
@@ -75,10 +122,16 @@ def generate_semantic_description(setup_path: str) -> bool:
75122 '--min-collision-fraction' , '0.95' ,
76123 '--ros-args' , '--log-level' , 'fatal'
77124 ]
78- run_executable (path = path , argv = argv )
125+ ret , out , err = run_ros2_executable (path = path , argv = argv )
79126 # Delete pseudo package
80127 os .remove (os .path .join (setup_path , 'package.xml' ))
81128
129+ if ret == 0 :
130+ print (f'Generated { os .path .join (setup_path )} /robot.srdf' )
131+ else :
132+ print (f'Failed to generate { os .path .join (setup_path )} /robot.srdf' )
133+ raise Exception (f'Failed semantic generation with \n \t stdout:{ out } \n \t stderr: { err } ' )
134+
82135
83136def error_log (name : str , sample : str , error : Exception ) -> str :
84137 """Return error entry."""
@@ -95,7 +148,7 @@ def generate_test_samples(root_dir: str):
95148 # Filter for Test Samples
96149 if 'test' not in sample :
97150 continue
98- print (sample )
151+ print (f'Generating { sample } ' . center ( 100 , '-' ) )
99152 # Create Clearpath Directory
100153 src = os .path .join (sample_dir , sample )
101154 dst = os .path .join (
@@ -138,8 +191,10 @@ def generate_test_samples(root_dir: str):
138191 except Exception as e :
139192 errors .append (error_log ('SemanticDescriptionGenerator' , sample , e ))
140193 if len (errors ) > 0 :
141- sample_errors .append (f'Sample "{ sample } " failed to generate:\n ' '\n ' .join (errors ))
194+ sample_errors .append (f'Sample "{ sample } " failed to generate:\n { '\n ' .join (errors )} ' )
195+ print ()
142196 if len (sample_errors ) > 0 :
197+ print (f'Generators reported { len (sample_errors )} errors' .center (100 , '*' ))
143198 raise GenerationFailureException (
144199 message = f'Generation failed for { len (sample_errors )} samples:\n '
145200 f'{ "\n " .join (sample_errors )} ' ,
0 commit comments