@@ -72,12 +72,27 @@ def __init__(self):
7272 self .steering_corrections = [] # Store steering corrections during calibration
7373 self .recording_corrections = False
7474
75+ # Load max_steering_angle from config for joystick corrections
76+ try :
77+ import re
78+ config_path = "/home/orin/roboracer_ws/src/ut_automata/config/car.lua"
79+ with open (config_path , 'r' ) as f :
80+ content = f .read ()
81+ match = re .search (r'max_steering_angle\s*=\s*([-0-9.]+)' , content )
82+ if match :
83+ self .max_steering_angle = float (match .group (1 ))
84+ else :
85+ self .max_steering_angle = 0.286 # default
86+ except :
87+ self .max_steering_angle = 0.286 # default
88+
7589 # Calibration results
7690 self .results = {
7791 'steering_offset' : None ,
7892 'steering_gain' : None ,
7993 'speed_offset' : None ,
80- 'speed_gain' : None
94+ 'speed_gain' : None ,
95+ 'max_steering_angle' : None
8196 }
8297
8398 self .get_logger ().info ('VESC Calibrator initialized' )
@@ -96,8 +111,9 @@ def joy_callback(self, msg):
96111 # Use left stick horizontal (axes[0]) for steering, same as vesc_driver
97112 # Negative because that's how vesc_driver does it
98113 steer_input = - msg .axes [0 ] if len (msg .axes ) > 0 else 0.0
99- # Scale by max turn rate (0.25 rad from vesc_driver.cpp)
100- steering_correction = steer_input * 0.25
114+ # Scale by max steering angle from config (default 0.286 rad)
115+ max_steering_angle = getattr (self , 'max_steering_angle' , 0.286 )
116+ steering_correction = steer_input * max_steering_angle
101117 self .steering_corrections .append (steering_correction )
102118
103119 def send_drive_command (self , velocity , curvature ):
@@ -322,6 +338,38 @@ def write_speed_gain(self, gain, config_path="/home/orin/roboracer_ws/src/ut_aut
322338 except Exception as e :
323339 self .get_logger ().error (f"Error writing config file: { e } " )
324340 return False
341+
342+ def write_max_steering_angle (self , angle , config_path = "/home/orin/roboracer_ws/src/ut_automata/config/car.lua" ):
343+ """Write max_steering_angle to car.lua config file"""
344+ import re
345+
346+ try :
347+ # Read existing content or create new file
348+ try :
349+ with open (config_path , 'r' ) as f :
350+ content = f .read ()
351+ except FileNotFoundError :
352+ # Create new file with car_name if it doesn't exist
353+ content = 'car_name = "orin12";\n \n '
354+
355+ # Check if max_steering_angle already exists in the file
356+ pattern = r'(max_steering_angle\s*=\s*)([-0-9.]+)([;]?[^\n]*)'
357+ if re .search (pattern , content ):
358+ # Replace existing value (preserve semicolon and comments)
359+ replacement = f'\\ g<1>{ angle :.4f} \\ g<3>'
360+ new_content = re .sub (pattern , replacement , content )
361+ else :
362+ # Append to file if it doesn't exist
363+ new_content = content .rstrip () + f'\n max_steering_angle = { angle :.4f} ; -- radians, calibrated from turn radius\n '
364+
365+ with open (config_path , 'w' ) as f :
366+ f .write (new_content )
367+
368+ self .get_logger ().info (f"Updated max_steering_angle to { angle :.4f} rad ({ math .degrees (angle ):.2f} deg) in { config_path } " )
369+ return True
370+ except Exception as e :
371+ self .get_logger ().error (f"Error writing config file: { e } " )
372+ return False
325373
326374 def calibrate_steering_offset (self ):
327375 """
@@ -376,8 +424,8 @@ def calibrate_steering_offset(self):
376424 if self .current_joy is not None and len (self .current_joy .axes ) > 0 :
377425 # Use left stick horizontal (axes[0]) for steering
378426 steer_input = - self .current_joy .axes [0 ]
379- # Scale by max turn rate (0.25 rad)
380- steering_correction = steer_input * 0.25
427+ # Scale by max steering angle from config
428+ steering_correction = steer_input * self . max_steering_angle
381429
382430 # Command forward with user's steering correction
383431 # curvature = 1/turn_radius, for small angles: curvature ≈ steering_angle / wheelbase
@@ -503,7 +551,22 @@ def calibrate_steering_gain(self):
503551 return
504552
505553 wheelbase = 0.324 # meters (from vesc.lua)
506- max_steering_angle = 0.25 # radians (from vesc_driver.cpp)
554+
555+ # Read current max_steering_angle from config (or use default)
556+ try :
557+ import re
558+ config_path = "/home/orin/roboracer_ws/src/ut_automata/config/car.lua"
559+ with open (config_path , 'r' ) as f :
560+ content = f .read ()
561+ match = re .search (r'max_steering_angle\s*=\s*([-0-9.]+)' , content )
562+ if match :
563+ max_steering_angle = float (match .group (1 ))
564+ print (f"Current max_steering_angle from config: { max_steering_angle :.4f} rad ({ math .degrees (max_steering_angle ):.2f} °)" )
565+ else :
566+ max_steering_angle = 0.286 # default for ~1.1m turn radius
567+ print (f"No max_steering_angle in config, using default: { max_steering_angle :.4f} rad" )
568+ except :
569+ max_steering_angle = 0.286 # default
507570
508571 # Calculate maximum curvature from max steering angle
509572 # From vesc_driver: steering_angle = atan(wheelbase / turn_radius)
@@ -565,12 +628,19 @@ def calibrate_steering_gain(self):
565628
566629 # Calculate average turn radius
567630 avg_radius = np .mean (turn_radii )
568- print (f"\n Average turn radius: { avg_radius :.3f} m" )
631+ print (f"\n 📊 Turn Radius Measurements:" )
632+ print (f" Average turn radius: { avg_radius :.3f} m" )
633+ if len (turn_radii ) > 1 :
634+ print (f" Individual radii: { ', ' .join ([f'{ r :.3f} m' for r in turn_radii ])} " )
635+ print (f" Variation: ±{ np .std (turn_radii ):.3f} m" )
569636
570637 # Calculate actual steering angle from measured radius
571638 # steering_angle = atan(wheelbase / turn_radius)
572639 actual_steering_angle = math .atan (wheelbase / avg_radius )
573640
641+ # This is the max_steering_angle the vehicle can physically achieve
642+ measured_max_steering_angle = actual_steering_angle
643+
574644 # Calculate gain: commanded_angle / actual_angle gives us the gain
575645 # But we command curvature, so we need to work backwards
576646 # curvature = 1/turn_radius, steering_angle = atan(wheelbase * curvature)
@@ -606,6 +676,7 @@ def calibrate_steering_gain(self):
606676 new_gain = current_gain * correction_factor
607677
608678 self .results ['steering_gain' ] = new_gain
679+ self .results ['max_steering_angle' ] = measured_max_steering_angle
609680
610681 # Write the gain to car.lua config file
611682 if self .write_steering_gain (new_gain ):
@@ -614,8 +685,18 @@ def calibrate_steering_gain(self):
614685 print (f"\n ⚠️ Failed to update car.lua. Please update it manually." )
615686 print (f" Set steering_angle_to_servo_gain = { new_gain :.4f} ;" )
616687
688+ # Write max_steering_angle to car.lua config file
689+ if self .write_max_steering_angle (measured_max_steering_angle ):
690+ print (f"✅ Updated car.lua with max_steering_angle: { measured_max_steering_angle :.4f} rad ({ math .degrees (measured_max_steering_angle ):.2f} °)" )
691+ print (f" This corresponds to minimum turning radius: { avg_radius :.3f} m" )
692+ else :
693+ print (f"\n ⚠️ Failed to update car.lua. Please update it manually." )
694+ print (f" Set max_steering_angle = { measured_max_steering_angle :.4f} ;" )
695+
617696 print (f"\n ✓ Steering gain calibrated: { new_gain :.4f} " )
618697 print (f" (Correction factor: { correction_factor :.3f} )" )
698+ print (f"✓ Max steering angle calibrated: { measured_max_steering_angle :.4f} rad ({ math .degrees (measured_max_steering_angle ):.2f} °)" )
699+ print (f" Minimum turning radius: { avg_radius :.3f} m" )
619700 print ("⚠️ Remember to restart the VESC driver node for the change to take effect!" )
620701
621702 def calibrate_speed_offset (self ):
@@ -870,6 +951,11 @@ def print_results(self):
870951 if self .results ['speed_gain' ] is not None :
871952 print (f"speed_to_erpm_gain = { self .results ['speed_gain' ]:.1f} ;" )
872953
954+ if self .results ['max_steering_angle' ] is not None :
955+ print (f"max_steering_angle = { self .results ['max_steering_angle' ]:.4f} ; -- { math .degrees (self .results ['max_steering_angle' ]):.2f} degrees" )
956+ min_turn_radius = 0.324 / math .tan (self .results ['max_steering_angle' ])
957+ print (f" --> Minimum turning radius: { min_turn_radius :.3f} m" )
958+
873959 print ("-" * 60 )
874960
875961 print ("\n ⚠️ IMPORTANT: You must restart the VESC driver node for changes to take effect!" )
0 commit comments