I was playing around with the simulator today (not the websim), and using the default robot.py project (the one in the docs), it seemed like no matter what I put the speed value to in the arcade drive, the robot went backwards off the SIM screen. The encoders were negative as well.
Any idea what I am doing wrong?
Thanks.
~Mr. R.^2
P.S. Thank you all for adding in the elements for this year’s game.
It is this one. I am working in auto as I have not yet installed pygame on the team’s programming machine yet.
!/usr/bin/env python3
"""
This is a good foundation to build your robot code on
"""
import wpilib
import wpilib.drive
class MyRobot(wpilib.TimedRobot):
def robotInit(self):
"""
This function is called upon program startup and
should be used for any initialization code.
"""
self.left_motor = wpilib.Spark(0)
self.right_motor = wpilib.Spark(1)
self.drive = wpilib.drive.DifferentialDrive(self.left_motor, self.right_motor)
self.stick = wpilib.Joystick(1)
self.timer = wpilib.Timer()
def autonomousInit(self):
"""This function is run once each time the robot enters autonomous mode."""
self.timer.reset()
self.timer.start()
def autonomousPeriodic(self):
"""This function is called periodically during autonomous."""
# Drive for two seconds
if self.timer.get() < 2.0:
self.drive.arcadeDrive(-0.5, 0) # Drive forwards at half speed
else:
self.drive.arcadeDrive(0, 0) # Stop robot
def teleopPeriodic(self):
"""This function is called periodically during operator control."""
self.drive.arcadeDrive(self.stick.getY(), self.stick.getX())
if __name__ == "__main__":
wpilib.run(MyRobot)
This seems to match the getting-started example, which doesn’t have a physics implementation associated with it. That means your physics.py is doing something wrong. Can you post your physics.py also – or maybe you might consider starting with one of the existing physics examples?
'''
Created on Sep 16, 2018
@author: Leko
'''
#
# See the documentation for more details on how this works
#
# The idea here is you provide a simulation object that overrides specific
# pieces of WPILib, and modifies motors/sensors accordingly depending on the
# state of the simulation. An example of this would be measuring a motor
# moving for a set period of time, and then changing a limit switch to turn
# on after that period of time. This can help you do more complex simulations
# of your robot code without too much extra effort.
#
import math
from pyfrc.physics import motor_cfgs, tankmodel
from pyfrc.physics.units import units
class PhysicsEngine(object):
'''
Simulates a motor moving something that strikes two limit switches,
one on each end of the track. Obviously, this is not particularly
realistic, but it's good enough to illustrate the point
'''
def __init__(self, physics_controller):
'''
:param physics_controller: `pyfrc.physics.core.PhysicsInterface` object
to communicate simulation effects to
'''
self.physics_controller = physics_controller
self.position = 0
# Change these parameters to fit your robot!
bumper_width = 3.25*units.inch
self.drivetrain = tankmodel.TankModel.theory(
motor_cfgs.MOTOR_CFG_CIM, # motor configuration
110*units.lbs, # robot mass
10.71, # drivetrain gear ratio
2, # motors per side
22*units.inch, # robot wheelbase
23*units.inch + bumper_width*2, # robot width
32*units.inch + bumper_width*2, # robot length
6*units.inch # wheel diameter
)
# Precompute the encoder constant
# -> encoder counts per revolution / wheel circumference
self.kEncoder = 360 / (0.5 * math.pi)
self.l_distance = 0
self.r_distance = 0
def update_sim(self, hal_data, now, tm_diff):
'''
Called when the simulation parameters for the program need to be
updated.
:param now: The current time as a float
:param tm_diff: The amount of time that has passed since the last
time that this function was called
'''
# Simulate the drivetrain
l_motor = hal_data['pwm'][1]['value']
r_motor = hal_data['pwm'][2]['value']
x, y, angle = self.drivetrain.get_distance(l_motor, r_motor, tm_diff)
self.physics_controller.distance_drive(x, y, angle)
# Update encoders
self.l_distance += self.drivetrain.l_velocity * tm_diff
self.r_distance += self.drivetrain.r_velocity * tm_diff
hal_data['encoder'][0]['count'] = int(self.l_distance * self.kEncoder)
hal_data['encoder'][1]['count'] = int(self.r_distance * self.kEncoder)
I’m not sure if this is the best place to post this, but has there been any work done, or any desire, to have a more powerful physics engine integrated into the robotpy simulator? I was thinking of working on this integration (box2D seems to be the one coming up the most often), but I don’t want to work on something that would not have much value for the robotpy community even right out of the gate.
Hey @warren.parsons, sounds like the sort of thing that would be appropriate in a new thread.
However, the idea of enhanced physics has definitely come up in the past, and we’ve done some work towards improving them over the years. I think the primary problem is just someone needs to do the work of (a) identifying a suitable engine and (b) actually doing the work.
@AmoryG has done some work with robotpy-websim, and has integrated Matter.js (a 2D rigid body physics engine) with it. Eventually I’d like for the websim to be our default so that it would be easier to build C++/Java backends for it, but I haven’t really taken the time to play with that yet. I’d encourage you to take a look and see if that meets your needs.
I am sorry for resurrecting an old post, but it seemed most relevant.
I can’t seem to find much documentation for the hal_data structure in the simulator. Specifically how would you access motor/controller values for a CAN motor; would you just swap ‘can’ for ‘pwm’ in the hal_data data structure access?
I would like to read more about this part of the simulator. Could someone point me to the best document describing it?