(distance: number, direction: 'forward' | 'backward' = 'forward')
| 123 | |
| 124 | // Execute move command with odometry feedback |
| 125 | const executeMove = async (distance: number, direction: 'forward' | 'backward' = 'forward'): Promise<void> => { |
| 126 | // Validate odometry before starting |
| 127 | if (!isValidOdometry()) { |
| 128 | throw new Error('Invalid odometry data - cannot execute movement'); |
| 129 | } |
| 130 | |
| 131 | const startPosition = { ...odometry.pose.pose.position }; |
| 132 | const baseVelocity = direction === 'forward' ? LINEAR_VELOCITY : -LINEAR_VELOCITY; |
| 133 | const slowVelocity = direction === 'forward' ? LINEAR_VELOCITY_SLOW : -LINEAR_VELOCITY_SLOW; |
| 134 | |
| 135 | // Add minimum execution time to prevent immediate stops |
| 136 | const minExecutionTime = Math.max(500, (distance / Math.abs(LINEAR_VELOCITY)) * 1000 * 0.8); // 80% of theoretical time |
| 137 | const maxExecutionTime = (distance / Math.abs(LINEAR_VELOCITY)) * 1000 * 3; // 3x theoretical time as absolute max |
| 138 | const startTime = Date.now(); |
| 139 | |
| 140 | // Debug logging |
| 141 | console.log('Starting move:', { |
| 142 | distance, |
| 143 | direction, |
| 144 | startPosition, |
| 145 | baseVelocity, |
| 146 | minExecutionTime, |
| 147 | maxExecutionTime |
| 148 | }); |
| 149 | |
| 150 | // Send initial command to wake up the robot |
| 151 | console.log('Sending initial velocity command to wake robot...'); |
| 152 | publishVelocity({ |
| 153 | linear: new Vector3({ x: slowVelocity * 0.5, y: 0, z: 0 }), |
| 154 | angular: new Vector3({ x: 0, y: 0, z: 0 }) |
| 155 | }); |
| 156 | |
| 157 | // Wait a moment for robot to respond |
| 158 | await new Promise(resolve => setTimeout(resolve, 100)); |
| 159 | |
| 160 | // Log initial odometry state |
| 161 | console.log('Initial odometry state:', { |
| 162 | position: { |
| 163 | x: odometry.pose.pose.position.x.toFixed(3), |
| 164 | y: odometry.pose.pose.position.y.toFixed(3), |
| 165 | z: odometry.pose.pose.position.z.toFixed(3) |
| 166 | }, |
| 167 | orientation: { |
| 168 | x: odometry.pose.pose.orientation.x.toFixed(3), |
| 169 | y: odometry.pose.pose.orientation.y.toFixed(3), |
| 170 | z: odometry.pose.pose.orientation.z.toFixed(3), |
| 171 | w: odometry.pose.pose.orientation.w.toFixed(3) |
| 172 | }, |
| 173 | twist: { |
| 174 | linear: { |
| 175 | x: odometry.twist.twist.linear.x.toFixed(3), |
| 176 | y: odometry.twist.twist.linear.y.toFixed(3), |
| 177 | z: odometry.twist.twist.linear.z.toFixed(3) |
| 178 | } |
| 179 | } |
| 180 | }); |
| 181 | |
| 182 | return new Promise((resolve, reject) => { |
no test coverage detected