devagent-physical-engine 1.6.0__tar.gz → 1.6.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {devagent_physical_engine-1.6.0/src/devagent_physical_engine.egg-info → devagent_physical_engine-1.6.2}/PKG-INFO +30 -5
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/README.md +29 -4
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/pyproject.toml +1 -1
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/__init__.py +5 -1
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/joint_state_recorder.py +40 -4
- devagent_physical_engine-1.6.2/src/devagent_physical_engine/ros2/moveit_joint_plan_v161_probe.py +154 -0
- devagent_physical_engine-1.6.2/src/devagent_physical_engine/ros2/support_contact_runner_v161.py +41 -0
- devagent_physical_engine-1.6.2/src/devagent_physical_engine/ros2/support_contact_v161.py +165 -0
- devagent_physical_engine-1.6.2/src/devagent_physical_engine/smooth_motion_hotfix_v162.py +39 -0
- devagent_physical_engine-1.6.2/src/devagent_physical_engine/support_contact_hotfix_v161.py +12 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2/src/devagent_physical_engine.egg-info}/PKG-INFO +30 -5
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine.egg-info/SOURCES.txt +8 -0
- devagent_physical_engine-1.6.2/tests/test_golden_abb_showcase.py +102 -0
- devagent_physical_engine-1.6.2/tests/test_smooth_motion_hotfix_v162.py +81 -0
- devagent_physical_engine-1.6.2/tests/test_support_contact_hotfix_v161.py +169 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/NOTICE +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/setup.cfg +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/__init__.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/compiler.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/contracts.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/coordinator.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/critic.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/evidence.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/interpreter.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/planner.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/recovery.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/routing.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/runtime.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/semantic.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/agent/structured.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ai_cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial_campaign.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial_cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial_importer.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial_intelligence.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial_readiness.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/commercial_repository.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/continuous_clearance.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/doctor.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/engineering_agent.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/engineering_request.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/evidence_replay.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/evidence_trust.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/execution.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/models.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/one_command.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/one_command_runtime.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/one_command_v15.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/one_command_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/operating_envelope.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/__init__.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/benchmark.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/candidates.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/contracts.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/evaluator.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/evidence.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/experience.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/measured.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/optimizer.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/optimization/orchestrator.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/physical_campaign.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/physical_evidence.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/physical_motion.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/planning.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/pose_math.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/preexecution_contract.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/production_authority.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/production_grade.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/project.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_adapters/__init__.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_adapters/anthropic.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_adapters/common.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_adapters/factory.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_adapters/gemini.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_adapters/openai.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_criterion.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/provider_qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/providers.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/qualification_cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/qualification_harness.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/reference_workcell.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/report_test_execution.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/report_test_execution_strict.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/robot_platform.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/robots.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/__init__.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/acceptance.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/commands.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/continuous_clearance_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/doctor.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/fk_pose.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/fk_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/frame_alignment.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/gazebo_cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/gazebo_pose.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/gazebo_world.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/joint_state_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/measured_motion.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/moveit_joint_plan_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/moveit_scene.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/moveit_task_planner.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/preexecution.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/qualification_v10.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/qualification_v11.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/qualification_v12.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/report_test_visualization.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/scene_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/state_validity_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/task_adapter.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/task_visualization.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/tf_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/tool_scene.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/tool_scene_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/trajectory.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/trajectory_action_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/trajectory_tracking.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/ur5e.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/ur5e_adapter.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/ur5e_v10_adapter.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/workpiece_follow.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/workpiece_gazebo_follower.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/workpiece_scene.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/ros2/workpiece_scene_probe.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/selective_verification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/selective_verification_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/setup_profile.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/sim_real_qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/simulation.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/simulation_platform.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/tool_collision.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/trajectory_qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/twin.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/twin_builder.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/twin_codec.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/twin_materialization.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/user_cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/user_cli_v15.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/user_cli_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/verification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine/workpiece_lifecycle.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine.egg-info/dependency_links.txt +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine.egg-info/entry_points.txt +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine.egg-info/requires.txt +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/src/devagent_physical_engine.egg-info/top_level.txt +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_agent_core.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_agent_semantic_hardening.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ai_cli.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ai_cli_v07.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_commercial_importer_v1.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_commercial_intelligence_v15.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_commercial_readiness_v1.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_commercial_v1.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_continuous_clearance_v011.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_core.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_engineering_request_v07.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_evidence_replay_v12.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_evidence_trust_coverage_v12.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_evidence_trust_transport_v12.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_evidence_trust_v12.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_evidence_viewer_palette_v130.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_gazebo_cli_v0122.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_interpreter_profiles_v08.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_joint_state_probe_v0125.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_live_provider_qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_measured_motion_v10.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_moveit_planning_diagnostics_v0125.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_moveit_scene_v0123.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_natural_language_agent_v07.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_one_command_hardening_v13.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_one_command_pose_hardening_v15.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_one_command_regression_v141.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_one_command_v13.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_openai_strict_schema_v0113.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_optimization_v05.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_physical_campaign_v09.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_physical_evidence_v09.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_physical_motion_v09.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_planning_fallback_v012.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_pose_math_v0125.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_preexecution_contract_v10.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_production_authority_v11.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_production_grade_coverage_v11.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_production_grade_v11.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_project_spine_v013.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_provider_and_qualification.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_provider_criterion_v15.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_qualification_cli_lifecycle_v06.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_qualification_harness_v06.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_readme_pypi.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_real_provider_adapters.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_reference_workcell_ros_frames_v0125.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_reference_workcell_v012.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_report_test_contract_coverage_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_report_test_lineage_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_report_test_visual_execution_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_robot_platform_v08.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ros2_production_receipts_v011.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ros2_simulation.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ros_trajectory_v09.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_selective_verification_v14.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_setup_profile.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_sim_real_qualification_v011.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_simulation_platform_v08.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_tool_collision_v011.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_tool_scene_v0124.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_trajectory_action_probe_v0125.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_trajectory_qualification_v09.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_trajectory_tracking_v0125.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_twin_materialization_v10.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_twin_v08.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ur5e_adapter_scopes_v09.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_ur5e_v10_adapter_scopes.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_user_cli_interactive_v131.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_user_cli_progress_v131.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_user_cli_report_visual_v16.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_user_cli_selective_v14.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_user_cli_v15.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_user_cli_v15_hotfix_inheritance.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_v052_stabilization.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_v08_catalog_mapping_regression.py +0 -0
- {devagent_physical_engine-1.6.0 → devagent_physical_engine-1.6.2}/tests/test_workpiece_lifecycle_v011.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devagent-physical-engine
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
4
4
|
Summary: Production-grade verification-first robotics evidence runtime with one-command customer intake, validated requirement mapping, report-test Gazebo visualization, requirement-driven test generation, selective verification, deterministic Twin lineage, measured physical verification, replay inspection, regression, and FAT evidence.
|
|
5
5
|
Author: Tom Ha
|
|
6
6
|
License: All Rights Reserved
|
|
@@ -82,7 +82,7 @@ DevAgent is designed to answer: **What can be proven about this cell, what faile
|
|
|
82
82
|
Python 3.11+ is required.
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
python -m pip install --upgrade devagent-physical-engine==1.6.
|
|
85
|
+
python -m pip install --upgrade devagent-physical-engine==1.6.2
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
Verify the installed package:
|
|
@@ -94,7 +94,7 @@ python -c "import devagent_physical_engine as d; print(d.__version__)"
|
|
|
94
94
|
Expected:
|
|
95
95
|
|
|
96
96
|
```text
|
|
97
|
-
1.6.
|
|
97
|
+
1.6.2
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
Run the normal customer workflow:
|
|
@@ -207,6 +207,31 @@ devagent-physical ros demo
|
|
|
207
207
|
|
|
208
208
|
for report evidence.
|
|
209
209
|
|
|
210
|
+
## v1.6.1 support-contact lift hotfix
|
|
211
|
+
|
|
212
|
+
The qualified reference load profile starts with the workpiece physically resting on its source support. During the first attached-object `lift` preflight, v1.6.1 preserves the complete live MoveIt Allowed Collision Matrix and enables exactly one temporary request-local pair:
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
attached workpiece ↔ conveyor_a support surface
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
That allowance is scoped to lift departure only. Transfer/place keep normal collision checking, no global PlanningScene collision policy is disabled, and the live ACM is never replaced by a sparse two-object matrix.
|
|
219
|
+
|
|
220
|
+
## v1.6.2 smooth visual motion hotfix
|
|
221
|
+
|
|
222
|
+
v1.6.2 makes the packaged UR5e visual task deliberately slower and easier to inspect. The task-specific MoveIt planner defaults are reduced from 25% velocity / 25% acceleration to:
|
|
223
|
+
|
|
224
|
+
```text
|
|
225
|
+
velocity scale: 12%
|
|
226
|
+
acceleration scale: 8%
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
This is real trajectory time parameterization through MoveIt and `FollowJointTrajectory`; DevAgent does not fake smoothness with teleports or sleeps. Explicit planner scales remain authoritative. Collision checks, endpoint tolerances, tracking tolerances, Twin lineage, and real-execution authority are unchanged.
|
|
230
|
+
|
|
231
|
+
The joint-state recorder also rejects duplicate/backward ROS source timestamps before trajectory interpolation while recording the number of dropped samples. This removes the false `trajectory_tracking_time_not_increasing` failure caused by duplicate Gazebo/ros2_control JointState stamps without manufacturing synthetic timestamps.
|
|
232
|
+
|
|
233
|
+
Because the visual trajectory now executes more slowly, cycle-time requirements are evaluated against the actual slower simulation execution. DevAgent does not normalize the observed duration back to a faster value or claim performance that was not executed.
|
|
234
|
+
|
|
210
235
|
## Exact lineage hardening
|
|
211
236
|
|
|
212
237
|
A case ID such as `case-0001` is local to its verification plan. v1.6 therefore requires the complete lineage:
|
|
@@ -502,9 +527,9 @@ devagent-physical-ai optional provider-backed engineering front end
|
|
|
502
527
|
|
|
503
528
|
# Project status
|
|
504
529
|
|
|
505
|
-
**v1.6.
|
|
530
|
+
**v1.6.2 — Production/Stable software workflow**
|
|
506
531
|
|
|
507
|
-
v1.6.
|
|
532
|
+
v1.6.2 slows the packaged UR5e task/report visual motion to conservative 12% velocity / 8% acceleration defaults and hardens JointState acquisition against duplicate/backward ROS timestamps. It retains the v1.6.1 lift support-contact fix, exact-Twin report execution, immutable Requirement→Mapping→Verification Plan→Case lineage, typed simulation measurements, and fail-closed authority boundaries.
|
|
508
533
|
|
|
509
534
|
Production-oriented software capabilities include:
|
|
510
535
|
|
|
@@ -41,7 +41,7 @@ DevAgent is designed to answer: **What can be proven about this cell, what faile
|
|
|
41
41
|
Python 3.11+ is required.
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
python -m pip install --upgrade devagent-physical-engine==1.6.
|
|
44
|
+
python -m pip install --upgrade devagent-physical-engine==1.6.2
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Verify the installed package:
|
|
@@ -53,7 +53,7 @@ python -c "import devagent_physical_engine as d; print(d.__version__)"
|
|
|
53
53
|
Expected:
|
|
54
54
|
|
|
55
55
|
```text
|
|
56
|
-
1.6.
|
|
56
|
+
1.6.2
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
Run the normal customer workflow:
|
|
@@ -166,6 +166,31 @@ devagent-physical ros demo
|
|
|
166
166
|
|
|
167
167
|
for report evidence.
|
|
168
168
|
|
|
169
|
+
## v1.6.1 support-contact lift hotfix
|
|
170
|
+
|
|
171
|
+
The qualified reference load profile starts with the workpiece physically resting on its source support. During the first attached-object `lift` preflight, v1.6.1 preserves the complete live MoveIt Allowed Collision Matrix and enables exactly one temporary request-local pair:
|
|
172
|
+
|
|
173
|
+
```text
|
|
174
|
+
attached workpiece ↔ conveyor_a support surface
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
That allowance is scoped to lift departure only. Transfer/place keep normal collision checking, no global PlanningScene collision policy is disabled, and the live ACM is never replaced by a sparse two-object matrix.
|
|
178
|
+
|
|
179
|
+
## v1.6.2 smooth visual motion hotfix
|
|
180
|
+
|
|
181
|
+
v1.6.2 makes the packaged UR5e visual task deliberately slower and easier to inspect. The task-specific MoveIt planner defaults are reduced from 25% velocity / 25% acceleration to:
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
velocity scale: 12%
|
|
185
|
+
acceleration scale: 8%
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
This is real trajectory time parameterization through MoveIt and `FollowJointTrajectory`; DevAgent does not fake smoothness with teleports or sleeps. Explicit planner scales remain authoritative. Collision checks, endpoint tolerances, tracking tolerances, Twin lineage, and real-execution authority are unchanged.
|
|
189
|
+
|
|
190
|
+
The joint-state recorder also rejects duplicate/backward ROS source timestamps before trajectory interpolation while recording the number of dropped samples. This removes the false `trajectory_tracking_time_not_increasing` failure caused by duplicate Gazebo/ros2_control JointState stamps without manufacturing synthetic timestamps.
|
|
191
|
+
|
|
192
|
+
Because the visual trajectory now executes more slowly, cycle-time requirements are evaluated against the actual slower simulation execution. DevAgent does not normalize the observed duration back to a faster value or claim performance that was not executed.
|
|
193
|
+
|
|
169
194
|
## Exact lineage hardening
|
|
170
195
|
|
|
171
196
|
A case ID such as `case-0001` is local to its verification plan. v1.6 therefore requires the complete lineage:
|
|
@@ -461,9 +486,9 @@ devagent-physical-ai optional provider-backed engineering front end
|
|
|
461
486
|
|
|
462
487
|
# Project status
|
|
463
488
|
|
|
464
|
-
**v1.6.
|
|
489
|
+
**v1.6.2 — Production/Stable software workflow**
|
|
465
490
|
|
|
466
|
-
v1.6.
|
|
491
|
+
v1.6.2 slows the packaged UR5e task/report visual motion to conservative 12% velocity / 8% acceleration defaults and hardens JointState acquisition against duplicate/backward ROS timestamps. It retains the v1.6.1 lift support-contact fix, exact-Twin report execution, immutable Requirement→Mapping→Verification Plan→Case lineage, typed simulation measurements, and fail-closed authority boundaries.
|
|
467
492
|
|
|
468
493
|
Production-oriented software capabilities include:
|
|
469
494
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "devagent-physical-engine"
|
|
7
|
-
version = "1.6.
|
|
7
|
+
version = "1.6.2"
|
|
8
8
|
description = "Production-grade verification-first robotics evidence runtime with one-command customer intake, validated requirement mapping, report-test Gazebo visualization, requirement-driven test generation, selective verification, deterministic Twin lineage, measured physical verification, replay inspection, regression, and FAT evidence."
|
|
9
9
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -108,6 +108,8 @@ from .selective_verification import (
|
|
|
108
108
|
VerificationTestMappingRecorder,
|
|
109
109
|
)
|
|
110
110
|
from .selective_verification_v16 import SelectiveVerificationServiceV16
|
|
111
|
+
from .smooth_motion_hotfix_v162 import install_smooth_motion_hotfix_v162
|
|
112
|
+
from .support_contact_hotfix_v161 import install_support_contact_hotfix_v161
|
|
111
113
|
from .twin import TwinConfidenceLevel, TwinSpec, TwinValidationReport, TwinValidator
|
|
112
114
|
from .twin_codec import twin_from_dict, twin_from_revision
|
|
113
115
|
|
|
@@ -209,6 +211,8 @@ __all__ = [
|
|
|
209
211
|
"twin_from_revision",
|
|
210
212
|
]
|
|
211
213
|
|
|
214
|
+
install_support_contact_hotfix_v161()
|
|
215
|
+
install_smooth_motion_hotfix_v162()
|
|
212
216
|
install_one_command_runtime()
|
|
213
217
|
|
|
214
|
-
__version__ = "1.6.
|
|
218
|
+
__version__ = "1.6.2"
|
|
@@ -14,6 +14,29 @@ def _atomic_json(path: Path, payload: dict[str, object]) -> None:
|
|
|
14
14
|
temporary.replace(path)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def accepted_sample_time_ns(
|
|
18
|
+
*,
|
|
19
|
+
stamped_ns: int,
|
|
20
|
+
fallback_ns: int,
|
|
21
|
+
previous_ns: int | None,
|
|
22
|
+
) -> int | None:
|
|
23
|
+
"""Return one strictly increasing sample timestamp or reject the duplicate.
|
|
24
|
+
|
|
25
|
+
Some ros2_control/Gazebo publishers can emit more than one JointState callback
|
|
26
|
+
with the same ROS header stamp. Tracking interpolation requires a strictly
|
|
27
|
+
increasing time axis, so duplicate/backward source stamps are discarded rather
|
|
28
|
+
than silently perturbing their timestamps. The recorder reports how many samples
|
|
29
|
+
were discarded so the raw acquisition behavior remains auditable.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
candidate = int(stamped_ns) if int(stamped_ns) > 0 else int(fallback_ns)
|
|
33
|
+
if candidate < 0:
|
|
34
|
+
return None
|
|
35
|
+
if previous_ns is not None and candidate <= int(previous_ns):
|
|
36
|
+
return None
|
|
37
|
+
return candidate
|
|
38
|
+
|
|
39
|
+
|
|
17
40
|
def main() -> int:
|
|
18
41
|
parser = argparse.ArgumentParser()
|
|
19
42
|
parser.add_argument("--output", required=True)
|
|
@@ -30,6 +53,7 @@ def main() -> int:
|
|
|
30
53
|
samples: list[dict[str, object]] = []
|
|
31
54
|
overflow = False
|
|
32
55
|
ready_written = False
|
|
56
|
+
dropped_non_increasing = 0
|
|
33
57
|
|
|
34
58
|
import rclpy
|
|
35
59
|
from sensor_msgs.msg import JointState
|
|
@@ -37,20 +61,29 @@ def main() -> int:
|
|
|
37
61
|
rclpy.init()
|
|
38
62
|
node = rclpy.create_node("devagent_joint_state_recorder")
|
|
39
63
|
started_ns: int | None = None
|
|
64
|
+
previous_ns: int | None = None
|
|
40
65
|
|
|
41
66
|
def callback(message: JointState) -> None:
|
|
42
|
-
nonlocal started_ns, overflow, ready_written
|
|
67
|
+
nonlocal started_ns, previous_ns, overflow, ready_written, dropped_non_increasing
|
|
43
68
|
stamp = message.header.stamp
|
|
44
69
|
stamped_ns = int(stamp.sec) * 1_000_000_000 + int(stamp.nanosec)
|
|
45
|
-
|
|
70
|
+
selected_ns = accepted_sample_time_ns(
|
|
71
|
+
stamped_ns=stamped_ns,
|
|
72
|
+
fallback_ns=node.get_clock().now().nanoseconds,
|
|
73
|
+
previous_ns=previous_ns,
|
|
74
|
+
)
|
|
75
|
+
if selected_ns is None:
|
|
76
|
+
dropped_non_increasing += 1
|
|
77
|
+
return
|
|
78
|
+
previous_ns = selected_ns
|
|
46
79
|
if started_ns is None:
|
|
47
|
-
started_ns =
|
|
80
|
+
started_ns = selected_ns
|
|
48
81
|
if len(samples) >= int(args.max_samples):
|
|
49
82
|
overflow = True
|
|
50
83
|
return
|
|
51
84
|
samples.append(
|
|
52
85
|
{
|
|
53
|
-
"time_s": (
|
|
86
|
+
"time_s": (selected_ns - started_ns) / 1_000_000_000.0,
|
|
54
87
|
"names": list(message.name),
|
|
55
88
|
"positions_rad": list(message.position),
|
|
56
89
|
}
|
|
@@ -62,6 +95,7 @@ def main() -> int:
|
|
|
62
95
|
"ready": True,
|
|
63
96
|
"topic": args.topic,
|
|
64
97
|
"first_sample_received": True,
|
|
98
|
+
"strictly_increasing_time": True,
|
|
65
99
|
},
|
|
66
100
|
)
|
|
67
101
|
ready_written = True
|
|
@@ -77,6 +111,8 @@ def main() -> int:
|
|
|
77
111
|
"sample_count": len(samples),
|
|
78
112
|
"overflow": overflow,
|
|
79
113
|
"ready_observed": ready_written,
|
|
114
|
+
"strictly_increasing_time": True,
|
|
115
|
+
"dropped_non_increasing_count": dropped_non_increasing,
|
|
80
116
|
"samples": samples,
|
|
81
117
|
}
|
|
82
118
|
_atomic_json(output, payload)
|
devagent_physical_engine-1.6.2/src/devagent_physical_engine/ros2/moveit_joint_plan_v161_probe.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Any, Mapping
|
|
8
|
+
|
|
9
|
+
# ROS helpers are executed by absolute file path under the distro Python rather than
|
|
10
|
+
# the caller's virtualenv. Add the package src root explicitly so this hotfix can reuse
|
|
11
|
+
# the validated v1.6 probe contract without inheriting virtualenv Python overrides.
|
|
12
|
+
_SRC_ROOT = Path(__file__).resolve().parents[2]
|
|
13
|
+
if str(_SRC_ROOT) not in sys.path:
|
|
14
|
+
sys.path.insert(0, str(_SRC_ROOT))
|
|
15
|
+
|
|
16
|
+
from devagent_physical_engine.ros2 import moveit_joint_plan_probe as base
|
|
17
|
+
from devagent_physical_engine.ros2.support_contact_v161 import (
|
|
18
|
+
SUPPORT_CONTACT_SCOPE,
|
|
19
|
+
SupportContactContractError,
|
|
20
|
+
allow_only_support_pair,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _support_contract(path: Path) -> tuple[str, str] | None:
|
|
25
|
+
try:
|
|
26
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
27
|
+
except (OSError, json.JSONDecodeError) as exc:
|
|
28
|
+
raise SupportContactContractError("support_contact_request_invalid") from exc
|
|
29
|
+
if not isinstance(payload, Mapping):
|
|
30
|
+
raise SupportContactContractError("support_contact_request_invalid")
|
|
31
|
+
scene = payload.get("scene_contract")
|
|
32
|
+
if not isinstance(scene, Mapping) or scene.get("allow_support_contact") is not True:
|
|
33
|
+
return None
|
|
34
|
+
if str(scene.get("state") or "") != "attached":
|
|
35
|
+
raise SupportContactContractError("support_contact_requires_attached_scene")
|
|
36
|
+
if str(scene.get("support_contact_scope") or "") != SUPPORT_CONTACT_SCOPE:
|
|
37
|
+
raise SupportContactContractError("support_contact_scope_invalid")
|
|
38
|
+
workpiece = scene.get("workpiece")
|
|
39
|
+
if not isinstance(workpiece, Mapping):
|
|
40
|
+
raise SupportContactContractError("support_contact_workpiece_missing")
|
|
41
|
+
workpiece_id = str(workpiece.get("id") or "").strip()
|
|
42
|
+
support_id = str(scene.get("support_surface_id") or "").strip()
|
|
43
|
+
if not workpiece_id or not support_id or workpiece_id == support_id:
|
|
44
|
+
raise SupportContactContractError("support_contact_pair_invalid")
|
|
45
|
+
return workpiece_id, support_id
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _read_live_acm(*, timeout_s: float) -> dict[str, Any]:
|
|
49
|
+
import rclpy
|
|
50
|
+
from moveit_msgs.msg import PlanningSceneComponents
|
|
51
|
+
from moveit_msgs.srv import GetPlanningScene
|
|
52
|
+
|
|
53
|
+
rclpy.init()
|
|
54
|
+
node = rclpy.create_node("devagent_moveit_support_acm_probe_v161")
|
|
55
|
+
client = node.create_client(GetPlanningScene, "/get_planning_scene")
|
|
56
|
+
try:
|
|
57
|
+
if not client.wait_for_service(timeout_sec=timeout_s):
|
|
58
|
+
raise SupportContactContractError("moveit_planning_scene_service_unavailable")
|
|
59
|
+
request = GetPlanningScene.Request()
|
|
60
|
+
request.components.components = PlanningSceneComponents.ALLOWED_COLLISION_MATRIX
|
|
61
|
+
future = client.call_async(request)
|
|
62
|
+
rclpy.spin_until_future_complete(node, future, timeout_sec=timeout_s)
|
|
63
|
+
if not future.done() or future.result() is None:
|
|
64
|
+
raise SupportContactContractError("moveit_planning_scene_acm_timeout")
|
|
65
|
+
acm = future.result().scene.allowed_collision_matrix
|
|
66
|
+
return {
|
|
67
|
+
"entry_names": [str(value) for value in acm.entry_names],
|
|
68
|
+
"entry_values": [list(item.enabled) for item in acm.entry_values],
|
|
69
|
+
"default_entry_names": [str(value) for value in acm.default_entry_names],
|
|
70
|
+
"default_entry_values": [bool(value) for value in acm.default_entry_values],
|
|
71
|
+
}
|
|
72
|
+
finally:
|
|
73
|
+
node.destroy_client(client)
|
|
74
|
+
node.destroy_node()
|
|
75
|
+
if rclpy.ok():
|
|
76
|
+
rclpy.shutdown()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _install_full_acm(payload: Mapping[str, Any]):
|
|
80
|
+
original = base._apply_scene_contract
|
|
81
|
+
|
|
82
|
+
def apply(goal, contract):
|
|
83
|
+
original(goal, contract)
|
|
84
|
+
from moveit_msgs.msg import AllowedCollisionEntry
|
|
85
|
+
|
|
86
|
+
acm = goal.planning_options.planning_scene_diff.allowed_collision_matrix
|
|
87
|
+
acm.entry_names = list(payload["entry_names"])
|
|
88
|
+
acm.entry_values = [
|
|
89
|
+
AllowedCollisionEntry(enabled=list(row))
|
|
90
|
+
for row in payload["entry_values"]
|
|
91
|
+
]
|
|
92
|
+
acm.default_entry_names = list(payload["default_entry_names"])
|
|
93
|
+
acm.default_entry_values = list(payload["default_entry_values"])
|
|
94
|
+
|
|
95
|
+
base._apply_scene_contract = apply
|
|
96
|
+
return original
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def plan(path: Path, *, timeout_s: float) -> dict[str, Any]:
|
|
100
|
+
support = _support_contract(path)
|
|
101
|
+
if support is None:
|
|
102
|
+
return base.plan(path, timeout_s=timeout_s)
|
|
103
|
+
workpiece_id, support_id = support
|
|
104
|
+
live = _read_live_acm(timeout_s=timeout_s)
|
|
105
|
+
augmented = allow_only_support_pair(
|
|
106
|
+
live,
|
|
107
|
+
workpiece_id=workpiece_id,
|
|
108
|
+
support_surface_id=support_id,
|
|
109
|
+
)
|
|
110
|
+
original = _install_full_acm(augmented)
|
|
111
|
+
try:
|
|
112
|
+
result = dict(base.plan(path, timeout_s=timeout_s))
|
|
113
|
+
finally:
|
|
114
|
+
base._apply_scene_contract = original
|
|
115
|
+
result.update(
|
|
116
|
+
{
|
|
117
|
+
"support_contact_allowed": True,
|
|
118
|
+
"support_contact_scope": SUPPORT_CONTACT_SCOPE,
|
|
119
|
+
"support_surface_id": support_id,
|
|
120
|
+
"support_workpiece_id": workpiece_id,
|
|
121
|
+
"support_acm_entry_count": len(augmented["entry_names"]),
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
if (
|
|
125
|
+
result.get("success") is not True
|
|
126
|
+
and str(result.get("code") or "").startswith("move_group_action_status_")
|
|
127
|
+
):
|
|
128
|
+
result["underlying_code"] = result.get("code")
|
|
129
|
+
result["code"] = "moveit_support_contact_departure_aborted"
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def main() -> int:
|
|
134
|
+
parser = argparse.ArgumentParser()
|
|
135
|
+
parser.add_argument("--input", required=True)
|
|
136
|
+
parser.add_argument("--timeout", type=float, default=15.0)
|
|
137
|
+
args = parser.parse_args()
|
|
138
|
+
try:
|
|
139
|
+
result = plan(
|
|
140
|
+
Path(args.input).expanduser().resolve(),
|
|
141
|
+
timeout_s=float(args.timeout),
|
|
142
|
+
)
|
|
143
|
+
except Exception as exc:
|
|
144
|
+
result = {
|
|
145
|
+
"success": False,
|
|
146
|
+
"code": f"moveit_support_contact_probe_error:{type(exc).__name__}",
|
|
147
|
+
"detail": str(exc),
|
|
148
|
+
}
|
|
149
|
+
print(json.dumps(result, sort_keys=True))
|
|
150
|
+
return 0 if result.get("success") else 2
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
if __name__ == "__main__":
|
|
154
|
+
raise SystemExit(main())
|
devagent_physical_engine-1.6.2/src/devagent_physical_engine/ros2/support_contact_runner_v161.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Sequence
|
|
5
|
+
|
|
6
|
+
from .commands import CommandResult, SubprocessRosRunner
|
|
7
|
+
from .support_contact_v161 import prepare_lift_support_request
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
_LEGACY_PROBE = "moveit_joint_plan_probe.py"
|
|
11
|
+
_HOTFIX_PROBE = "moveit_joint_plan_v161_probe.py"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def rewrite_moveit_probe_command(command: Sequence[str]) -> tuple[str, ...]:
|
|
15
|
+
rewritten = [str(value) for value in command]
|
|
16
|
+
if len(rewritten) < 2 or Path(rewritten[1]).name != _LEGACY_PROBE:
|
|
17
|
+
return tuple(rewritten)
|
|
18
|
+
try:
|
|
19
|
+
input_index = rewritten.index("--input") + 1
|
|
20
|
+
request_path = Path(rewritten[input_index]).expanduser().resolve()
|
|
21
|
+
except (ValueError, IndexError):
|
|
22
|
+
return tuple(rewritten)
|
|
23
|
+
if not prepare_lift_support_request(request_path):
|
|
24
|
+
return tuple(rewritten)
|
|
25
|
+
rewritten[1] = str(Path(__file__).with_name(_HOTFIX_PROBE).resolve())
|
|
26
|
+
return tuple(rewritten)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class SupportContactSubprocessRosRunner(SubprocessRosRunner):
|
|
30
|
+
"""Report-test ROS runner with a bounded lift support-contact preflight hotfix."""
|
|
31
|
+
|
|
32
|
+
def run(
|
|
33
|
+
self,
|
|
34
|
+
command: Sequence[str],
|
|
35
|
+
*,
|
|
36
|
+
timeout_s: float = 15.0,
|
|
37
|
+
) -> CommandResult:
|
|
38
|
+
return super().run(
|
|
39
|
+
rewrite_moveit_probe_command(command),
|
|
40
|
+
timeout_s=timeout_s,
|
|
41
|
+
)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Mapping, Sequence
|
|
7
|
+
|
|
8
|
+
from ..twin_materialization import _backend_id as _materialized_backend_id
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
QUALIFIED_SOURCE_ENTITY_ID = "conveyor_a"
|
|
12
|
+
SUPPORT_CONTACT_SCOPE = "lift_departure_only"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SupportContactContractError(ValueError):
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def support_surface_backend_id(
|
|
20
|
+
source_entity_id: str = QUALIFIED_SOURCE_ENTITY_ID,
|
|
21
|
+
) -> str:
|
|
22
|
+
source = str(source_entity_id).strip()
|
|
23
|
+
if not source:
|
|
24
|
+
raise SupportContactContractError("support_surface_entity_id_missing")
|
|
25
|
+
return _materialized_backend_id(source)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def prepare_lift_support_request(
|
|
29
|
+
path: Path | str,
|
|
30
|
+
*,
|
|
31
|
+
source_entity_id: str = QUALIFIED_SOURCE_ENTITY_ID,
|
|
32
|
+
) -> bool:
|
|
33
|
+
"""Annotate only the qualified lift-departure request with one support pair.
|
|
34
|
+
|
|
35
|
+
The v1.6 report profile preflights every phase before execution. The workpiece is
|
|
36
|
+
resting on the source fixture at the grasp pose, so the first request-local
|
|
37
|
+
attached-object scene must tolerate exactly that workpiece/support contact while
|
|
38
|
+
departing upward. Transfer/place remain untouched and therefore keep normal
|
|
39
|
+
collision checking.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
target = Path(path).expanduser().resolve()
|
|
43
|
+
if not target.name.endswith("-lift.request.json"):
|
|
44
|
+
return False
|
|
45
|
+
try:
|
|
46
|
+
payload = json.loads(target.read_text(encoding="utf-8"))
|
|
47
|
+
except (OSError, json.JSONDecodeError) as exc:
|
|
48
|
+
raise SupportContactContractError("support_contact_request_invalid") from exc
|
|
49
|
+
if not isinstance(payload, dict):
|
|
50
|
+
raise SupportContactContractError("support_contact_request_invalid")
|
|
51
|
+
raw_scene = payload.get("scene_contract")
|
|
52
|
+
if not isinstance(raw_scene, Mapping) or str(raw_scene.get("state") or "") != "attached":
|
|
53
|
+
return False
|
|
54
|
+
raw_workpiece = raw_scene.get("workpiece")
|
|
55
|
+
if not isinstance(raw_workpiece, Mapping):
|
|
56
|
+
raise SupportContactContractError("support_contact_workpiece_missing")
|
|
57
|
+
workpiece_id = str(raw_workpiece.get("id") or "").strip()
|
|
58
|
+
if not workpiece_id:
|
|
59
|
+
raise SupportContactContractError("support_contact_workpiece_missing")
|
|
60
|
+
support_id = support_surface_backend_id(source_entity_id)
|
|
61
|
+
if support_id == workpiece_id:
|
|
62
|
+
raise SupportContactContractError("support_contact_pair_invalid")
|
|
63
|
+
|
|
64
|
+
scene = dict(raw_scene)
|
|
65
|
+
scene.update(
|
|
66
|
+
{
|
|
67
|
+
"allow_support_contact": True,
|
|
68
|
+
"support_contact_scope": SUPPORT_CONTACT_SCOPE,
|
|
69
|
+
"support_surface_id": support_id,
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
payload["scene_contract"] = scene
|
|
73
|
+
temporary = target.with_suffix(target.suffix + ".tmp")
|
|
74
|
+
temporary.write_text(
|
|
75
|
+
json.dumps(payload, sort_keys=True, separators=(",", ":"), allow_nan=False),
|
|
76
|
+
encoding="utf-8",
|
|
77
|
+
)
|
|
78
|
+
temporary.replace(target)
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _validated_bool_rows(raw: object, *, size: int) -> list[list[bool]]:
|
|
83
|
+
if isinstance(raw, (str, bytes, bytearray)) or not isinstance(raw, Sequence):
|
|
84
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
85
|
+
rows: list[list[bool]] = []
|
|
86
|
+
for item in raw:
|
|
87
|
+
if isinstance(item, (str, bytes, bytearray)) or not isinstance(item, Sequence):
|
|
88
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
89
|
+
row = [bool(value) for value in item]
|
|
90
|
+
if len(row) != size:
|
|
91
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
92
|
+
rows.append(row)
|
|
93
|
+
if len(rows) != size:
|
|
94
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
95
|
+
return rows
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def allow_only_support_pair(
|
|
99
|
+
payload: Mapping[str, Any],
|
|
100
|
+
*,
|
|
101
|
+
workpiece_id: str,
|
|
102
|
+
support_surface_id: str,
|
|
103
|
+
) -> dict[str, Any]:
|
|
104
|
+
"""Return a full ACM preserving every existing entry and allowing one pair.
|
|
105
|
+
|
|
106
|
+
MoveIt replaces the ACM when a PlanningScene diff contains entry_names, so a sparse
|
|
107
|
+
two-name matrix would accidentally discard SRDF self-collision allowances. This
|
|
108
|
+
function starts from the full live ACM returned by /get_planning_scene, adds names
|
|
109
|
+
using MoveIt's default-entry semantics, and flips only the symmetric
|
|
110
|
+
workpiece/support pair to True.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
left = str(workpiece_id).strip()
|
|
114
|
+
right = str(support_surface_id).strip()
|
|
115
|
+
if not left or not right or left == right:
|
|
116
|
+
raise SupportContactContractError("support_contact_pair_invalid")
|
|
117
|
+
|
|
118
|
+
result = deepcopy(dict(payload))
|
|
119
|
+
raw_names = result.get("entry_names", [])
|
|
120
|
+
if isinstance(raw_names, (str, bytes, bytearray)) or not isinstance(raw_names, Sequence):
|
|
121
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
122
|
+
names = [str(value).strip() for value in raw_names]
|
|
123
|
+
if any(not value for value in names) or len(set(names)) != len(names):
|
|
124
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
125
|
+
rows = _validated_bool_rows(result.get("entry_values", []), size=len(names))
|
|
126
|
+
|
|
127
|
+
raw_default_names = result.get("default_entry_names", [])
|
|
128
|
+
raw_default_values = result.get("default_entry_values", [])
|
|
129
|
+
if (
|
|
130
|
+
isinstance(raw_default_names, (str, bytes, bytearray))
|
|
131
|
+
or not isinstance(raw_default_names, Sequence)
|
|
132
|
+
or isinstance(raw_default_values, (str, bytes, bytearray))
|
|
133
|
+
or not isinstance(raw_default_values, Sequence)
|
|
134
|
+
):
|
|
135
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
136
|
+
default_names = [str(value).strip() for value in raw_default_names]
|
|
137
|
+
default_values = [bool(value) for value in raw_default_values]
|
|
138
|
+
if len(default_names) != len(default_values) or any(not value for value in default_names):
|
|
139
|
+
raise SupportContactContractError("allowed_collision_matrix_invalid")
|
|
140
|
+
default_by_name = dict(zip(default_names, default_values))
|
|
141
|
+
|
|
142
|
+
def add_name(name: str) -> None:
|
|
143
|
+
if name in names:
|
|
144
|
+
return
|
|
145
|
+
if name in default_by_name:
|
|
146
|
+
new_values = [default_by_name[name]] * len(names)
|
|
147
|
+
else:
|
|
148
|
+
new_values = [default_by_name.get(existing, False) for existing in names]
|
|
149
|
+
for row, enabled in zip(rows, (*new_values, False)):
|
|
150
|
+
row.append(bool(enabled))
|
|
151
|
+
names.append(name)
|
|
152
|
+
rows.append([*new_values, False])
|
|
153
|
+
|
|
154
|
+
add_name(left)
|
|
155
|
+
add_name(right)
|
|
156
|
+
left_index = names.index(left)
|
|
157
|
+
right_index = names.index(right)
|
|
158
|
+
rows[left_index][right_index] = True
|
|
159
|
+
rows[right_index][left_index] = True
|
|
160
|
+
|
|
161
|
+
result["entry_names"] = names
|
|
162
|
+
result["entry_values"] = rows
|
|
163
|
+
result["default_entry_names"] = default_names
|
|
164
|
+
result["default_entry_values"] = default_values
|
|
165
|
+
return result
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from functools import wraps
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from .ros2.moveit_task_planner import MoveItTaskPlanner
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
VISUAL_MOVEIT_VELOCITY_SCALE = 0.12
|
|
10
|
+
VISUAL_MOVEIT_ACCELERATION_SCALE = 0.08
|
|
11
|
+
_PATCH_MARKER = "_devagent_smooth_motion_v162"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def install_smooth_motion_hotfix_v162() -> None:
|
|
15
|
+
"""Install conservative defaults for the task-specific visual MoveIt planner.
|
|
16
|
+
|
|
17
|
+
MoveItTaskPlanner is used only by the packaged task/report visual execution paths.
|
|
18
|
+
Those paths previously inherited 25% velocity and 25% acceleration. On the
|
|
19
|
+
qualified UR5e reference cell that made short pick/lift phases visually abrupt
|
|
20
|
+
and also reduced controller tracking margin on a real Gazebo/ros2_control stack.
|
|
21
|
+
|
|
22
|
+
v1.6.2 lowers only the planner defaults used when the caller did not explicitly
|
|
23
|
+
request a scale. Explicit planner scales remain authoritative. Collision checking,
|
|
24
|
+
endpoint tolerances, tracking tolerances, exact-Twin lineage, and real-execution
|
|
25
|
+
authority are not relaxed.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
current = MoveItTaskPlanner.__init__
|
|
29
|
+
if getattr(current, _PATCH_MARKER, False):
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
@wraps(current)
|
|
33
|
+
def patched(self: MoveItTaskPlanner, *args: Any, **kwargs: Any) -> None:
|
|
34
|
+
kwargs.setdefault("velocity_scale", VISUAL_MOVEIT_VELOCITY_SCALE)
|
|
35
|
+
kwargs.setdefault("acceleration_scale", VISUAL_MOVEIT_ACCELERATION_SCALE)
|
|
36
|
+
current(self, *args, **kwargs)
|
|
37
|
+
|
|
38
|
+
setattr(patched, _PATCH_MARKER, True)
|
|
39
|
+
MoveItTaskPlanner.__init__ = patched
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def install_support_contact_hotfix_v161() -> None:
|
|
5
|
+
"""Install the v1.6.1 report-test ROS runner without changing other ROS paths."""
|
|
6
|
+
|
|
7
|
+
from . import report_test_execution
|
|
8
|
+
from .ros2.support_contact_runner_v161 import SupportContactSubprocessRosRunner
|
|
9
|
+
|
|
10
|
+
if report_test_execution.SubprocessRosRunner is SupportContactSubprocessRosRunner:
|
|
11
|
+
return
|
|
12
|
+
report_test_execution.SubprocessRosRunner = SupportContactSubprocessRosRunner
|