Skip to content

Bump 1.0.2#90

Merged
robotpilot merged 14 commits into
humblefrom
main
Jan 13, 2026
Merged

Bump 1.0.2#90
robotpilot merged 14 commits into
humblefrom
main

Conversation

@GyuH13
Copy link
Copy Markdown
Member

@GyuH13 GyuH13 commented Jan 6, 2026

Dependency issues have been resolved through lazy imports, and the package is now ready for ROS distro release.
Additionally, updates have been made to address multiple PRs.

Copilot AI review requested due to automatic review settings January 6, 2026 08:24
@GyuH13 GyuH13 added the bump Increase the version number to release label Jan 6, 2026
@GyuH13 GyuH13 added this to Platform Jan 6, 2026
@github-project-automation github-project-automation Bot moved this to 🌱 Todo in Platform Jan 6, 2026
@GyuH13 GyuH13 moved this from 🌱 Todo to 📝 Pull Request in Platform Jan 6, 2026
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @GyuH13, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces version 1.0.2, primarily focusing on enhancing the robustness and configurability of the DQN (Deep Q-Network) package. Key improvements include resolving dependency conflicts through lazy TensorFlow imports, transitioning command-line arguments to ROS parameters for greater flexibility, and refining model loading and saving mechanisms. These changes aim to streamline development, improve user experience, and prepare the package for a new ROS distro release.

Highlights

  • Dependency Management: Implemented lazy imports for TensorFlow and Keras modules to resolve dependency issues, improving package loading efficiency and reducing initial startup overhead.
  • Configuration Flexibility: Migrated system arguments to ROS parameters, introducing new parameters like 'use_gpu', 'model_file', and 'verbose' for more dynamic and flexible configuration of the DQN agent during training and testing.
  • Model Management Enhancements: Added functionality to load existing trained models and continue training, along with renaming the 'load_model' boolean to 'use_pretrained_model' for clarity and making 'model_path' a local variable for better encapsulation.
  • Version Bump and Updates: Updated package versions to 1.0.2 across 'turtlebot3_dqn' and 'turtlebot3_machine_learning', including a fix for a JSON parameter name ('step' to 'step_counter') and adding 'Hyungyu Kim' as a new contributor.
  • README and Core Dependencies: The 'README.md' was updated to reflect current active and legacy branches and include a new driver link. Core Python dependencies ('tensorflow', 'numpy', 'scipy', 'keras') were explicitly added with specific versions to 'setup.py' for better dependency control.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/ros-ci.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several significant improvements, such as version bumping to 1.0.2, lazy loading of TensorFlow to handle dependency issues, and transitioning from command-line arguments to ROS 2 parameters for configuration. These are all positive changes that improve the package's usability and robustness. My review focuses on further enhancing robustness by adding error handling for file operations and parameter validation. I've also noted a change in the model saving behavior that might have unintended consequences on disk usage.

Comment on lines +87 to +88
model_file = self.get_parameter('model_file').get_parameter_value().string_value
use_gpu = self.get_parameter('use_gpu').get_parameter_value().bool_value
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The DQNTest node requires the model_file parameter to be set to a valid model file for testing. If this parameter is not provided, it defaults to an empty string, which will cause self.load_model() to fail with a potentially unclear error message. It would be more robust to add an explicit check for the model_file parameter and exit with an informative error if it's not provided.

Suggested change
model_file = self.get_parameter('model_file').get_parameter_value().string_value
use_gpu = self.get_parameter('use_gpu').get_parameter_value().bool_value
model_file = self.get_parameter('model_file').get_parameter_value().string_value
if not model_file:
self.get_logger().fatal("'model_file' parameter must be set for dqn_test.")
sys.exit(1)
use_gpu = self.get_parameter('use_gpu').get_parameter_value().bool_value

Comment on lines +180 to +184
with open(json_path) as outfile:
param = json.load(outfile)
self.epsilon = param.get('epsilon', self.epsilon)
self.step_counter = param.get('step_counter', self.step_counter)
self.load_episode = param.get('trained_episodes', self.load_episode)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The code for loading parameters from the JSON file does not handle potential json.JSONDecodeError if the file is corrupted. This could cause the node to crash. It's good practice to wrap the json.load() call in a try...except block to handle this case gracefully.

Suggested change
with open(json_path) as outfile:
param = json.load(outfile)
self.epsilon = param.get('epsilon', self.epsilon)
self.step_counter = param.get('step_counter', self.step_counter)
self.load_episode = param.get('trained_episodes', self.load_episode)
try:
with open(json_path) as outfile:
param = json.load(outfile)
self.epsilon = param.get('epsilon', self.epsilon)
self.step_counter = param.get('step_counter', self.step_counter)
self.load_episode = param.get('trained_episodes', self.load_episode)
except json.JSONDecodeError:
self.get_logger().error(f'Error decoding JSON from {json_path}. Using default values.')

Comment on lines +281 to 296
idx = 1
while True:
model_path = os.path.join(
self.model_dir_path,
f'model{idx}.h5'
)
json_path = os.path.join(
self.model_dir_path,
'stage' + str(self.stage) + '_episode' + str(episode) + '.json'
),
'w'
) as outfile:
f'model{idx}.json'
)
if not os.path.exists(model_path):
break
idx += 1
self.model.save(model_path)
with open(json_path, 'w') as outfile:
json.dump(param_dictionary, outfile)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current model saving logic creates a new model file (model1.h5, model2.h5, etc.) every 100 episodes without deleting old ones. This can lead to a large number of files and consume significant disk space during long training sessions. If this is not the intended behavior, you might consider a strategy to limit the number of saved checkpoints, such as checkpoint rotation or naming files with the episode number to allow for overwriting.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR bumps the package version from 1.0.1 to 1.0.2 and introduces dependency management improvements through lazy TensorFlow imports, preparing the package for ROS distro release. The key changes include transitioning from command-line arguments to ROS parameters, adding GPU configuration options, and improving model loading/saving functionality.

Key Changes:

  • Implemented lazy imports for TensorFlow modules to resolve dependency issues
  • Migrated from system arguments (sys.argv) to ROS parameters for configuration
  • Added use_gpu and model_file parameters for better control over training and testing

Reviewed changes

Copilot reviewed 11 out of 13 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
turtlebot3_machine_learning/package.xml Version bump to 1.0.2 and added new author
turtlebot3_machine_learning/CHANGELOG.rst Added changelog entry for 1.0.2 release
turtlebot3_dqn/turtlebot3_dqn/dqn_test.py Implemented lazy TensorFlow imports and migrated to ROS parameters
turtlebot3_dqn/turtlebot3_dqn/dqn_agent.py Implemented lazy imports, ROS parameters, and improved model saving with sequential naming
turtlebot3_dqn/setup.py Version bump, new author, and explicit dependency specifications
turtlebot3_dqn/saved_model/stage1_episode600.json Removed old model JSON file
turtlebot3_dqn/saved_model/model1.json Added new model JSON with updated parameter names
turtlebot3_dqn/package.xml Version bump, new author, and removed explicit Python dependency declarations
turtlebot3_dqn/CHANGELOG.rst Added changelog entry for 1.0.2 release
README.md Updated branch information and added coin_d4_driver to project list
.github/workflows/ros-ci.yml Added rosdep check step to verify dependency resolution

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +186 to +187
self.get_logger().error('Loaded model episode exceeds max training episodes.')
raise ValueError('Loaded model episode exceeds max training episodes.')
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message states "Loaded model episode exceeds max training episodes" but the condition checks if load_episode >= max_training_episodes. This means the error will trigger even when they are equal, not just when it exceeds. Either the message should be updated to "Loaded model episode meets or exceeds max training episodes" or the condition should be changed to load_episode > max_training_episodes.

Suggested change
self.get_logger().error('Loaded model episode exceeds max training episodes.')
raise ValueError('Loaded model episode exceeds max training episodes.')
self.get_logger().error('Loaded model episode meets or exceeds max training episodes.')
raise ValueError('Loaded model episode meets or exceeds max training episodes.')

Copilot uses AI. Check for mistakes.
def get_action(self, state):
state = numpy.asarray(state)
q_values = self.model.predict(state.reshape(1, -1), verbose=0)
q_values = self.model.predict(state.reshape(1, -1), verbose=self.verbose)
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'verbose' parameter in model.predict() expects an integer (0, 1, or 2) to control logging verbosity, but self.verbose is a boolean. When verbose=True, it will be interpreted as 1 (showing progress bar), and when verbose=False, it will be 0 (silent). While this works, it would be clearer to explicitly convert the boolean to the expected integer values (e.g., 1 if self.verbose else 0) or declare the parameter as an integer type to match the API expectations.

Suggested change
q_values = self.model.predict(state.reshape(1, -1), verbose=self.verbose)
q_values = self.model.predict(state.reshape(1, -1),
verbose=1 if self.verbose else 0)

Copilot uses AI. Check for mistakes.
local_step += 1

q_values = self.model.predict(state)
q_values = self.model.predict(state, verbose=self.verbose)
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'verbose' parameter in model.predict() expects an integer (0, 1, or 2) to control logging verbosity, but self.verbose is a boolean. When verbose=True, it will be interpreted as 1 (showing progress bar), and when verbose=False, it will be 0 (silent). While this works, it would be clearer to explicitly convert the boolean to the expected integer values (e.g., 1 if self.verbose else 0) or declare the parameter as an integer type to match the API expectations.

Suggested change
q_values = self.model.predict(state, verbose=self.verbose)
verbose_level = 1 if self.verbose else 0
q_values = self.model.predict(state, verbose=verbose_level)

Copilot uses AI. Check for mistakes.
<author email="kkjong@robotis.com">Gilbert</author>
<author email="dddoggi1207@gmail.com">ChanHyeong Lee</author>
<author email="kimhg@robotis.com">Hyungyu Kim</author>
<exec_depend>python3-pip</exec_depend>
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dependencies 'python-tensorflow-pip' and 'python3-numpy' have been removed from exec_depend, but these are now specified in setup.py's install_requires. While this may work, it's important to ensure that the ROS dependency resolution system can properly handle Python package dependencies specified only in setup.py. Consider whether these should remain as exec_depend entries for better ROS ecosystem integration.

Suggested change
<exec_depend>python3-pip</exec_depend>
<exec_depend>python3-pip</exec_depend>
<exec_depend>python-tensorflow-pip</exec_depend>
<exec_depend>python3-numpy</exec_depend>

Copilot uses AI. Check for mistakes.
Comment thread turtlebot3_dqn/setup.py
Comment on lines +28 to +31
'tensorflow==2.19.0',
'numpy==1.26.4',
'scipy==1.10.1',
'keras==3.9.2',
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinning specific versions of TensorFlow, NumPy, SciPy, and Keras in install_requires can cause dependency conflicts and make the package less flexible. These exact versions may not be compatible with all systems or other dependencies. Consider using version ranges (e.g., 'tensorflow>=2.19.0,<3.0.0') or removing the version constraints if the code is compatible with multiple versions.

Suggested change
'tensorflow==2.19.0',
'numpy==1.26.4',
'scipy==1.10.1',
'keras==3.9.2',
'tensorflow>=2.19.0,<3.0.0',
'numpy>=1.26.4,<2.0.0',
'scipy>=1.10.1,<2.0.0',
'keras>=3.9.2,<4.0.0',

Copilot uses AI. Check for mistakes.
Comment on lines +281 to 296
idx = 1
while True:
model_path = os.path.join(
self.model_dir_path,
f'model{idx}.h5'
)
json_path = os.path.join(
self.model_dir_path,
'stage' + str(self.stage) + '_episode' + str(episode) + '.json'
),
'w'
) as outfile:
f'model{idx}.json'
)
if not os.path.exists(model_path):
break
idx += 1
self.model.save(model_path)
with open(json_path, 'w') as outfile:
json.dump(param_dictionary, outfile)
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The model saving logic increments the model file index without bound. This could lead to an accumulation of model files over time. Consider implementing a cleanup strategy or limiting the number of saved models (e.g., keeping only the last N models) to prevent disk space issues during long training runs.

Copilot uses AI. Check for mistakes.
tensorflow.config.set_visible_devices([], 'GPU')

LOGGING = True
current_time = datetime.datetime.now().strftime('[%mm%dd-%H:%M]')
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The datetime format string '%mm%dd' contains lowercase 'm' which represents minutes, not months. This should be '%m%d' to properly format the date as month and day. The current format will produce incorrect timestamps like '[01m06d-12:34]' instead of the intended '[0106-12:34]'.

Suggested change
current_time = datetime.datetime.now().strftime('[%mm%dd-%H:%M]')
current_time = datetime.datetime.now().strftime('[%m%d-%H:%M]')

Copilot uses AI. Check for mistakes.
@robotpilot robotpilot merged commit 4db57a8 into humble Jan 13, 2026
30 checks passed
@github-project-automation github-project-automation Bot moved this from 📝 Pull Request to 🚩Done in Platform Jan 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bump Increase the version number to release

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants